Blog:部落格園 個人
參考:Ingress | Kubernetes、《Kubernetes進階實戰》、《Kubernetes網路權威指南 》
何謂Ingress?從字面意思解讀,就是入站流量。Kubernetes的Ingress資源物件是指授權入站連線到達叢集內服務的規則集合。
我們知道,Kubernetes上的NodePort和LoadBalancer型別的Service資源能夠把叢集內部服務暴露給叢集外部客戶端訪問,但兩個負載均衡躍點(路由)必然產生更大的網路延遲,且無疑會大大增加組織在使用雲服務方面的費用開銷。
因此,Kubernetes為這種需求提供了一種更為高階的流量管理約束方式,尤其是對HTTP/HTTPS協議的約束。Kubernetes使用Ingress控制器作為統一的流量入口,管理內部各種必要的服務,並通過Ingress這一API資源來描述如何區分流量以及內部的路由邏輯。有了Ingress和Ingress控制器,我們就可通過定義路由流量的規則來完成服務釋出,而無須建立一堆NodePort或LoadBalancer型別的Service,而且流量也會由Ingress控制器直接到達Pod物件。
Kubernetes Ingress提供了負載平衡器的典型特性:HTTP路由、黏性會話、SSL終止、SSL直通、TCP和UDP負載平衡等。目前,並不是所有的Ingress Controller都實現了這些功能,需要檢視具體的Ingress Controller文件。Ingress控制器有各種型別,包括GoogleCloud Load Balancer、Nginx、Istio等。有些Ingress Controller可能還依賴各種外掛,例如cert-manager,它可以為服務自動提供SSL證書。
?Tips:人們通常把Kubernetes叢集內部的通訊稱為東西向流量,而把叢集內外部的通訊稱為南北向流量。
下面是一個將所有流量都傳送到同一 Service 的簡單 Ingress 示例:
通常情況下,Service和Pod僅可在叢集內部網路中通過IP地址訪問。所有到達邊界路由的流量或被丟棄或被轉發到其他地方。
Ingress的作用就是在邊界路由處開個口子,放外部流量進來。因此,Ingress是建立在Service之上的L7訪問入口,它支援通過URL的方式將Service暴露到k8s叢集外;支援自定義Service的訪問策略;提供按域名訪問的虛擬主機功能;支援TLS通訊。
Ingress規則
每個 HTTP 規則都包含以下資訊:
- 可選的
host
。在此示例中,未指定host
,因此該規則適用於通過指定 IP 地址的所有入站 HTTP 通訊。 如果提供了host
(例如 foo.bar.com),則rules
適用於該host
。 - 路徑列表 paths(例如,
/testpath
),每個路徑都有一個由serviceName
和servicePort
定義的關聯後端。 在負載均衡器將流量定向到引用的服務之前,主機和路徑都必須匹配傳入請求的內容。 backend
(後端)是 Kubernetes:服務與負載均衡中所述的服務和埠名稱的組合。 與規則的host
和path
匹配的對 Ingress 的 HTTP(和 HTTPS )請求將傳送到列出的backend
。
通常在 Ingress 控制器中會配置 defaultBackend
(預設後端),以服務於任何不符合規約中 path
的請求。
?注意:沒有
rules
的 Ingress 將所有流量傳送到同一個預設後端。如果hosts
或paths
都沒有與 Ingress 物件中的 HTTP 請求匹配,則流量將路由到預設後端。
路徑型別
Ingress 中的每個路徑都需要有對應的路徑型別(Path Type)。未明確設定 pathType
的路徑無法通過合法性檢查。當前支援的路徑型別有三種:
ImplementationSpecific
:對於這種路徑型別,匹配方法取決於 IngressClass。 具體實現可以將其作為單獨的pathType
處理或者與Prefix
或Exact
型別作相同處理。Exact
:精確匹配 URL 路徑,且區分大小寫。Prefix
:基於以/
分隔的 URL 路徑字首匹配。匹配區分大小寫,並且對路徑中的元素逐個完成。 路徑元素指的是由/
分隔符分隔的路徑中的標籤列表。 如果每個 p 都是請求路徑 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 |
否,使用預設後端 |
混合 | /foo (Prefix), /foo (Exact) |
/foo |
是,優選 Exact 型別 |
在某些情況下,Ingress 中的多條路徑會匹配同一個請求。 這種情況下最長的匹配路徑優先。 如果仍然有兩條同等的匹配路徑,則精確路徑型別優先於字首路徑型別。
主機名萬用字元
主機名可以是精確匹配(例如“foo.bar.com
”)或者使用萬用字元來匹配 (例如“*.foo.com
”)。 精確匹配要求 HTTP host
頭部欄位與 host
欄位值完全匹配。 萬用字元匹配則要求 HTTP host
頭部欄位與萬用字元規則中的字尾部分相同。
主機 | host 頭部 | 匹配與否? |
---|---|---|
*.foo.com |
bar.foo.com |
基於相同的字尾匹配 |
*.foo.com |
baz.bar.foo.com |
不匹配,萬用字元僅覆蓋了一個 DNS 標籤 |
*.foo.com |
foo.com |
不匹配,萬用字元僅覆蓋了一個 DNS 標籤 |
Ingress型別
單個Service實現
現有的 Kubernetes 概念允許你暴露單個 Service,例如:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
defaultBackend:
service:
name: test
port:
number: 80
執行:
[root@master test]# kubectl apply -f ./test-ingress.yaml
ingress.networking.k8s.io/test-ingress created
簡單扇出(Simple fanout)
一個扇出(fanout)配置根據請求的 HTTP URI 將來自同一 IP 地址的流量路由到多個 Service。 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
基於名稱的虛擬託管(Name based virtual hosting)
基於名稱的虛擬主機支援將針對多個主機名的 HTTP 流量路由到同一 IP 地址上。
總結
Kubernetes的Ingress簡單理解就是個規則定義,例如某個域名對應某個Service,即當某個域名的請求進來時,轉發給某個Service。Ingress Controller負責實現這個規則,即Ingress Controller將其動態寫入負載均衡器的配置中,從而實現服務的負載均衡。