1. Ingress

提示: 本文对 Ingress 进行基础性的介绍,更深入的细节请访问 Ingress 专题

Ingress 是提供了除 Service 之外的另一种从 Kubernetes 集群外部访问集群内部服务的解决方案。

Ingress 是 Kubernetes 集群中的一种 API 资源,只是一种资源配置,本身并不会提供服务。实际功能由 ingress-controller 提供,一般是以 hostNetwork 的方式部署运行,监听 80/443 端口,以域名的虚拟机方式对外提供7层的代理服务。常见的 ingress-controller 有 nginx-ingress-controlle 、Traefik-ingress-controller等。

通常情况下,service 和 pod 仅可在集群内部网络中通过IP地址访问。所有到达边界路由器的流量或被丢弃或被转发到其他地方。从概念上讲,可能像下面这样:

    internet
        |
  ------------
  [ Services ]

Ingress是授权入站连接到达集群服务的规则集合。

    internet
        |
   [ Ingress ]
   --|-----|--
   [ Services ]

你可以给 Ingress 配置提供外部可访问的 URL、负载均衡、SSL、基于名称的虚拟主机等。用户通过POST Ingress资源到 API server 的方式来请求 ingress。 Ingress controller负责实现Ingress,通常使用负载平衡器,它还可以配置边界路由和其他前端,这有助于以 HA 方式处理流量。

1.1. Ingress Spec

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  rules:
  - host: test-ingress.mydomain.com
    http:
      paths: /test
      - backend:
          serviceName: test-ingress
          servicePort: 80

1.1.1. rules

spec.rules 定义了一个列表,每个列表项是一个包含一套相关访问规则配置。

  • rules.host : 定义服务的域名,和 nginx 的虚拟机主机功能类似,通过域名来区分后端的服务。
  • rules.http : 定义路由及后端资源。
  • rules.http.paths : 定义路由或 path,可以类比 nginx 的 Location 配置项。
  • rules.http.paths.backend : 定义路由转发的后端服务,详见 spec.backend

1.1.2. backend

  backend:
    serviceName: test-ingress
        servicePort: 80

spec.backend 定义当前 host 服务的后端。

  • serviceName 是 Kubernetes 的 Service 资源的名称,这里只是通过 Service 名称获取到后端的 Endpoints 列表,路由请求代理时是 Ingress-controller 直接转发给 Pod,而不是转发给 Service 的 ClusterIP。
  • servicePort: 服务端口,默认是80。该端口是由 Ingress-controller 启动参数配置的监听端口,其他未监听的端口配置是无效的。

1.1.3. TLS

你可以通过指定包含TLS私钥和证书的 secret 来加密 Ingress。 目前,Ingress 仅支持单个TLS端口443,并假定 TLS termination。 如果 Ingress 中的 TLS 配置部分指定了不同的主机,则它们将根据通过 SNI TLS 扩展指定的主机名(假如 Ingress controller 支持 SNI)在多个相同端口上进行复用。 TLS secret 中必须包含名为 tls.crttls.key 的密钥,这里面包含了用于 TLS 的证书和私钥,例如:

apiVersion: v1
data:
  tls.crt: base64 encoded cert
  tls.key: base64 encoded key
kind: Secret
metadata:
  name: testsecret
  namespace: default
type: Opaque

在 Ingress 中引用这个 secret 将通知 Ingress controller 使用 TLS 加密从将客户端到 loadbalancer 的 channel:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: no-rules-map
spec:
  tls:
    - secretName: testsecret
  backend:
    serviceName: s1
    servicePort: 80

如果配置 tls 的 Ingress 未指定具体 rules 时,这该 tls 是全局的,或者说是默认的。在有明确的 rules 时,会优先使用其ingress 中配置的 tls。

请注意,各种 Ingress controller 支持的 TLS 功能之间存在差距。 请参阅有关 nginxGCE 或任何其他平台特 定Ingress controller 的文档,以了解 TLS 在你的环境中的工作原理。

