1. 程式人生 > >Kubernetes Ingress解析_Kubernetes中文社群

Kubernetes Ingress解析_Kubernetes中文社群

前言

這是kubernete官方文件中Ingress Resource的翻譯,因為最近工作中用到,文章也不長,也很好理解,索性翻譯一下,也便於自己加深理解,同時造福kubernetes中文社群。後續準備使用Traefik來做Ingress controller,文章末尾給出了幾個相關連結,實際使用案例正在摸索中,屆時相關安裝文件和配置說明將同步更新到kubernetes-handbook中。

術語

在本篇文章中你將會看到一些在其他地方被交叉使用的術語,為了防止產生歧義,我們首先來澄清下。

  • 節點:Kubernetes叢集中的一臺物理機或者虛擬機器。
  • 叢集:位於Internet防火牆後的節點,這是kubernetes管理的主要計算資源。
  • 邊界路由器:為叢集強制執行防火牆策略的路由器。 這可能是由雲提供商或物理硬體管理的閘道器。
  • 叢集網路:一組邏輯或物理連結,可根據Kubernetes網路模型實現群集內的通訊。 叢集網路的實現包括Overlay模型的 flannel 和基於SDN的OVS
  • 服務:使用標籤選擇器標識一組pod成為的Kubernetes服務。 除非另有說明,否則服務假定在叢集網路內僅可通過虛擬IP訪問。

什麼是Ingress?

通常情況下,service和pod僅可在叢集內部網路中通過IP地址訪問。所有到達邊界路由器的流量或被丟棄或被轉發到其他地方。從概念上講,可能像下面這樣:

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

Ingress是授權入站連線到達叢集服務的規則集合。

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

你可以給Ingress配置提供外部可訪問的URL、負載均衡、SSL、基於名稱的虛擬主機等。使用者通過POST Ingress資源到API server的方式來請求ingress。 Ingress controller負責實現Ingress,通常使用負載平衡器,它還可以配置邊界路由和其他前端,這有助於以HA方式處理流量。

先決條件

在使用Ingress resource之前,有必要先了解下面幾件事情。Ingress是beta版本的resource,在kubernetes1.1之前還沒有。你需要一個Ingress Controller

來實現Ingress,單純的建立一個Ingress沒有任何意義。

GCE/GKE會在master節點上部署一個ingress controller。你可以在一個pod中部署任意個自定義的ingress controller。你必須正確地annotate每個ingress,比如 執行多個ingress controller關閉glbc.

確定你已經閱讀了Ingress controller的beta版本限制。在非GCE/GKE的環境中,你需要在pod中部署一個controller

Ingress Resource

最簡化的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

如果你沒有配置Ingress controller就將其POST到API server不會有任何用處

配置說明

1-4行:跟Kubernetes的其他配置一樣,ingress的配置也需要apiVersionkindmetadata欄位。配置檔案的詳細說明請檢視部署應用, 配置容器使用resources.

5-7行: Ingress spec 中包含配置一個loadbalancer或proxy server的所有資訊。最重要的是,它包含了一個匹配所有入站請求的規則列表。目前ingress只支援http規則。

8-9行:每條http規則包含以下資訊:一個host配置項(比如for.bar.com,在這個例子中預設是*),path列表(比如:/testpath),每個path都關聯一個backend(比如test:80)。在loadbalancer將流量轉發到backend之前,所有的入站請求都要先匹配host和path。

10-12行:正如 services doc中描述的那樣,backend是一個service:port的組合。Ingress的流量被轉發到它所匹配的backend。

全域性引數:為了簡單起見,Ingress示例中沒有全域性引數,請參閱資源完整定義的api參考。 在所有請求都不能跟spec中的path匹配的情況下,請求被髮送到Ingress controller的預設後端,可以指定全域性預設backend。

Ingress Controllers

為了使Ingress正常工作,叢集中必須執行Ingress controller。 這與其他型別的控制器不同,其他型別的控制器通常作為kube-controller-manager二進位制檔案的一部分執行,在叢集啟動時自動啟動。 你需要選擇最適合自己叢集的Ingress controller或者自己實現一個。 示例和說明可以在這裡找到。

在你開始前

以下文件描述了Ingress資源中公開的一組跨平臺功能。 理想情況下,所有的Ingress controller都應該符合這個規範,但是我們還沒有實現。 GCE和nginx控制器的文件分別在這裡這裡確保您檢視控制器特定的文件,以便您瞭解每個文件的注意事項。

Ingress型別

單Service Ingress

Kubernetes中已經存在一些概念可以暴露單個service(檢視替代方案),但是你仍然可以通過Ingress來實現,通過指定一個沒有rule的預設backend的方式。

ingress.yaml定義檔案:

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

使用kubectl create -f命令建立,然後檢視ingress:

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

107.178.254.228就是Ingress controller為了實現Ingress而分配的IP地址。RULE列表示所有傳送給該IP的流量都被轉發到了BACKEND所列的Kubernetes service上。

簡單展開

如前面描述的那樣,kubernete pod中的IP只在叢集網路內部可見,我們需要在邊界設定一個東西,讓它能夠接收ingress的流量並將它們轉發到正確的端點上。這個東西一般是高可用的loadbalancer。使用Ingress能夠允許你將loadbalancer的個數降低到最少,例如,嫁入你想要建立這樣的一個設定:

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

只要服務(s1,s2)存在,Ingress controller就會將提供一個滿足該Ingress的特定loadbalancer實現。 這一步完成後,您將在Ingress的最後一列看到loadbalancer的地址。

基於名稱的虛擬主機

Name-based的虛擬主機在同一個IP地址下擁有多個主機名。

foo.bar.com --|                 |-> foo.bar.com s1:80
              | 178.91.123.132  |
bar.foo.com --|                 |-> bar.foo.com s2:80

下面這個ingress說明基於Host header的後端loadbalancer的路由請求:

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

預設backend:一個沒有rule的ingress,如前面章節中所示,所有流量都將傳送到一個預設backend。你可以用該技巧通知loadbalancer如何找到你網站的404頁面,通過制定一些列rule和一個預設backend的方式。如果請求header中的host不能跟ingress中的host匹配,並且/或請求的URL不能與任何一個path匹配,則流量將路由到你的預設backend。

TLS

你可以通過指定包含TLS私鑰和證書的secret來加密Ingress。 目前,Ingress僅支援單個TLS埠443,並假定TLS termination。 如果Ingress中的TLS配置部分指定了不同的主機,則它們將根據通過SNI TLS擴充套件指定的主機名(假如Ingress controller支援SNI)在多個相同埠上進行復用。 TLS secret中必須包含名為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中引用這個secret將通知Ingress controller使用TLS加密從將客戶端到loadbalancer的channel:

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

請注意,各種Ingress controller支援的TLS功能之間存在差距。 請參閱有關nginxGCE或任何其他平臺特定Ingress controller的文件,以瞭解TLS在你的環境中的工作原理。

Ingress controller啟動時附帶一些適用於所有Ingress的負載平衡策略設定,例如負載均衡演算法,後端權重方案等。更高階的負載平衡概念(例如持久會話,動態權重)尚未在Ingress中公開。 你仍然可以通過service loadbalancer獲取這些功能。 隨著時間的推移,我們計劃將適用於跨平臺的負載平衡模式加入到Ingress資源中。

還值得注意的是,儘管健康檢查不直接通過Ingress公開,但Kubernetes中存在並行概念,例如準備探查,可以使你達成相同的最終結果。 請檢視特定控制器的文件,以瞭解他們如何處理健康檢查(nginxGCE)。

更新Ingress

假如你想要向已有的ingress中增加一個新的Host,你可以編輯和更新該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
..

儲存它會更新API server中的資源,這會觸發ingress controller重新配置loadbalancer。

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

在一個修改過的ingress yaml檔案上呼叫kubectl replace -f命令一樣可以達到同樣的效果。

跨可用域故障

在不通雲供應商之間,跨故障域的流量傳播技術有所不同。 有關詳細資訊,請檢視相關Ingress controller的文件。 有關在federation叢集中部署Ingress的詳細資訊,請參閱[federation文件]()。

未來計劃

  • 多樣化的HTTPS/TLS模型支援(如SNI,re-encryption)
  • 通過宣告來請求IP或者主機名
  • 結合L4和L7 Ingress
  • 更多的Ingress controller

請跟蹤L7和Ingress的proposal,瞭解有關資源演進的更多細節,以及Ingress repository,瞭解有關各種Ingress controller演進的更多詳細資訊。

替代方案

你可以通過很多種方式暴露service而不必直接使用ingress:

參考