Ingress
Kubernetes v1.19 [穩定]
一個 API 物件,用於管理對叢集中服務的外部存取,通常是 HTTP。
Ingress 可以提供負載平衡、SSL 終止和基於名稱的虛擬主機。
注意
Ingress 已凍結。新功能正在新增至閘道 API。術語
為了清楚起見,本指南定義了以下術語
- 節點:Kubernetes 中的工作機器,叢集的一部分。
- 叢集:一組節點,執行由 Kubernetes 管理的容器化應用程式。在此範例以及大多數常見的 Kubernetes 部署中,叢集中的節點不屬於公共網際網路。
- 邊緣路由器:一個路由器,用於強制執行叢集的防火牆原則。這可能是由雲端供應商管理的閘道或實體硬體。
- 叢集網路:一組連結(邏輯或實體),用於促進叢集內根據 Kubernetes 網路模型進行通訊。
- 服務:Kubernetes 服務,使用標籤選擇器識別一組 Pod。除非另有說明,否則服務假定為僅在叢集網路內可路由的虛擬 IP。
什麼是 Ingress?
Ingress 將來自叢集外部的 HTTP 和 HTTPS 路由公開到叢集內的服務。流量路由由 Ingress 資源上定義的規則控制。
這是一個簡單的範例,其中 Ingress 將所有流量傳送到一個服務
圖. Ingress
Ingress 可以設定為提供服務外部可存取的 URL、負載平衡流量、終止 SSL/TLS,並提供基於名稱的虛擬主機。 Ingress 控制器負責實現 Ingress,通常使用負載平衡器,儘管它也可能設定您的邊緣路由器或額外的前端來協助處理流量。
Ingress 不會公開任意連接埠或協定。將 HTTP 和 HTTPS 以外的服務公開到網際網路通常使用類型為 Service.Type=NodePort 或 Service.Type=LoadBalancer 的服務。
先決條件
您必須具有 Ingress 控制器才能滿足 Ingress。僅建立 Ingress 資源沒有任何作用。
您可能需要部署 Ingress 控制器,例如 ingress-nginx。您可以從許多 Ingress 控制器中選擇。
理想情況下,所有的 Ingress 控制器都應符合參考規格。但實際上,各種 Ingress 控制器的運作方式略有不同。
注意
請務必詳閱您的 Ingress 控制器的文件,以瞭解選擇它時的注意事項。Ingress 資源
Ingress 資源的最小範例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
Ingress 需要 apiVersion
、kind
、metadata
和 spec
欄位。Ingress 物件的名稱必須是有效的 DNS 子網域名稱。如需組態檔案的一般資訊,請參閱部署應用程式、設定容器、管理資源。Ingress 經常使用註解來設定某些選項,具體取決於 Ingress 控制器,例如 rewrite-target 註解。不同的 Ingress 控制器支援不同的註解。請查閱您選擇的 Ingress 控制器的文件,以瞭解支援哪些註解。
Ingress spec 具有設定負載平衡器或 Proxy 伺服器所需的所有資訊。最重要的是,它包含一個規則清單,用於比對所有傳入的請求。Ingress 資源僅支援用於導向 HTTP(S) 流量的規則。
如果省略 ingressClassName
,則應定義預設 Ingress 類別。
有些 Ingress 控制器無需定義預設的 IngressClass
即可運作。例如,Ingress-NGINX 控制器可以使用 flag --watch-ingress-without-class
進行設定。不過,建議指定預設的 IngressClass
,如下方所示。
Ingress 規則
每個 HTTP 規則都包含以下資訊:
- 選用的 host。在此範例中,未指定 host,因此規則適用於透過指定的 IP 位址的所有 inbound HTTP 流量。如果提供了 host(例如 foo.bar.com),則規則適用於該 host。
- 路徑清單(例如
/testpath
),每個路徑都有一個關聯的後端,並使用service.name
和service.port.name
或service.port.number
進行定義。host 和路徑都必須與傳入請求的內容相符,負載平衡器才會將流量導向至參照的 Service。 - 後端是 Service 和埠口名稱的組合,如 Service 文件中所述,或是透過 CRD 的自訂資源後端。符合規則的 host 和路徑的 HTTP(和 HTTPS)請求會傳送到列出的後端。
defaultBackend
通常在 Ingress 控制器中設定,以服務任何與 spec 中的路徑不符的請求。
DefaultBackend
沒有規則的 Ingress 會將所有流量傳送到單一預設後端,而 .spec.defaultBackend
是在這種情況下應處理請求的後端。defaultBackend
通常是 Ingress 控制器的組態選項,並未在您的 Ingress 資源中指定。如果未指定 .spec.rules
,則必須指定 .spec.defaultBackend
。如果未設定 defaultBackend
,則不符合任何規則的請求的處理方式將取決於 Ingress 控制器(請查閱您的 Ingress 控制器的文件,以瞭解它如何處理這種情況)。
如果 Ingress 物件中沒有任何 host 或路徑符合 HTTP 請求,則流量會路由到您的預設後端。
資源後端
Resource
後端是 ObjectRef,指向與 Ingress 物件位於相同命名空間中的另一個 Kubernetes 資源。Resource
是與 Service 互斥的設定,如果兩者都指定,則驗證將會失敗。Resource
後端的常見用法是將資料傳送到具有靜態資產的物件儲存後端。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-resource-backend
spec:
defaultBackend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: static-assets
rules:
- http:
paths:
- path: /icons
pathType: ImplementationSpecific
backend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: icon-assets
建立上述 Ingress 之後,您可以使用以下指令檢視它:
kubectl describe ingress ingress-resource-backend
Name: ingress-resource-backend
Namespace: default
Address:
Default backend: APIGroup: k8s.example.com, Kind: StorageBucket, Name: static-assets
Rules:
Host Path Backends
---- ---- --------
*
/icons APIGroup: k8s.example.com, Kind: StorageBucket, Name: icon-assets
Annotations: <none>
Events: <none>
路徑類型
Ingress 中的每個路徑都必須具有對應的路徑類型。未包含明確 pathType
的路徑將無法通過驗證。支援三種路徑類型:
ImplementationSpecific
:使用此路徑類型時,比對由 IngressClass 決定。實作可以將其視為單獨的pathType
,或將其視為與Prefix
或Exact
路徑類型相同。Exact
:完全且區分大小寫地比對 URL 路徑。Prefix
:根據由/
分隔的 URL 路徑前綴進行比對。比對區分大小寫,並以路徑元素為單位進行。路徑元素指的是路徑中由/
分隔符號分隔的標籤清單。如果請求路徑的每個元素都以路徑 p 作為前綴,則請求與路徑 p 相符。注意
如果路徑的最後一個元素是請求路徑中最後一個元素的子字串,則不相符(例如:/foo/bar
符合/foo/bar/baz
,但不符合/foo/barbaz
)。
範例
類型 | 路徑 | 請求路徑 | 相符? |
---|---|---|---|
Prefix | / | (所有路徑) | 是 |
Exact | /foo | /foo | 是 |
Exact | /foo | /bar | 否 |
Exact | /foo | /foo/ | 否 |
Exact | /foo/ | /foo | 否 |
Prefix | /foo | /foo 、/foo/ | 是 |
Prefix | /foo/ | /foo 、/foo/ | 是 |
Prefix | /aaa/bb | /aaa/bbb | 否 |
Prefix | /aaa/bbb | /aaa/bbb | 是 |
Prefix | /aaa/bbb/ | /aaa/bbb | 是,忽略結尾斜線 |
Prefix | /aaa/bbb | /aaa/bbb/ | 是,符合結尾斜線 |
Prefix | /aaa/bbb | /aaa/bbb/ccc | 是,符合子路徑 |
Prefix | /aaa/bbb | /aaa/bbbxyz | 否,不符合字串前綴 |
Prefix | / 、/aaa | /aaa/ccc | 是,符合 /aaa 前綴 |
Prefix | / 、/aaa 、/aaa/bbb | /aaa/bbb | 是,符合 /aaa/bbb 前綴 |
Prefix | / 、/aaa 、/aaa/bbb | /ccc | 是,符合 / 前綴 |
Prefix | /aaa | /ccc | 否,使用預設後端 |
Mixed | /foo (Prefix)、/foo (Exact) | /foo | 是,偏好 Exact |
多重比對
在某些情況下,Ingress 中的多個路徑會符合請求。在這些情況下,優先順序首先會給予最長的比對路徑。如果兩個路徑仍然相等比對,則優先順序會給予具有 exact 路徑類型而不是 prefix 路徑類型的路徑。
主機名稱萬用字元
Host 可以是精確比對(例如 “foo.bar.com
”)或萬用字元(例如 “*.foo.com
”)。精確比對要求 HTTP host
標頭與 host
欄位相符。萬用字元比對要求 HTTP host
標頭等於萬用字元規則的後綴。
Host | Host 標頭 | 相符? |
---|---|---|
*.foo.com | bar.foo.com | 根據共用後綴比對 |
*.foo.com | baz.bar.foo.com | 不相符,萬用字元僅涵蓋單一 DNS 標籤 |
*.foo.com | foo.com | 不相符,萬用字元僅涵蓋單一 DNS 標籤 |
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-wildcard-host
spec:
rules:
- host: "foo.bar.com"
http:
paths:
- pathType: Prefix
path: "/bar"
backend:
service:
name: service1
port:
number: 80
- host: "*.foo.com"
http:
paths:
- pathType: Prefix
path: "/foo"
backend:
service:
name: service2
port:
number: 80
Ingress 類別
Ingress 可以由不同的控制器實作,通常具有不同的組態。每個 Ingress 都應指定一個類別,即對 IngressClass 資源的參照,其中包含其他組態,包括應實作該類別的控制器的名稱。
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
IngressClass 的 .spec.parameters
欄位可讓您參照另一個資源,該資源提供與該 IngressClass 相關的組態。
要使用的參數的特定類型取決於您在 IngressClass 的 .spec.controller
欄位中指定的 Ingress 控制器。
IngressClass 範圍
根據您的 Ingress 控制器,您可以使用叢集範圍或僅適用於單一命名空間的參數。
IngressClass 參數的預設範圍是叢集範圍。
如果您設定 .spec.parameters
欄位且未設定 .spec.parameters.scope
,或者如果您將 .spec.parameters.scope
設定為 Cluster
,則 IngressClass 會參照叢集範圍的資源。參數的 kind
(與 apiGroup
結合)參照叢集範圍的 API(可能是自訂資源),而參數的 name
識別該 API 的特定叢集範圍資源。
例如:
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-1
spec:
controller: example.com/ingress-controller
parameters:
# The parameters for this IngressClass are specified in a
# ClusterIngressParameter (API group k8s.example.net) named
# "external-config-1". This definition tells Kubernetes to
# look for a cluster-scoped parameter resource.
scope: Cluster
apiGroup: k8s.example.net
kind: ClusterIngressParameter
name: external-config-1
Kubernetes v1.23 [stable]
如果您設定 .spec.parameters
欄位並將 .spec.parameters.scope
設定為 Namespace
,則 IngressClass 會參照命名空間範圍的資源。您還必須在 .spec.parameters
內設定 namespace
欄位,以指定包含您要使用的參數的命名空間。
參數的 kind
(與 apiGroup
結合)參照命名空間範圍的 API(例如:ConfigMap),而參數的 name
識別您在 namespace
中指定的命名空間中的特定資源。
命名空間範圍的參數可協助叢集運算子委派對工作負載使用的組態(例如:負載平衡器設定、API 閘道定義)的控制權。如果您使用叢集範圍的參數,則:
- 每次套用新的組態變更時,叢集運算子團隊都需要批准不同團隊的變更。
- 叢集運算子必須定義特定的存取控制,例如 RBAC 角色和繫結,以允許應用程式團隊變更叢集範圍的參數資源。
IngressClass API 本身始終是叢集範圍的。
以下是一個 IngressClass 的範例,該範例參照命名空間範圍的參數:
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-2
spec:
controller: example.com/ingress-controller
parameters:
# The parameters for this IngressClass are specified in an
# IngressParameter (API group k8s.example.com) named "external-config",
# that's in the "external-configuration" namespace.
scope: Namespace
apiGroup: k8s.example.com
kind: IngressParameter
namespace: external-configuration
name: external-config
已棄用的註解
在 Kubernetes 1.18 中新增 IngressClass 資源和 ingressClassName
欄位之前,Ingress 類別是使用 Ingress 上的 kubernetes.io/ingress.class
註解指定的。此註解從未正式定義,但受到 Ingress 控制器的廣泛支援。
Ingress 上較新的 ingressClassName
欄位是該註解的替代方案,但並非直接對等。雖然註解通常用於參照應實作 Ingress 的 Ingress 控制器的名稱,但該欄位是對 IngressClass 資源的參照,其中包含其他 Ingress 組態,包括 Ingress 控制器的名稱。
預設 IngressClass
您可以將特定的 IngressClass 標記為叢集的預設值。在 IngressClass 資源上將 ingressclass.kubernetes.io/is-default-class
註解設定為 true
,將確保未指定 ingressClassName
欄位的新 Ingress 會被指派此預設 IngressClass。
注意
如果您有多個 IngressClass 標記為叢集的預設值,則 admission controller 會阻止建立未指定ingressClassName
的新 Ingress 物件。您可以透過確保叢集中最多只有 1 個 IngressClass 標記為預設值來解決此問題。有些 Ingress 控制器無需定義預設的 IngressClass
即可運作。例如,Ingress-NGINX 控制器可以使用 flag --watch-ingress-without-class
進行設定。不過,建議指定預設的 IngressClass
。
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
app.kubernetes.io/component: controller
name: nginx-example
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: k8s.io/ingress-nginx
Ingress 類型
由單一 Service 支援的 Ingress
現有的 Kubernetes 概念允許您公開單一 Service(請參閱替代方案)。您也可以使用 Ingress 透過指定沒有規則的預設後端來執行此操作。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
defaultBackend:
service:
name: test
port:
number: 80
如果您使用 kubectl apply -f
建立它,您應該能夠檢視您新增的 Ingress 的狀態
kubectl get ingress test-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress external-lb * 203.0.113.123 80 59s
其中 203.0.113.123
是 Ingress 控制器為滿足此 Ingress 而配置的 IP。
注意
Ingress 控制器和負載平衡器可能需要一兩分鐘才能配置 IP 位址。在該時間之前,您通常會看到位址列為<pending>
。簡單的扇出
扇出組態會根據請求的 HTTP URI,將來自單一 IP 位址的流量路由到多個 Service。Ingress 可讓您將負載平衡器的數量保持在最低限度。例如,像這樣的設定:
圖. Ingress 扇出
它需要像這樣的 Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080
當您使用 kubectl apply -f
建立 Ingress 時:
kubectl describe ingress simple-fanout-example
Name: simple-fanout-example
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 service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
Ingress 控制器會佈建實作特定的負載平衡器,以滿足 Ingress,前提是 Service(service1
、service2
)存在。完成後,您可以在 Address 欄位中看到負載平衡器的位址。
基於名稱的虛擬主機
基於名稱的虛擬主機支援將 HTTP 流量路由到相同 IP 位址的多個主機名稱。
圖. Ingress 基於名稱的虛擬主機
以下 Ingress 告知後端負載平衡器根據 Host 標頭路由請求。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
如果您建立沒有在規則中定義任何 host 的 Ingress 資源,則可以比對到您的 Ingress 控制器的 IP 位址的任何 Web 流量,而無需基於名稱的虛擬主機。
例如,以下 Ingress 將針對 first.bar.com
的流量路由到 service1
,將 second.bar.com
的流量路由到 service2
,並將任何請求 host 標頭與 first.bar.com
和 second.bar.com
不符的流量路由到 service3
。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress-no-third-host
spec:
rules:
- host: first.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: second.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
- http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service3
port:
number: 80
TLS
您可以透過指定包含 TLS 私密金鑰和憑證的 Secret 來保護 Ingress。Ingress 資源僅支援單一 TLS 埠口 443,並假設 TLS 終止於 Ingress 點(到 Service 及其 Pod 的流量為純文字)。如果 Ingress 中的 TLS 組態區段指定了不同的 host,則它們會根據透過 SNI TLS 擴充功能指定的主機名稱在同一個埠口上進行多工處理(前提是 Ingress 控制器支援 SNI)。TLS Secret 必須包含名為 tls.crt
和 tls.key
的金鑰,其中包含用於 TLS 的憑證和私密金鑰。例如:
apiVersion: v1
kind: Secret
metadata:
name: testsecret-tls
namespace: default
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
type: kubernetes.io/tls
在 Ingress 中參照此 Secret 會告知 Ingress 控制器使用 TLS 保護從用戶端到負載平衡器的通道。您需要確保您建立的 TLS Secret 來自包含 Common Name (CN) 的憑證,也稱為 https-example.foo.com
的完整合格網域名稱 (FQDN)。
注意
請記住,TLS 將無法在預設規則上運作,因為憑證必須針對所有可能的子網域發行。因此,tls
區段中的 hosts
需要明確符合 rules
區段中的 host
。apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- https-example.foo.com
secretName: testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
負載平衡
Ingress 控制器使用一些負載平衡策略設定進行引導,這些設定會套用至所有 Ingress,例如負載平衡演算法、後端權重配置和其他設定。更進階的負載平衡概念(例如持續性連線、動態權重)尚未透過 Ingress 公開。您可以透過用於 Service 的負載平衡器來取得這些功能。
同樣值得注意的是,即使健康狀態檢查未直接透過 Ingress 公開,Kubernetes 中也存在並行的概念,例如 readiness probes,可讓您達到相同的最終結果。請查閱控制器特定的文件,以瞭解它們如何處理健康狀態檢查(例如:nginx 或 GCE)。
更新 Ingress
若要更新現有的 Ingress 以新增新的 Host,您可以透過編輯資源來更新它:
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 service1: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 格式的現有組態。修改它以包含新的 Host:
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
service:
name: service1
port:
number: 80
path: /foo
pathType: Prefix
- host: bar.baz.com
http:
paths:
- backend:
service:
name: service2
port:
number: 80
path: /foo
pathType: Prefix
..
儲存變更後,kubectl 會更新 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 service1:80 (10.8.0.90:80)
bar.baz.com
/foo service2: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
您可以透過在修改後的 Ingress YAML 檔案上調用 kubectl replace -f
來達到相同的結果。
跨可用性區域故障轉移
跨故障網域分散流量的技術因雲端供應商而異。請查看相關 Ingress 控制器的文件以瞭解詳細資訊。
替代方案
您可以使用多種不直接涉及 Ingress 資源的方式公開 Service: