Ingress

使用協定感知組態機制,讓您的 HTTP (或 HTTPS) 網路服務可用,此機制可理解 URI、主機名稱、路徑等 Web 概念。Ingress 概念可讓您根據透過 Kubernetes API 定義的規則,將流量對應至不同的後端。

功能狀態: Kubernetes v1.19 [穩定]

一個 API 物件,用於管理對叢集中服務的外部存取,通常是 HTTP。

Ingress 可以提供負載平衡、SSL 終止和基於名稱的虛擬主機。

術語

為了清楚起見,本指南定義了以下術語

  • 節點:Kubernetes 中的工作機器,叢集的一部分。
  • 叢集:一組節點,執行由 Kubernetes 管理的容器化應用程式。在此範例以及大多數常見的 Kubernetes 部署中,叢集中的節點不屬於公共網際網路。
  • 邊緣路由器:一個路由器,用於強制執行叢集的防火牆原則。這可能是由雲端供應商管理的閘道或實體硬體。
  • 叢集網路:一組連結(邏輯或實體),用於促進叢集內根據 Kubernetes 網路模型進行通訊。
  • 服務:Kubernetes 服務,使用標籤選擇器識別一組 Pod。除非另有說明,否則服務假定為僅在叢集網路內可路由的虛擬 IP。

什麼是 Ingress?

Ingress 將來自叢集外部的 HTTP 和 HTTPS 路由公開到叢集內的服務。流量路由由 Ingress 資源上定義的規則控制。

這是一個簡單的範例,其中 Ingress 將所有流量傳送到一個服務

ingress-diagram

圖. Ingress

Ingress 可以設定為提供服務外部可存取的 URL、負載平衡流量、終止 SSL/TLS,並提供基於名稱的虛擬主機。 Ingress 控制器負責實現 Ingress,通常使用負載平衡器,儘管它也可能設定您的邊緣路由器或額外的前端來協助處理流量。

Ingress 不會公開任意連接埠或協定。將 HTTP 和 HTTPS 以外的服務公開到網際網路通常使用類型為 Service.Type=NodePortService.Type=LoadBalancer 的服務。

先決條件

您必須具有 Ingress 控制器才能滿足 Ingress。僅建立 Ingress 資源沒有任何作用。

您可能需要部署 Ingress 控制器,例如 ingress-nginx。您可以從許多 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 需要 apiVersionkindmetadataspec 欄位。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.nameservice.port.nameservice.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,或將其視為與 PrefixExact 路徑類型相同。

  • Exact:完全且區分大小寫地比對 URL 路徑。

  • Prefix:根據由 / 分隔的 URL 路徑前綴進行比對。比對區分大小寫,並以路徑元素為單位進行。路徑元素指的是路徑中由 / 分隔符號分隔的標籤清單。如果請求路徑的每個元素都以路徑 p 作為前綴,則請求與路徑 p 相符。

範例

類型路徑請求路徑相符?
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 標頭等於萬用字元規則的後綴。

HostHost 標頭相符?
*.foo.combar.foo.com根據共用後綴比對
*.foo.combaz.bar.foo.com不相符,萬用字元僅涵蓋單一 DNS 標籤
*.foo.comfoo.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

FEATURE STATE: 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。

有些 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。

簡單的扇出

扇出組態會根據請求的 HTTP URI,將來自單一 IP 位址的流量路由到多個 Service。Ingress 可讓您將負載平衡器的數量保持在最低限度。例如,像這樣的設定:

ingress-fanout-diagram

圖. 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(service1service2)存在。完成後,您可以在 Address 欄位中看到負載平衡器的位址。

基於名稱的虛擬主機

基於名稱的虛擬主機支援將 HTTP 流量路由到相同 IP 位址的多個主機名稱。

ingress-namebase-diagram

圖. 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.comsecond.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.crttls.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)。

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,可讓您達到相同的最終結果。請查閱控制器特定的文件,以瞭解它們如何處理健康狀態檢查(例如:nginxGCE)。

更新 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:

下一步

上次修改時間:2024 年 9 月 13 日上午 9:33 PST:修正 markdown 檔案中的一些超連結 (e6855623c7)