Ingress
在本篇文章中你將會看到一些在其他地方被交叉使用的術語,爲了防止產生歧義,我們首先來澄清下。
節點:Kubernetes 集群中的服務器;
集群:Kubernetes 管理的一組服務器集合;
邊界路由器:爲局域網和 Internet 路由數據包的路由器,執行防火牆保護局域網絡;
服務:Kubernetes 的服務 (Service) 是使用標籤選擇器標識的一組 pod Service。 除非另有說明,否則服務的虛擬 IP 僅可在集群內部訪問。
什麼是 Ingress?
通常情況下,service 和 pod 的 IP 僅可在集群內部訪問。集群外部的請求需要通過負載均衡轉發到 service 在 Node 上暴露的 NodePort 上,然後再由 kube-proxy 通過邊緣路由器 (edge router) 將其轉發給相關的 Pod 或者丟棄。如下圖所示
internet
|
------------
[Services]
而 Ingress 就是爲進入集群的請求提供路由規則的集合,如下圖所示

Ingress 可以給 service 提供集群外部訪問的 URL、負載均衡、SSL 終止、HTTP 路由等。爲了配置這些 Ingress 規則,集群管理員需要部署一個 Ingress controller,它監聽 Ingress 和 service 的變化,並根據規則配置負載均衡並提供訪問入口。
Ingress 格式
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
rules:
- http:
paths:
- path: /testpath
backend:
serviceName: test
servicePort: 80
每個 Ingress 都需要配置 rules
,目前 Kubernetes 僅支持 http 規則。上面的示例表示請求 /testpath
時轉發到服務 test
的 80 端口。
API 版本對照表
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 僅指定一個沒有任何規則的後端服務。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
backend:
serviceName: testsvc
servicePort: 80
注:單個服務還可以通過設置
Service.Type=NodePort
或者Service.Type=LoadBalancer
來對外暴露。
多服務的 Ingress
路由到多服務的 Ingress 即根據請求路徑的不同轉發到不同的後端服務上,比如
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
虛擬主機 Ingress
虛擬主機 Ingress 即根據名字的不同轉發到不同的後端服務上,而他們共用同一個的 IP 地址,如下所示
foo.bar.com --| |-> foo.bar.com s1:80
| 178.91.123.132 |
bar.foo.com --| |-> bar.foo.com s2:80
下面是一個基於 Host header 路由請求的 Ingress:
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
注:沒有定義規則的後端服務稱爲默認後端服務,可以用來方便的處理 404 頁面。
TLS Ingress
TLS Ingress 通過 Secret 獲取 TLS 私鑰和證書 (名爲 tls.crt
和 tls.key
),來執行 TLS 終止。如果 Ingress 中的 TLS 配置部分指定了不同的主機,則它們將根據通過 SNI TLS 擴展指定的主機名(假如 Ingress controller 支持 SNI)在多個相同端口上進行復用。
定義一個包含 tls.crt
和 tls.key
的 secret:
apiVersion: v1
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
kind: Secret
metadata:
name: testsecret
namespace: default
type: Opaque
Ingress 中引用 secret:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: no-rules-map
spec:
tls:
- secretName: testsecret
backend:
serviceName: s1
servicePort: 80
注意,不同 Ingress controller 支持的 TLS 功能不盡相同。 請參閱有關 nginx,GCE 或任何其他 Ingress controller 的文檔,以瞭解 TLS 的支持情況。
更新 Ingress
可以通過 kubectl edit ing name
的方法來更新 ingress:
$ kubectl get ing
NAME RULE BACKEND ADDRESS
test - 178.91.123.132
foo.bar.com
/foo s1:80
$ kubectl edit ing test
這會彈出一個包含已有 IngressSpec yaml 文件的編輯器,修改並保存就會將其更新到 kubernetes API server,進而觸發 Ingress Controller 重新配置負載均衡:
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
..
更新後:
$ 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 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:
helm install stable/nginx-ingress --name nginx-ingress --set rbac.create=true
其他 Ingress Controller 還有:
traefik ingress 提供了一個 Traefik Ingress Controller 的實踐案例
kubernetes/ingress-nginx 提供了一個詳細的 Nginx Ingress Controller 示例
kubernetes/ingress-gce 提供了一個用於 GCE 的 Ingress Controller 示例
Ingress Class
在 Ingress Class 之前,要給 Ingress 選擇具體的 Controller,需要加上特殊的 annotation(如 kubernetes.io/ingress.class: nginx)。而有了 IngressClass,集群管理員就可以預先創建好支持的 Ingress 類型,並可以 Ingress 中直接引用。
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com
kind: IngressParameters
name: external-lb
參考文檔
Last updated