概念

Edit This Page

Ingress

Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。

Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

专用术语

在本文档中,您将看到一些有时在其他地方可互换使用的术语,这些术语可能会引起混淆。 本节试图澄清它们

Ingress 是什么?

通常,服务 和 Pod 具有仅能在集群网络内路由的 IP 地址。在边缘路由器结束的所有流量都被丢弃或转发到别处。从概念上讲,这可能看起来像:

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

Ingress 是允许连接到集群 Service 的规则集合。

    互联网
        |
   [ Ingress ]
   --|-----|--
   [ Services ]

它可以被配置为提供外部可访问的URL、负载均衡流量、终止SSL、提供基于名称的虚拟托管等等。 用户通过向 API 服务器 POST Ingress 资源来请求 Ingress。 Ingress 控制器 负责实现 Ingress,它通常使用负载均衡器,不过它也可以配置边缘路由器或其他前端,从而帮助用户以 HA 方式处理流量。

环境准备

在开始使用 Ingress 资源之前,有一些事情您应该了解。 Ingress 是 beta 资源,在 1.1 之前的任何 Kubernetes 版本中都不可用。 您需要一个 Ingress 控制器来满足 Ingress,否则简单地创建资源将不起作用。

GCE/Google Kubernetes Engine 是在主节点上部署 Ingress 控制器。 您可以在 Pod 中部署任意数量的自定义 Ingress 控制器。 您必须使用适当的类来注释每个 Ingress,如这里这里 所示。

一定要检查一下这个控制器的 beta 限制。 在 GCE/Google Kubernetes Engine 之外的环境中,需要将控制器部署 为 Pod。

Ingress 资源

最小的 Ingress 可能看起来像这样:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80

如果尚未配置 Ingress 控制器,则向 API 服务器 POST 操作将没有任何效果。

1-6 行: 与其他 Kubernetes 对象配置一样,Ingress 需要 apiVersionkind、和 metadata 字段。 有关使用配置文件的一般信息,请参见 部署应用配置容器管理资源ingress 配置重写

7-9 行: Ingress spec 具有配置负载均衡器或代理服务器所需的所有信息。 最重要的是,它包含与所有传入请求相匹配的规则列表。目前,Ingress 资源仅支持 HTTP 规则。

10-11 行: 每个 HTTP 规则都包含以下信息:主机(例如:foo.bar.com,在本例中默认为 * ),路径列表(例如:/testpath),每个路径都有一个关联的后端(test:80)。 在负载均衡器将流量路由到后端之前,主机和路径都必须与传入请求的规则匹配。

12-14 行: 如services doc中所述,后端(endpoint)是 “Service:port” 的组合。 Ingress 流量通常被直接发送到与后端相匹配的端点。

全局参数: 为了简单起见,Ingress 示例没有全局参数,有关资源的完整定义请参见 API引用。 您可以指定全局默认的后端,这样的话,当请求与 spec 中的路径不匹配时,就会被转发到 Ingress 控制器的默认后端。

Ingress 控制器

为了使 Ingress 资源正常工作,集群必须有 Ingress 控制器运行。 这不同于其他类型的控制器,它们通常作为 kube-controller-manager 二进制文件的一部分运行,并且通常作为集群创建的一部分自动启动。 请选择最适合您的集群的 Ingress 控制器,或者实现一个新的 Ingress 控制器。

Note: 注意: 请检查你的控制器的文档以找到其特定的支持策略。

在您开始之前

下面的文档描述了通过Ingress资源公开的一组跨平台特性。 理想情况下,所有 Ingress 控制器都应该满足这个规范,但是我们还没有。 我们现在支持并维护 GCEnginx 控制器。 如果您使用 F5 BIG-IP 控制器,请参考 使用 BIG-IP 控制器作为 Kubernetes Ingress 控制器

Note: 注意: 请您一定要查看您的控制器的特定文档,以便您能理解这些警告。

Ingress 的类型

单服务 Ingress

现有的 Kubernetes 概念允许您暴露单个 Service (查看 替代方案),同样您也可以使用 Ingress 来实现,具体方法是指定一个没有规则的 *默认后端(default backend)*。

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

如果您用 kubectl create -f创建它,你应该看到:

kubectl get ingress test-ingress
NAME           HOSTS     ADDRESS           PORTS     AGE
test-ingress   *         107.178.254.228   80        59s

其中 107.178.254.228 是 Ingress 控制器为该 Ingress 分配的 IP 该。

简单分列

如前所述,Kubernetes 中 Pod 的 IP 仅在集群网络上可见,所以我们需要在集群网络的边缘接收下行流量并将其代理到正确的端点。 这个组件通常是一个高可用的负载均衡器。Ingress 允许您将负载均衡器的数量降至最低。例如,这样的设置:

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

可能需要一个 Ingress 就像:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
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 describe ingress test
Name:             test
Namespace:        default
Address:          178.91.123.132
Default backend:  default-http-backend:80 (10.8.2.3:8080)
Rules:
  Host         Path  Backends
  ----         ----  --------
  foo.bar.com
               /foo   s1:80 (10.8.0.90:80)
               /bar   s2:80 (10.8.0.91:80)
