Ingress
在本篇文章中你将会看到一些在其他地方被交叉使用的术语,为了防止产生歧义,我们首先来澄清下。
    节点:Kubernetes 集群中的服务器;
    集群:Kubernetes 管理的一组服务器集合;
    边界路由器:为局域网和 Internet 路由数据包的路由器,执行防火墙保护局域网络;
    集群网络:遵循 Kubernetes网络模型 实现集群内的通信的具体实现,比如 flannelOVS
    服务:Kubernetes 的服务 (Service) 是使用标签选择器标识的一组 pod Service。 除非另有说明,否则服务的虚拟 IP 仅可在集群内部访问。

什么是 Ingress?

通常情况下,service 和 pod 的 IP 仅可在集群内部访问。集群外部的请求需要通过负载均衡转发到 service 在 Node 上暴露的 NodePort 上,然后再由 kube-proxy 通过边缘路由器 (edge router) 将其转发给相关的 Pod 或者丢弃。如下图所示
1
internet
2
|
3
------------
4
[Services]
Copied!
而 Ingress 就是为进入集群的请求提供路由规则的集合,如下图所示
image-20190316184154726
Ingress 可以给 service 提供集群外部访问的 URL、负载均衡、SSL 终止、HTTP 路由等。为了配置这些 Ingress 规则,集群管理员需要部署一个 Ingress controller,它监听 Ingress 和 service 的变化,并根据规则配置负载均衡并提供访问入口。

Ingress 格式

1
apiVersion: extensions/v1beta1
2
kind: Ingress
3
metadata:
4
name: test-ingress
5
spec:
6
rules:
7
- http:
8
paths:
9
- path: /testpath
10
backend:
11
serviceName: test
12
servicePort: 80
Copied!
每个 Ingress 都需要配置 rules,目前 Kubernetes 仅支持 http 规则。上面的示例表示请求 /testpath 时转发到服务 test 的 80 端口。

API 版本对照表

Kubernetes 版本
Extension 版本
v1.5-v1.17
extensions/v1beta1
v1.8-v1.18
networking.k8s.io/v1beta1
v1.19+
networking.k8s.io/v1

Ingress 类型

根据 Ingress Spec 配置的不同,Ingress 可以分为以下几种类型:

单服务 Ingress

单服务 Ingress 即该 Ingress 仅指定一个没有任何规则的后端服务。
1
apiVersion: extensions/v1beta1
2
kind: Ingress
3
metadata:
4
name: test-ingress
5
spec:
6
backend:
7
serviceName: testsvc
8
servicePort: 80
Copied!
注:单个服务还可以通过设置 Service.Type=NodePort 或者 Service.Type=LoadBalancer 来对外暴露。

多服务的 Ingress

路由到多服务的 Ingress 即根据请求路径的不同转发到不同的后端服务上,比如
1
foo.bar.com -> 178.91.123.132 -> / foo s1:80
2
/ bar s2:80
Copied!
可以通过下面的 Ingress 来定义:
1
apiVersion: extensions/v1beta1
2
kind: Ingress
3
metadata:
4
name: test
5
spec:
6
rules:
7
- host: foo.bar.com
8
http:
9
paths:
10
- path: /foo
11
backend:
12
serviceName: s1
13
servicePort: 80
14
- path: /bar
15
backend:
16
serviceName: s2
17
servicePort: 80
Copied!
使用 kubectl create -f 创建完 ingress 后:
1
$ kubectl get ing
2
NAME RULE BACKEND ADDRESS
3
test -
4
foo.bar.com
5
/foo s1:80
6
/bar s2:80
Copied!

虚拟主机 Ingress

虚拟主机 Ingress 即根据名字的不同转发到不同的后端服务上,而他们共用同一个的 IP 地址,如下所示
1
foo.bar.com --| |-> foo.bar.com s1:80
2
| 178.91.123.132 |
3
bar.foo.com --| |-> bar.foo.com s2:80
Copied!
下面是一个基于 Host header 路由请求的 Ingress:
1
apiVersion: extensions/v1beta1
2
kind: Ingress
3
metadata:
4
name: test
5
spec:
6
rules:
7
- host: foo.bar.com
8
http:
9
paths:
10
- backend:
11
serviceName: s1
12
servicePort: 80
13
- host: bar.foo.com
14
http:
15
paths:
16
- backend:
17
serviceName: s2
18
servicePort: 80
Copied!
注:没有定义规则的后端服务称为默认后端服务,可以用来方便的处理 404 页面。

