K8s Ingress

Table of Contents

Ingress 是管理访问集群外部服务的 API 对象,一般指 HTTP。

Ingress 可以提供负载均衡,SSL 终端和基于名称的虚拟主机(name-based virtual hosting)。

_tips_:Vhosts 分为两种情况,一种是基于 IP 的(IP-based virtual hosting),一台机器上运行多个网站,不同的网站有不同的 IP 地址; 另外一种是基于名称的,即多个网站有相同的 IP 地址,用名称来隔离 1

术语

1 什么是 Ingress ?

通常,服务和 pods 拥有的 IPs 只能在集群网络路由。所有的在边缘路由器结束的流量会被丢弃或者转发到别的地方。就像下面这样:

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

Ingress 提供了一系列的规则允许入站连接到达集群服务。

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

它可以配置为提供外部服务的 URLs,流量负载均衡,SSL 终止,提供具名虚拟主机等等。用户使用时向 ingress API 服务器提交 POST 请求,由 Ingress controller 完成这一工作,通常用作负载均衡,尽管它也可以配置你的边缘路由或者处理流量高可用。

2 先决条件

在你使用 Ingress 资源之前,你需要了解一些事情。Ingress 是一个 beta 资源,在任何 K8s 发布 1.1 之前都是不可用的。你需要一个 Ingress 控制器来满足 Ingress,简单的创建资源将不起作用。

GCE/谷歌 K8s 引擎在 master 上部署了一个 ingress 控制器。你可以在 pod 上部署任意数量的自定义 ingress 控制器。你必须在每个 ingress 添加适合的注解,类似 这里这里

确保你阅读过这个控制器的 beta limitation,在 GCE/谷歌 K8s 引擎之外的环境中,你需要部署一个控制器。

3 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 没用。

1-6 行 :和其他 K8s 的配置一样,Ingress 需要 apiVersion~,~kindmetadata 字段。

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

10-11 行 :每个 http 规则包含下面这些信息:一个域名(比如:foo.bar.com,在这个例子中默认是 *),关联后端的路径列表(一对一,这个例子中是 /testpath 映射到 test:80 )。

12-14 行 :后端服务和端口组合在 服务文档 中有描述,Ingress 流量通常会直接发送到匹配的后端。

全局参数 :为了演示一个精简的例子所有没有设置全局参数,查看 API文档 查看完整的定义。可以指定一个全局默认的后端,在请求规则不匹配的情况下,会默认发送到 default 后端。

4 Ingress controllers

为了使 ingress 资源生效,集群必须有一个 Ingress controller 运行。这和其他类型的控制器不用,通常作为 kube-controller-manager 二进制的一部分来运行,跟随集群一直启动。选择一个合适你集群的 ingress controller 实现,或者你自己实现一个。

5 开始之前

以下文档介绍了一套 Ingress 资源跨平台资源暴露的特性,在理想情况下,所有的 Ingress 控制器应该满足这个规范,但是我们还没有实现。 我们当前支持和维护了 GCE 和 nginx 控制器。如果你使用了 F5 BIG-IP 控制器,查看 使用 BIG-IP 控制器作为 K8s Ingress 控制器

6 Ingress 类型

6.1 单个服务

现有的 K8s 概念允许你暴露单个服务(查看备选方案),不过你也可以通过 Ingress 来实现,通过指定一个没有规则的默认后端服务。

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

如果你使用 kubectl create -f 创建的,你可以看到:

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

107.178.254.228 是 Ingress 控制器分配的 IP,~RULE~ 列表示了所有的流量都直接发送到 BACKEND 列表下的 K8s 服务。

6.2 简单的扇出(fanout)

如前所述,在 K8s 中的 pods 的 IPs 只能在集群内部访问,所以我们需要在边缘获取流量并且代理到正确的端点。这个组件通常用来做高可用负载均衡。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 get ing
NAME      RULE          BACKEND   ADDRESS
test      -
          foo.bar.com
          /foo          s1:80
          /bar          s2:80

只要服务(s1,s2)存在,Ingress 控制器会提供满足 Ingress 的特定负载均衡器。当它这样做时,在最后一列,你会看到均衡器的地址。

6.3 基于名称的 vhost

基于名称的 vhosts 为相同的 IP 地址提供不同的 host 名称。

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 页面。

6.4 TLS

通过指定包含 TLS 私有 key 和证书的 secret 可以提高 Ingress 的安全。当前 Ingress 只支持单一的 TLS 端口,443,并假定 TLS termination。如果 TLS 配置小节指定了不同的 hosts, 它们将根据通过 SNI TLS 扩展指定的主机名在同一端口进行多路复用(前提是 Ingress 控制器支持 SNI)。TLS 秘钥必须包含名为 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 中引用这个密钥将告诉 Ingress 使用 TLS 从客户端保护负载均衡器:

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

要注意在不同的 Ingress 控制器支持的 TLS 功能之间的差距。请查看 nginx,GCE 和其他平台特定的 Ingress 控制器文档,以便更好的理解 TLS 在你的环境中是如何生效的。

6.5 负载均衡

一个 Ingress 控制器是一些负载均衡策略设置的引导,可以应用到所有的 Ingress 上,比如负载均衡算法,后端权重方案,等等。更多的高级负载均衡概念(比如:回话保持、动态权重等),还没有通过 Ingress 暴露。 你仍旧可以通过 service loadbalancer 得到这些特性。随着时间的漂移,我们会逐渐的将这些适用于跨平台的负载均衡提取到 Ingress 资源中。

值得注意的是健康监测即便不通过 Ingress 暴露出来,K8s 已经存在的并行的概念例如 readiness 探针 也能达到相同的效果。请查看控制器具体的文档去查看他们是怎么处理健康监测的(nginx,GCE)。

7 更新 Ingress

你已经添加了一个 Ingress,现在你可以编辑它:

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

保存 yaml 文件会向 API 服务器更新资源,将会告诉 Ingress 控制器重新配置负载均衡器。

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

调用 kubectl replace -f 在一个修改好的 Ingress yaml 文件上也可以达到相同的效果。

8 跨可用区域失败

云服务提供商之间的跨故障域传播流量的技术不同,请详细查询 Ingress 控制器的文档,有关在联合群集中部署 Ingress 的详细信息,请参阅 联合文档

9 未来的工作

  • 支持各种 HTTPS/TLS 模式
  • 通过 claims 请求 IP 或者主机名
  • 合并 L4 和 L7 Ingress
  • 更多的 Ingress 控制器

9.1 备选方案

不直接涉及 Ingress 资源你可以有多重方式暴露服务:

Footnotes:

Date: 2018-06-04 11:28:27

Author: JerryZhang