天天看點

kubernetes kube-proxy模式詳解

kubernetes裡kube-proxy支援三種模式,在v1.8之前我們使用的是iptables 以及 userspace兩種模式,在kubernetes 1.8之後引入了ipvs模式,并且在v1.11中正式使用,其中iptables和ipvs都是核心态也就是基于netfilter,隻有userspace模式是使用者态。下面詳細介紹下各個模式:

kubernetes kube-proxy模式詳解

userspace

在k8s v1.2後就已經被淘汰了,userspace的作用就是在proxy的使用者空間監聽一個端口,所有的svc都轉到這個端口,然後proxy的内部應用層對其進行轉發。proxy會為每個svc随機監聽一個端口,并增加一個iptables規則,從用戶端到 ClusterIP:Port 的封包都會被重定向到 Proxy Port,Kube-Proxy 收到封包後,通過 Round Robin (輪詢) 或者 Session Affinity(會話親和力,即同一 Client IP 都走同一鍊路給同一 Pod 服務)分發給對應的 Pod。所有流量都是在使用者空間進行轉發的,雖然比較穩定,但是效率不高。如下圖為userspace的工作流程。

kubernetes kube-proxy模式詳解

Iptables

iptables這種模式是從kubernetes1.2開始并在v1.12之前的預設模式。在這種模式下proxy監控kubernetes對svc和ep對象進行增删改查。并且這種模式使用iptables來做使用者态的入口,而真正提供服務的是核心的Netilter,Netfilter采用子產品化設計,具有良好的可擴充性。其重要工具子產品IPTables從使用者态的iptables連接配接到核心态的Netfilter的架構中,Netfilter與IP協定棧是無縫契合的,并允許使用者對資料報進行過濾、位址轉換、處理等操作。這種情況下proxy隻作為Controller。Kube-Proxy 監聽 Kubernetes Master 增加和删除 Service 以及 Endpoint 的消息。對于每一個 Service,Kube Proxy 建立相應的 IPtables 規則,并将發送到 Service Cluster IP 的流量轉發到 Service 後端提供服務的 Pod 的相應端口上。并且流量的轉發都是在核心态進行的,是以性能更高更加可靠。

在這種模式下缺點就是在大規模的叢集中,iptables添加規則會有很大的延遲。因為使用iptables,每增加一個svc都會增加一條iptables的chain。并且iptables修改了規則後必須得全部重新整理才可以生效。

iptables 自定義幾條鍊路:KUBE-SERVICES,KUBE-NODEPORTS,KUBE-POSTROUTING,KUBE-MARK-MASQ和KUBE-MARK-DROP五個鍊,并主要通過為 KUBE-SERVICES鍊(附着在PREROUTING和OUTPUT)增加rule來配制traffic routing 規則。

iptabels 模式下正常的通信鍊路:

在 PREROUTING的 chain裡将 将經過PREROUTING裡的資料包重定向到KUBE-SERVICES中

在自定義鍊kube-services裡找到dst為目标位址的ip(ps:kube-services對于相同目标位址都有2給target,對于非pod之間的通路進入KUBE-MARK-MASQ,對于pod之間的通路進入KUBE-SVC-*裡),找到對應的KUBE-SVC-*(ps:隻有有對應endpoint資訊的才有KUBE-SVC-*),并找到KUBE-SVC-*對應的KUBE-SEP-*。在SEP裡會對source來自自身ip的打KUBE-MARK-MASQ,對于其他的做DNAT轉換

IPVS

kubernetes從1.8開始增加了IPVS支援,IPVS相對于iptables來說效率會更加高,使用ipvs模式需要在允許proxy的節點上安裝ipvsadm,ipset工具包加載ipvs的核心子產品。并且ipvs可以輕松處理每秒 10 萬次以上的轉發請求。

當proxy啟動的時候,proxy将驗證節點上是否安裝了ipvs子產品。如果未安裝的話将回退到iptables模式。

