Kubernetes叢集中的網路_Kubernetes中文社群
本文從一個服務的不同訪問方式入手,分析了Kubernetes叢集中的網路組成,也給出了一個簡單可行的網路效能評估方案。
本文適合對虛擬網橋、iptables以及Kubernetes的相關概念有了解的讀者。
另外Service-Pod流量轉發時提到”iptables轉發”,嚴格說措辭不準確,因為iptables僅負責用資料庫維護了Kernel中Netfilter的hook,這樣表述是為了便於理解。
另外,本文也希望為以下幾個問題找出明確的答案:
- Service-Pod之間轉發流量時,kube-proxy是否承擔流量轉發?kube-proxy的轉發機制是怎麼樣的?
- Service-Pod之間(Service對應多個Pod時)的負載均衡的實現原理是怎麼樣的?是用kube-proxy來做負載均衡嗎?
Kubernetes網路組成分析
從不同訪問方式的資料流上看,一個Kubernetes叢集的網路可以劃分為2部分:
- Kubernetes網路模型實現:如Overlay Network(第三方實現中有Flannel,Contiv等)
- 叢集IP(Cluster IP),用以叢集內服務發現,DNS解析等
本節中的試驗叢集使用Flannel搭建Overlay Network,其他的解決方案沒有本質區別。
為了說明Kubernetes叢集網路,下面來部署一個Nginx服務,同時部署了2個Pod:
$ kubectl create -f https://raw.githubusercontent.com/yangyuqian/k8s-the-hard-way/master/assets/nginx.yaml deployment "nginx-deployment" created service "nginx-service" created
可以直接在主機上用Pod的IP來訪問對應的Pod:
$ kubectl get pod --selector="app=nginx" -o jsonpath='{ .items[*].status.podIP }' 172.30.40.3 172.30.98.4 $ curl 172.30.40.3:80 ... $ curl 172.30.98.4:80 ...
注意:下面“在叢集內”的命令都需要attach到一個Pod裡面才可以執行。
也可以在叢集內,使用Cluster IP來訪問服務:
$ kubectl get services NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 10.254.0.1 <none> 443/TCP 1d nginx-service 10.254.126.60 <none> 8000/TCP 9m $ kubectl run --rm -it curl --image="docker.io/appropriate/curl" sh $ curl 10.254.126.60:8000 ...
如果部署了DNS服務,那麼還可以通過叢集內的域名來訪問對應的服務:
$ curl nginx-service:8000 ...
圖1 上面例子的網路圖解(採用Flannel來搭建Overlay Network)
總結
Service到Pod的流量完全在本機網路中完成,簡單而不失高效。
kube-proxy並不承擔實際的流量轉發工作,實際上,它會從kube-apiserver動態拉取最新的應用與服務狀態資訊,並更新本機上的iptable規則. 即使把kube-proxy停掉,已經生成的規則還是可用的。
Service對多個Pod進行流量轉發時,採用iptable規則來進行負載均衡,上面的例子中,iptable會在兩個Pod中進行分別50%概率的流量轉發。
效能評估
叢集拓撲結構:
測試叢集採用Digital Ocean上2臺VPS,用Flannel搭建Overlay Network,使用vxlan backend, 預設mtu配置。
這裡旨在提供一種網路效能的評估方案,評估結果只能說明當前實驗環境下的Flannel網路效能。
分別對下面3種網路訪問方式,使用qperf做TCP和UDP的頻寬和延遲測試:
- 節點之間
- Pod-Pod之間
- Pod-Service-Pod
實驗 1 節點之間
Node 1上啟動qperf server:
$ qperf
Node 2上測試直接訪問效能:
$ qperf -v ${node1_ip} tcp_bw tcp_lat udp_bw udp_lat conf tcp_bw: bw = 331 MB/sec msg_rate = 5.05 K/sec send_cost = 451 ms/GB recv_cost = 2.05 sec/GB send_cpus_used = 15 % cpus recv_cpus_used = 68 % cpus tcp_lat: latency = 125 us msg_rate = 7.99 K/sec loc_cpus_used = 14 % cpus rem_cpus_used = 14 % cpus udp_bw: send_bw = 2.43 GB/sec recv_bw = 132 MB/sec msg_rate = 4.03 K/sec send_cost = 302 ms/GB recv_cost = 4.05 sec/GB send_cpus_used = 73.5 % cpus recv_cpus_used = 53.5 % cpus udp_lat: latency = 113 us msg_rate = 8.84 K/sec loc_cpus_used = 11 % cpus rem_cpus_used = 9 % cpus conf: loc_node = kube-minion-2 loc_cpu = Intel Xeon E5-2650L v3 @ 1.80GHz loc_os = Linux 3.10.0-514.6.1.el7.x86_64 loc_qperf = 0.4.9 rem_node = kube-minion-1 rem_cpu = Intel Xeon E5-2650L v3 @ 1.80GHz rem_os = Linux 3.10.0-514.6.1.el7.x86_64 rem_qperf = 0.4.9
實驗 2 Pod-Pod之間
部署qperf-server:
$ kubectl create -f https://raw.githubusercontent.com/yangyuqian/k8s-the-hard-way/master/assets/qperf-server.yaml
測試Pod-Pod之間網路:
$ podip=`kubectl get pod --selector="k8s-app=qperf-server" -o jsonpath='{ .items[0].status.podIP }'` $ kubectl run qperf-client -it --rm --image="arjanschaaf/centos-qperf" -- -v $podip -lp 4000 -ip 4001 tcp_bw tcp_lat udp_bw udp_lat conf bw = 170 MB/sec msg_rate = 2.59 K/sec port = 4,001 send_cost = 3.07 sec/GB recv_cost = 3.27 sec/GB send_cpus_used = 52 % cpus recv_cpus_used = 55.5 % cpus tcp_lat: latency = 154 us msg_rate = 6.5 K/sec port = 4,001 loc_cpus_used = 16 % cpus rem_cpus_used = 17 % cpus udp_bw: send_bw = 2.93 GB/sec recv_bw = 42.9 MB/sec msg_rate = 1.31 K/sec port = 4,001 send_cost = 341 ms/GB recv_cost = 17.1 sec/GB send_cpus_used = 100 % cpus recv_cpus_used = 73.5 % cpus udp_lat: latency = 170 us msg_rate = 5.87 K/sec port = 4,001 loc_cpus_used = 17 % cpus rem_cpus_used = 22.5 % cpus conf: loc_node = qperf-client-2392635233-sbwff loc_cpu = Intel Xeon E5-2650L v3 @ 1.80GHz loc_os = Linux 3.10.0-514.6.1.el7.x86_64 loc_qperf = 0.4.9 rem_node = qperf-server-rmjd8 rem_cpu = Intel Xeon E5-2650L v3 @ 1.80GHz rem_os = Linux 3.10.0-514.6.1.el7.x86_64 rem_qperf = 0.4.9
實驗 3 Service-Pod之間
部署qperf-server:
$ kubectl create -f https://raw.githubusercontent.com/yangyuqian/k8s-the-hard-way/master/assets/qperf-server.yaml
測試Pod – Service – Pod網路:
$ kubectl run qperf-client -it --rm --image="arjanschaaf/centos-qperf" -- -v qperf-server -lp 4000 -ip 4001 tcp_bw tcp_lat udp_bw udp_lat conf tcp_bw: bw = 217 MB/sec msg_rate = 3.31 K/sec port = 4,001 send_cost = 1.38 sec/GB recv_cost = 3.11 sec/GB send_cpus_used = 30 % cpus recv_cpus_used = 67.5 % cpus tcp_lat: latency = 157 us msg_rate = 6.38 K/sec port = 4,001 loc_cpus_used = 15 % cpus rem_cpus_used = 14.5 % cpus udp_bw: send_bw = 1.28 GB/sec recv_bw = 7.83 MB/sec msg_rate = 239 /sec port = 4,001 send_cost = 693 ms/GB recv_cost = 69.6 sec/GB send_cpus_used = 89 % cpus recv_cpus_used = 54.5 % cpus udp_lat: latency = 140 us msg_rate = 7.12 K/sec port = 4,001 loc_cpus_used = 17.5 % cpus rem_cpus_used = 11 % cpus conf: loc_node = qperf-client-3660233240-w0nq9 loc_cpu = Intel Xeon E5-2650L v3 @ 1.80GHz loc_os = Linux 3.10.0-514.6.1.el7.x86_64 loc_qperf = 0.4.9 rem_node = qperf-server-rmjd8 rem_cpu = Intel Xeon E5-2650L v3 @ 1.80GHz rem_os = Linux 3.10.0-514.6.1.el7.x86_64 rem_qperf = 0.4.9
評估結論
使用Flannel vxlan backend前提下,採用預設mtu配置,Overlay Network的轉發延遲在微妙量級,頻寬有一定影響(減半)。