Kubernetes 選擇 IPVS

什麼是 IPVS ?nginx

IPVS (IP Virtual Server)是在 Netfilter 上層構建的,並做爲 Linux 內核的一部分,實現傳輸層負載均衡。算法

IPVS 集成在 LVS(Linux Virtual Server,Linux 虛擬服務器)中,它在主機上運行,並在物理服務器集羣前做爲負載均衡器。IPVS 能夠將基於 TCP 和 UDP 服務的請求定向到真實服務器,並使真實服務器的服務在單個IP地址上顯示爲虛擬服務。 所以,IPVS 天然支持 Kubernetes 服務。服務器

爲何爲 Kubernetes 選擇 IPVS ?網絡

隨着 Kubernetes 的使用增加,其資源的可擴展性變得愈來愈重要。特別是,服務的可擴展性對於運行大型工做負載的開發人員/公司採用 Kubernetes 相當重要。數據結構

Kube-proxy 是服務路由的構建塊,它依賴於通過強化攻擊的 iptables 來實現支持核心的服務類型,如 ClusterIP 和 NodePort。 可是,iptables 難以擴展到成千上萬的服務,由於它純粹是爲防火牆而設計的,而且基於內核規則列表。負載均衡

儘管 Kubernetes 在版本v1.6中已經支持5000個節點,但使用 iptables 的 kube-proxy 其實是將集羣擴展到5000個節點的瓶頸。 一個例子是,在5000節點集羣中使用 NodePort 服務,若是咱們有2000個服務而且每一個服務有10個 pod,這將在每一個工做節點上至少產生20000個 iptable 記錄,這可能使內核很是繁忙。oop

另外一方面,使用基於 IPVS 的集羣內服務負載均衡能夠爲這種狀況提供不少幫助。 IPVS 專門用於負載均衡,並使用更高效的數據結構(哈希表),容許幾乎無限的規模擴張。spa

基於 IPVS 的 Kube-proxy設計

參數更改代理

參數: –proxy-mode 除了現有的用戶空間和 iptables 模式,IPVS 模式經過–proxy-mode = ipvs 進行配置。 它隱式使用 IPVS NAT 模式進行服務端口映射。

參數: –ipvs-scheduler

添加了一個新的 kube-proxy 參數來指定 IPVS 負載均衡算法,參數爲 –ipvs-scheduler。 若是未配置,則默認爲 round-robin 算法(rr)。

  • rr: round-robin
  • lc: least connection
  • dh: destination hashing
  • sh: source hashing
  • sed: shortest expected delay
  • nq: never queue

未來,咱們能夠實現特定於服務的調度程序(可能經過註釋),該調度程序具備更高的優先級並覆蓋該值。

參數: –cleanup-ipvs 相似於 –cleanup-iptables 參數,若是爲 true,則清除在 IPVS 模式下建立的 IPVS 配置和 IPTables 規則。

參數: –ipvs-sync-period 刷新 IPVS 規則的最大間隔時間(例如’5s’,’1m’)。 必須大於0。

參數: –ipvs-min-sync-period 刷新 IPVS 規則的最小間隔時間間隔(例如’5s’,’1m’)。 必須大於0。

參數: –ipvs-exclude-cidrs 清除 IPVS 規則時 IPVS 代理不該觸及的 CIDR 的逗號分隔列表,由於 IPVS 代理沒法區分 kube-proxy 建立的 IPVS 規則和用戶原始規則 IPVS 規則。 若是您在環境中使用 IPVS proxier 和您本身的 IPVS 規則,則應指定此參數,不然將清除原始規則。

設計注意事項

IPVS 服務網絡拓撲

建立 ClusterIP 類型服務時,IPVS proxier 將執行如下三項操做:

  • 確保節點中存在虛擬接口,默認爲 kube-ipvs0
  • 將服務 IP 地址綁定到虛擬接口
  • 分別爲每一個服務 IP 地址建立 IPVS 虛擬服務器

這是一個例子:

# kubectl describe svc nginx-service
Name:           nginx-service
...
Type:           ClusterIP
IP:             10.102.128.4
Port:           http    3080/TCP
Endpoints:      10.244.0.235:8080,10.244.1.237:8080
Session Affinity:   None

# ip addr
...
73: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 1a:ce:f5:5f:c1:4d brd ff:ff:ff:ff:ff:ff
    inet 10.102.128.4/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever

# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn     
TCP  10.102.128.4:3080 rr
  -> 10.244.0.235:8080            Masq    1      0          0         
  -> 10.244.1.237:8080            Masq    1      0          0

