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搭配使用。