并在Kubernetes 1.12成為kube-proxy的預設代理模式。ipvs模式也是基于netfilter,對比iptables模式在大規模Kubernetes叢集有更好的擴充性和性能,支援更加複雜的負載均衡算法(如:最小負載、最少連接配接、權重等),支援Server的健康檢查和連接配接重試等功能。ipvs依賴于iptables,使用iptables進行包過濾、SNAT、masquared。ipvs将使用ipset需要被DROP或MASQUARED的源位址或目标位址,這樣就能保證iptables規則數量的固定,我們不需要關心叢集中有多少個Service了。

kubernetes kube-proxy模式詳解

這種模式,Kube-Proxy 會監視 Kubernetes Service 對象 和 Endpoints,調用 Netlink 接口以相應地建立 IPVS 規則并定期與 Kubernetes Service 對象 和 Endpoints 對象同步 IPVS 規則,以確定 IPVS 狀态與期望一緻。通路服務時,流量将被重定向到其中一個後端 Pod。

以下情況下IPVS會使用iptables

IPVS proxier将使用iptables,在資料包過濾,SNAT和支援NodePort類型的服務這幾個場景中。具體來說,ipvs proxier将在以下4個場景中回歸iptables。

kube-proxy 啟動項設定了 –masquerade-all=true

如果kube-proxy以--masquerade-all = true開頭,則ipvs proxier将僞裝通路服務群集IP的所有流量,其行為與iptables proxier相同

注:master節點上也需要進行kubelet配置。因為ipvs在有些情況下是依賴iptables的,iptables中KUBE-POSTROUTING,KUBE-MARK-MASQ, KUBE-MARK-DROP這三條鍊是被 kubelet建立和維護的, ipvs不會建立它們。

在kube-proxy啟動中指定叢集CIDR

如果kube-proxy以--cluster-cidr = <cidr>開頭,則ipvs proxier将僞裝通路服務群集IP的群集外流量,其行為與iptables proxier相同。

為LB類型服務指定Load Balancer Source Ranges

當服務的LoadBalancerStatus.ingress.IP不為空并且指定了服務的LoadBalancerSourceRanges時,ipvs proxier将安裝iptables。

支援 NodePort type service

為了支援NodePort類型的服務,ipvs将在iptables proxier中繼續現有的實作。

kubernetes中ipvs實作原理圖:

kubernetes kube-proxy模式詳解

為什麼每個svc會在ipvs網卡增加vip位址:

由于 IPVS 的 DNAT 鈎子挂在 INPUT 鍊上,是以必須要讓核心識别 VIP 是本機的 IP。這樣才會過INPUT 鍊,要不然就通過OUTPUT鍊出去了。k8s 通過設定将service cluster ip 綁定到虛拟網卡kube-ipvs0。

①因為service cluster ip 綁定到虛拟網卡kube-ipvs0上,核心可以識别通路的 VIP 是本機的 IP.

②資料包到達INPUT鍊.

③ipvs監聽到達input鍊的資料包,比對資料包請求的服務是為叢集服務,修改資料包的目标IP位址為對應pod的IP,然後将資料包發至POSTROUTING鍊.

④資料包經過POSTROUTING鍊選路,将資料包通過flannel網卡發送出去。從flannel虛拟網卡獲得源IP.

⑤pod接收到請求之後,建構響應封包,改變源位址和目的位址,傳回給用戶端。

模拟ipvs模式:

新增DROP 鍊路 将svc位址即ipvs的vip位址為10.222.251.98的包丢棄

在指定的node節點執行

iptables -t filter -I INPUT -d 10.222.251.98 -j DROP

kubernetes kube-proxy模式詳解

當該vip位址進入到這個input的鍊路的時候直接DROP 如下:

檢視鍊路是否有包

watch -n 0.1 "iptables --line-number -nvxL INPUT"

kubernetes kube-proxy模式詳解

因為當我們通路10.222.251.98這個位址的時候,ipvs會感覺到這個ip是本機的vip位址,是以會線進入input的鍊路。是以我們在input增加了desc為10.222.251.98的DROP鍊路的話,會有限

之後恢複的話直接删除掉指定規則

iptables -D INPUT 1

繼續閱讀