TLS Ingress

TLS Ingress 通过 Secret 获取 TLS 私钥和证书 (名为 tls.crttls.key),来执行 TLS 终止。如果 Ingress 中的 TLS 配置部分指定了不同的主机,则它们将根据通过 SNI TLS 扩展指定的主机名(假如 Ingress controller 支持 SNI)在多个相同端口上进行复用。
定义一个包含 tls.crttls.key 的 secret:
1
apiVersion: v1
2
data:
3
tls.crt: base64 encoded cert
4
tls.key: base64 encoded key
5
kind: Secret
6
metadata:
7
name: testsecret
8
namespace: default
9
type: Opaque
Copied!
Ingress 中引用 secret:
1
apiVersion: extensions/v1beta1
2
kind: Ingress
3
metadata:
4
name: no-rules-map
5
spec:
6
tls:
7
- secretName: testsecret
8
backend:
9
serviceName: s1
10
servicePort: 80
Copied!
注意,不同 Ingress controller 支持的 TLS 功能不尽相同。 请参阅有关 nginxGCE 或任何其他 Ingress controller 的文档,以了解 TLS 的支持情况。

更新 Ingress

可以通过 kubectl edit ing name 的方法来更新 ingress:
1
$ kubectl get ing
2
NAME RULE BACKEND ADDRESS
3
test - 178.91.123.132
4
foo.bar.com
5
/foo s1:80
6
$ kubectl edit ing test
Copied!
这会弹出一个包含已有 IngressSpec yaml 文件的编辑器,修改并保存就会将其更新到 kubernetes API server,进而触发 Ingress Controller 重新配置负载均衡:
1
spec:
2
rules:
3
- host: foo.bar.com
4
http:
5
paths:
6
- backend:
7
serviceName: s1
8
servicePort: 80
9
path: /foo
10
- host: bar.baz.com
11
http:
12
paths:
13
- backend:
14
serviceName: s2
15
servicePort: 80
16
path: /foo
17
..
Copied!
更新后:
1
$ kubectl get ing
2
NAME RULE BACKEND ADDRESS
3
test - 178.91.123.132
4
foo.bar.com
5
/foo s1:80
6
bar.baz.com
7
/foo s2:80
Copied!
当然,也可以通过 kubectl replace -f new-ingress.yaml 命令来更新,其中 new-ingress.yaml 是修改过的 Ingress yaml。

Ingress Controller

Ingress 正常工作需要集群中运行 Ingress Controller。Ingress Controller 与其他作为 kube-controller-manager 中的在集群创建时自动启动的 controller 成员不同,需要用户选择最适合自己集群的 Ingress Controller,或者自己实现一个。
Ingress Controller 以 Kubernetes Pod 的方式部署,以 daemon 方式运行,保持 watch Apiserver 的 /ingress 接口以更新 Ingress 资源,以满足 Ingress 的请求。比如可以使用 Nginx Ingress Controller
1
helm install stable/nginx-ingress --name nginx-ingress --set rbac.create=true
Copied!
其他 Ingress Controller 还有:

Ingress Class

在 Ingress Class 之前,要给 Ingress 选择具体的 Controller,需要加上特殊的 annotation(如 kubernetes.io/ingress.class: nginx)。而有了 IngressClass,集群管理员就可以预先创建好支持的 Ingress 类型,并可以 Ingress 中直接引用。
1
apiVersion: networking.k8s.io/v1
2
kind: IngressClass
3
metadata:
4
name: external-lb
5
spec:
6
controller: example.com/ingress-controller
7
parameters:
8
apiGroup: k8s.example.com
9
kind: IngressParameters
10
name: external-lb
Copied!

参考文档

最近更新 1mo ago