Ingress controller 启动时附带一些适用于所有 Ingress 的负载平衡策略设置,例如负载均衡算法,后端权重方案等。更高级的负载平衡概念(例如持久会话,动态权重)尚未在 Ingress 中公开。 你仍然可以通过 service loadbalancer 获取这些功能。 随着时间的推移,我们计划将适用于跨平台的负载平衡模式加入到 Ingress 资源中。

还值得注意的是,尽管健康检查不直接通过 Ingress 公开,但 Kubernetes 中存在并行概念,例如准备探查,可以使你达成相同的最终结果。 请查看特定控制器的文档,以了解他们如何处理健康检查 (nginxGCE)。

1.2. 扩展阅读

1.2.1. 术语

在本篇文章中你将会看到一些在其他地方被交叉使用的术语,为了防止产生歧义,我们首先来澄清下。

  • 节点:Kubernetes 集群中的一台物理机或者虚拟机。
  • 集群:位于 Internet 防火墙后的节点,这是 kubernetes 管理的主要计算资源。
  • 边界路由器:为集群强制执行防火墙策略的路由器。 这可能是由云提供商或物理硬件管理的网关。
  • 集群网络:一组逻辑或物理链接,可根据 Kubernetes网络模型实现群集内的通信。 集群网络的实现包括 Overlay 模型的 flannel 和基于SDN 的 OVS。
  • 服务:使用标签选择器标识一组 pod 成为的 Kubernetes 服务。 除非另有说明,否则服务假定在集群网络内仅可通过虚拟 IP 访问。

1.2.2. 先决条件

在使用 Ingress resource之前,有必要先了解下面几件事情。Ingress是beta版本的resource,在kubernetes1.1之前还没有。你需要一个Ingress Controller来实现Ingress,单纯的创建一个Ingress没有任何意义。

GCE/GKE会在master节点上部署一个ingress controller。你可以在一个pod中部署任意个自定义的ingress controller。你必须正确地annotate每个ingress,比如 运行多个ingress controller 和 关闭glbc。

确定你已经阅读了Ingress controller的 beta版本限制。在非GCE/GKE的环境中,你需要在pod中部署一个controller

1.2.3. Ingress controllers

为了使 Ingress 正常工作,集群中必须运行 Ingress controller。 这与其他类型的控制器不同,其他类型的控制器通常作为kube-controller-manager 二进制文件的一部分运行,在集群启动时自动启动。 你需要选择最适合自己集群的Ingress controller或者自己实现一个。

1.2.4. 在你开始前

以下文档描述了 Ingress 资源中公开的一组跨平台功能。 理想情况下,所有的 Ingress controller 都应该符合这个规范,但是我们还没有实现。 GCE 和 nginx 控制器的文档分别在这里这里。如果您使用 F5 BIG-IP controller, 请参看这里. 确保您查看控制器特定的文档,以便您了解每个文档的注意事项。

1.2.5. 跨可用域故障

在不同云供应商之间,跨故障域的流量传播技术有所不同。 有关详细信息,请查看相关 Ingress controller 的文档。 有关在federation 集群中部署 Ingress 的详细信息,请参阅 federation 文档。

1.2.6. 未来计划

  • 多样化的 HTTPS/TLS 模型支持(如SNI,re-encryption)
  • 通过声明来请求 IP 或者主机名
  • 结合 L4 和 L7 Ingress
  • 更多的 Ingress controller

请跟踪 L7 和 Ingress 的 proposal,了解有关资源演进的更多细节,以及Ingress repository,了解有关各种 Ingress controller 演进的更多详细信息。

1.2.7. 替代方案

你可以通过很多种方式暴露service而不必直接使用ingress:

1.2.8. 基于名称的虚拟主机

Name-based的虚拟主机在同一个IP地址下拥有多个主机名。

foo.bar.com --|                 |-> foo.bar.com s1:80
              | 178.91.123.132  |
