kube-proxy模式詳解
kubernetes裡kube-proxy支援三種模式,在v1.8之前我們使用的是iptables 以及 userspace兩種模式,在kubernetes 1.8之後引入了ipvs模式,並且在v1.11中正式使用,其中iptables和ipvs都是核心態也就是基於netfilter,只有userspace模式是使用者態。
userspace
起初,kube-proxy程式是一個真實的TCP/UDP代理,當某個pod以clusterIP方式訪問某個service的時候,這個流量會被pod所在的本機的iptables轉發到本季的kube-proxy程式,然後將請求轉發到後端某個pod上。具體過程為:
- kube-proxy為每個service在node上開啟一個隨機埠作為代理埠
- 建立iptables規則,將clusterip的請求重定向到代理埠(使用者空間)
- 到達代理埠的請求再由kubeproxy轉發到後端
clusterip重定向到kube-proxy服務的過程存在核心態到使用者態的切換,開銷很大,因此有了iptables模式,而userspace模式也被廢棄了。
iptabels
kubernets從1.2版本開始將iptabels模式作為預設模式,這種模式下kube-proxy不再起到proxy的作用。其核心功能:通過API Server的Watch介面實時跟蹤Service和Endpoint的變更資訊,並更新對應的iptables規則,Client的請求流量通過iptables的NAT機制“直接路由”到目標Pod。
不同於userspace,iptables由kube-proxy動態的管理,kube-proxy不再負責轉發,資料包的走向完全由iptables規則決定,這樣的過程不存在核心態到使用者態的切換,效率明顯會高很多。但是隨著service的增加,iptables規則會不斷增加,導致核心十分繁忙(等於在讀一張很大的沒建索引的表)。
2個svc,8個pod就有34條iptabels規則了,隨著叢集中svc和pod大量增加以後,iptables中的規則開會急速膨脹,導致效能下降,某些極端情況下甚至會出現規則丟失的情況,並且這種故障難以重現和排查。
ipvs
從kubernetes 1.8版本開始引入第三代的IPVS模式,它也是基於netfilter實現的,但定位不同:iptables是為防火牆設計的,IPVS則專門用於高效能
負載均衡,並使用高效的資料結構Hash表,允許幾乎無限的規模擴張。
一句話說明:ipvs使用ipset儲存iptables規則,在查詢時類似hash表查詢,時間複雜度為O(1),而iptables時間複雜度則為O(n)。
可以將ipset簡單理解為ip集合,這個集合的內容可以是IP地址、IP網段、埠等,iptabels可以直接新增規則對這個可變集合進行操作,這樣做的好處可以大大減少iptables規則的數量,從而減少效能損耗。
假設要禁止上萬個IP訪問我們的伺服器,如果用iptables的話,就需要一條一條的新增規則,會生成大量的iptabels規則;但是用ipset的話,只需要將相關IP地址加入ipset集合中即可,這樣只需要設定少量的iptables規則即可實現目標。
由於ipvs無法提供包過濾、地址偽裝、SNAT等功能,所以某些場景下(比如NodePort的實現)還要與iptables搭配使用。