1. 程式人生 > >Kubernetes叢集中的網路_Kubernetes中文社群

Kubernetes叢集中的網路_Kubernetes中文社群

本文從一個服務的不同訪問方式入手,分析了Kubernetes叢集中的網路組成,也給出了一個簡單可行的網路效能評估方案。

20170312110318

本文適合對虛擬網橋、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)

20170312111354

總結

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網路效能。

20170312111406

分別對下面3種網路訪問方式,使用qperf做TCP和UDP的頻寬和延遲測試:

  1. 節點之間
  2. Pod-Pod之間
  3. 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的轉發延遲在微妙量級,頻寬有一定影響(減半)。