請注意,Kubernetes 服務和 IPVS 虛擬服務器之間的關係是「1:N」。 例如,考慮具備多個 IP 地址的 Kubernetes 服務。 外部 IP 類型服務有兩個 IP 地址 - 集羣IP和外部 IP。 而後,IPVS 代理將建立2個 IPVS 虛擬服務器 - 一個用於集羣 IP,另外一個用於外部 IP。 Kubernetes 的 endpoint(每一個IP +端口對)與 IPVS 虛擬服務器之間的關係是「1:1」。

刪除 Kubernetes 服務將觸發刪除相應的 IPVS 虛擬服務器,IPVS 物理服務器及其綁定到虛擬接口的 IP 地址。

端口映射

IPVS 中有三種代理模式:NAT(masq),IPIP 和 DR。 只有 NAT 模式支持端口映射。 Kube-proxy 利用 NAT 模式進行端口映射。 如下示例顯示 IPVS 服務端口3080到Pod端口8080的映射。

TCP  10.102.128.4:3080 rr
  -> 10.244.0.235:8080            Masq    1      0          0         
  -> 10.244.1.237:8080            Masq    1      0

會話關係

IPVS 支持客戶端 IP 會話關聯(持久鏈接)。 當服務指定會話關係時,IPVS 代理將在 IPVS 虛擬服務器中設置超時值(默認爲180分鐘= 10800秒)。 例如:

# kubectl describe svc nginx-service
Name:           nginx-service
...
IP:             10.102.128.4
Port:           http    3080/TCP
Session Affinity:   ClientIP

# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.102.128.4:3080 rr persistent 10800

IPVS 代理中的 Iptables 和 Ipset

IPVS 用於負載均衡,它沒法處理 kube-proxy 中的其餘問題,例如 包過濾,數據包欺騙,SNAT 等

IPVS proxier 在上述場景中利用 iptables。 具體來講,ipvs proxier 將在如下4種狀況下依賴於 iptables:

  • kube-proxy 以 –masquerade-all = true 開頭
  • 在 kube-proxy 啓動中指定集羣 CIDR
  • 支持 Loadbalancer 類型服務
  • 支持 NodePort 類型的服務

可是,咱們不想建立太多的 iptables 規則。 因此咱們採用 ipset 來減小 iptables 規則。 如下是 IPVS proxier 維護的 ipset 集表:

設置名稱 成員 用法
KUBE-CLUSTER-IP 全部服務 IP + 端口 masquerade-all=true 或 clusterCIDR 指定的狀況下進行假裝 KUBE-LOOP-BACK 全部服務 IP +端口+ IP 解決數據包欺騙問題
KUBE-EXTERNAL-IP 服務外部 IP +端口 將數據包假裝成外部 IP
KUBE-LOAD-BALANCER 負載均衡器入口 IP +端口 將數據包假裝成 Load Balancer 類型的服務
KUBE-LOAD-BALANCER-LOCAL 負載均衡器入口 IP +端口 以及 externalTrafficPolicy=local 接受數據包到 Load Balancer externalTrafficPolicy=local KUBE-LOAD-BALANCER-FW 負載均衡器入口 IP +端口 以及 loadBalancerSourceRanges 使用指定的 loadBalancerSourceRanges 丟棄 Load Balancer類型Service的數據包 KUBE-LOAD-BALANCER-SOURCE-CIDR 負載均衡器入口 IP +端口 + 源 CIDR 接受 Load Balancer 類型 Service 的數據包,並指定loadBalancerSourceRanges KUBE-NODE-PORT-TCP NodePort 類型服務 TCP 將數據包假裝成 NodePort(TCP)
KUBE-NODE-PORT-LOCAL-TCP NodePort 類型服務 TCP 端口,帶有 externalTrafficPolicy=local 接受數據包到 NodePort 服務 使用 externalTrafficPolicy=local KUBE-NODE-PORT-UDP NodePort 類型服務 UDP 端口 將數據包假裝成 NodePort(UDP)
KUBE-NODE-PORT-LOCAL-UDP NodePort 類型服務 UDP 端口 使用 externalTrafficPolicy=local 接受數據包到NodePort服務 使用 externalTrafficPolicy=local

一般,對於 IPVS proxier,不管咱們有多少 Service/ Pod,iptables 規則的數量都是靜態的。

在 IPVS 模式下運行 kube-proxy

目前,本地腳本,GCE 腳本和 kubeadm 支持經過導出環境變量(KUBE_PROXY_MODE=ipvs)或指定標誌(–proxy-mode=ipvs)來切換 IPVS 代理模式。 在運行IPVS 代理以前,請確保已安裝 IPVS 所需的內核模塊。

ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack_ipv4

最後,對於 Kubernetes v1.10,「SupportIPVSProxyMode」 默認設置爲 「true」。 對於 Kubernetes v1.11 ,該選項已徹底刪除。 可是,您須要在v1.10以前爲Kubernetes 明確啓用 –feature-gates = SupportIPVSProxyMode = true。

相關文章
相關標籤/搜索