Annotations:
  nginx.ingress.kubernetes.io/rewrite-target:  /
Events:
  Type     Reason  Age                From                     Message
  ----     ------  ----               ----                     -------
  Normal   ADD     22s                loadbalancer-controller  default/test

Ingress 控制器将提供实现特定的负载均衡器来满足 Ingress,只要 Service (s1s2) 存在。 当它这样做了,你会在地址栏看到负载平衡器的地址。

Note:

注意: 如果需要,你需要创建一个默认的 HTTP 后端 Service

基于名称的虚拟托管

基于名称的虚拟主机为同一个 IP 地址使用多个主机名。

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

下面的 Ingress 让后台的负载均衡器基于 Host header 路由请求。

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

默认后端: 一个没有规则的 Ingress,如前面部分所示,它将所有流量发送到单个默认后端。 通过指定一组规则*和*默认后端,您可以使用相同的技术来告诉负载均衡器在哪里找到网站的 404 页面。 如果 Ingress 中的主机与请求头中的主机不匹配,和/或没有路径与请求的 URL 匹配,则流量被路由到默认后端。

TLS

您可以通过指定包含TLS私钥和证书的 secret 来加密 Ingress。 目前,Ingress 只支持单个 TLS 端口,443,并假定 TLS 终止。 如果 Ingress 中的 TLS 配置部分指定了不同的主机,那么它们将根据通过 SNI TLS 扩展指定的主机名(如果 Ingress 控制器支持 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 控制器使用 TLS 保护从客户端到负载均衡器的通道:

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

注意,各种 Ingress 控制器所支持的 TLS 功能之间存在间隙。请参阅有关文件 nginxGCE, 或任何其他平台特定的 Ingress 控制器,以了解 TLS 如何在您的环境中工作。

负载均衡

Ingress控制器使用一些适用于所有 Ingress 的负载均衡策略设置进行自举,例如负载平衡算法、后端权重方案等。 更高级的负载平衡概念(例如,持久会话、动态权重)尚未通过Ingress公开。 您仍然可以通过 Service 负载均衡器 获得这些特性。 随着时间的推移,我们计划将跨平台应用的负载平衡模式提取到 Ingress 资源中。

值得注意的是,即使健康检查不是通过 Ingress 直接暴露的,但是在 Kubernetes 中存在并行概念,比如 就绪检查,它允许您实现相同的最终结果。 请检查控制器说明文档,以了解他们是怎样实现健康检查的 ( nginxGCE)。

更新 Ingress

假设您想向现有的 Ingress 中添加新主机,可以通过编辑资源来更新它:

kubectl describe ingress test
Name:             test
Namespace:        default
Address:          178.91.123.132
Default backend:  default-http-backend:80 (10.8.2.3:8080)
Rules:
  Host         Path  Backends
  ----         ----  --------
  foo.bar.com
               /foo   s1:80 (10.8.0.90:80)
Annotations:
  nginx.ingress.kubernetes.io/rewrite-target:  /
Events:
  Type     Reason  Age                From                     Message
  ----     ------  ----               ----                     -------
  Normal   ADD     35s                loadbalancer-controller  default/test
kubectl edit ingress test

这应该弹出一个编辑器与现有的 yaml,修改它来增加新的主机:

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
..

保存 yaml 将更新 API 服务器中的资源,这应该会告诉 Ingress 控制器来重新配置负载均衡器。

kubectl describe ingress test
Name:             test
Namespace:        default
Address:          178.91.123.132
Default backend:  default-http-backend:80 (10.8.2.3:8080)
Rules:
  Host         Path  Backends
  ----         ----  --------
  foo.bar.com
               /foo   s1:80 (10.8.0.90:80)
  bar.baz.com
               /foo   s2:80 (10.8.0.91:80)
Annotations:
  nginx.ingress.kubernetes.io/rewrite-target:  /
Events:
  Type     Reason  Age                From                     Message
  ----     ------  ----               ----                     -------
  Normal   ADD     45s                loadbalancer-controller  default/test

您可以通过 kubectl replace -f 命令调用修改后的 Ingress yaml 文件来获得同样的结果。

跨可用区失败

用于跨故障域传播流量的技术在云提供商之间是不同的。详情请查阅相关 Ingress 控制器的文档。 有关在联邦集群中部署 Ingress 的详细信息,请参阅联邦 文档

未来的工作

*各种 HTTPS/TLS 模式的支持(例如:SNI、重加密) *通过声明请求IP或主机名 *合并 L4 和 L7 Ingress *更多 Ingress 控制器

请跟踪 L7 and Ingress proposal以了解关于资源演化的更多细节,以及 Ingress repository 以了解关于各种 Ingress 控制器演进的更多细节。

替代方案

不直接使用 Ingress 资源,也有多种方法暴露 Service:

反馈