bar.foo.com --|                 |-> bar.foo.com s2:80

下面这个 ingress 说明基于 Host header的后端loadbalancer的路由请求:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - backend:
          serviceName: s1
          servicePort: 80
  - host: bar.foo.com
    http:
      paths:
      - backend:
          serviceName: s2
          servicePort: 80

默认backend:一个没有 rule 的 ingress,如前面章节中所示,所有流量都将发送到一个默认backend。你可以用该技巧通知 loadbalancer 如何找到你网站的 404 页面,通过制定一些列 rule 和一个默认 backend 的方式。如果请求 header 中的 host 不能跟 ingress 中的 host 匹配,并且/或请求的 URL 不能与任何一个 path 匹配,则流量将路由到你的默认 backend。

1.2.9. Ingress类型

单Service Ingress

Kubernetes 中已经存在一些概念可以暴露单个 service(查看替代方案),但是你仍然可以通过 Ingress 来实现,通过指定一个没有 rule 的默认backend的方式。

ingress.yaml定义文件:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  backend:
    serviceName: testsvc
    servicePort: 80

使用kubectl create -f命令创建,然后查看ingress:

$ kubectl get ing
NAME                RULE          BACKEND        ADDRESS
test-ingress        -             testsvc:80     107.178.254.228

107.178.254.228就是 Ingress controller 为了实现 Ingress 而分配的 IP 地址。RULE 列表示所有发送给该 IP 的流量都被转发到了 BACKEND 所列的 Kubernetes service 上。

简单展开

如前面描述的那样,kubernetes pod 中的 IP 只在集群网络内部可见,我们需要在边界设置一个东西,让它能够接收 ingress 的流量并将它们转发到正确的端点上。这个东西一般是高可用的 loadbalancer。使用 Ingress 能够允许你将 loadbalancer 的个数降低到最少,例如,假如你想要创建这样的一个设置:

foo.bar.com -> 178.91.123.132 -> / foo    s1:80
                                 / bar    s2:80

你需要一个这样的ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: s1
          servicePort: 80
      - path: /bar
        backend:
          serviceName: s2
          servicePort: 80

使用kubectl create -f创建完 ingress 后:

$ kubectl get ing
NAME      RULE          BACKEND   ADDRESS
test      -
          foo.bar.com
          /foo          s1:80
          /bar          s2:80

只要服务(s1,s2)存在,Ingress controller 就会将提供一个满足该 Ingress 的特定 loadbalancer 实现。 这一步完成后,您将在 Ingress 的最后一列看到 loadbalancer 的地址。

1.2.10. 更新Ingress

假如你想要向已有的 ingress 中增加一个新的 Host,你可以编辑和更新该 ingress:

注意: 更新 Ingress 配置不需要重启 Ingress-controller,Ingress-controller 会 watch 配置的变化自动重载配置文件。

$ kubectl get ing
NAME      RULE          BACKEND   ADDRESS
test      -                       178.91.123.132
          foo.bar.com
          /foo          s1:80
$ kubectl edit ing test

这会弹出一个包含已有的 yaml 文件的编辑器,修改它,增加新的 Host 配置。

spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - backend:
          serviceName: s1
          servicePort: 80
        path: /foo
  - host: bar.baz.com
    http:
      paths:
      - backend:
          serviceName: s2
          servicePort: 80
        path: /foo
..

保存它会更新 API server 中的资源,这会触发 ingress controller 重新配置 loadbalancer。

$ kubectl get ing
NAME      RULE          BACKEND   ADDRESS
test      -                       178.91.123.132
          foo.bar.com
          /foo          s1:80
          bar.baz.com
          /foo          s2:80

在一个修改过的 ingress yaml 文件上调用 kubectl replace -f 命令一样可以达到同样的效果。

1.3. 参考

Copyright © 温玉 2021 | 浙ICP备2020032454号 all right reserved,powered by Gitbook该文件修订时间: 2022-01-09 10:28:35

results matching ""

    No results matching ""