環境信息:
集羣網絡:10.244.0.0/16
Service網絡: 10.243.0.0/16
節點: 172.16.20.120 , 集羣網絡: 10.244.5.0/24 , cni0: 10.244.5.1/24 ,flannel.1: 10.244.5.0/32
節點: 172.16.20.121 , 集羣網絡: 10.244.3.0/24 , cni0: 10.244.3.1/24 , flannel.1: 10.244.3.0/32nginx
Service是由kube-proxy組件實現,而kube-proxy支持多種負載均衡機制,今天講ipvs模式在kubenertes中的應用。
修改ipvs模式:api
kubectl edit configmap kube-proxy -n kube-system mode: "ipvs"
kube-proxy不能動態生效,須要刪除kube-proxy,後纔會生效網絡
kubectl delete pod kube-proxy-xxx -n kube-system
咱們寫一個測試yml文件 nginx-deploy-svc.yml,以下:app
apiVersion: apps/v1 kind: Deployment metadata: labels: app: lvs-test name: lvs-deploy-test spec: replicas: 3 selector: matchLabels: app: lvs-test template: metadata: labels: app: lvs-test spec: containers: - image: nginx name: lvs-pod-test restartPolicy: Always --- apiVersion: v1 kind: Service metadata: labels: app: lvs-test name: lvs-svc-test spec: ports: - port: 8880 protocol: TCP targetPort: 80 selector: app: lvs-test type: NodePort
部署負載均衡
kubectl apply -f nginx-deploy-svc.yml
獲取svc/deploy/podcurl
# kubectl get svc,pod,deploy -l app=lvs-test -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/lvs-svc-test NodePort 10.243.21.14 <none> 8880:30981/TCP 25m app=lvs-test NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod/lvs-deploy-test-5944d4f9dc-2ljcw 1/1 Running 0 28m 10.244.5.23 cvm-120 <none> <none> pod/lvs-deploy-test-5944d4f9dc-h8l8x 1/1 Running 0 28m 10.244.5.24 cvm-120 <none> <none> pod/lvs-deploy-test-5944d4f9dc-wpqtc 1/1 Running 0 28m 10.244.3.32 cvm-121 <none> <none> NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR deployment.apps/lvs-deploy-test 3/3 3 3 28m lvs-pod-test nginx app=lvs-test
獲取svc詳情tcp
# kubectl describe service/lvs-svc-test Name: lvs-svc-test Namespace: default Labels: app=lvs-test Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"lvs-test"},"name":"lvs-svc-test","namespace":"default"},... Selector: app=lvs-test Type: NodePort IP: 10.243.21.14 Port: <unset> 8880/TCP TargetPort: 80/TCP NodePort: <unset> 30981/TCP Endpoints: 10.244.3.32:80,10.244.5.23:80,10.244.5.24:80 Session Affinity: None External Traffic Policy: Cluster Events: <none>
從上面能夠看到訪問宿主機+30981 (網絡可達宿主機就行),訪問 10.243.21.14:8880 (因爲是vip,非集羣主機不能訪問,只能集羣內部訪問) 時會轉發流量到 10.244.3.32:80,10.244.5.23:80,10.244.5.24:80。 那這種轉發是如何實現的了?
咱們查看lvside
# ipvsadm -L -n (省略部分輸出) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.243.21.14:8880 rr -> 10.244.3.32:80 Masq 1 0 0 -> 10.244.5.23:80 Masq 1 0 0 -> 10.244.5.24:80 Masq 1 0 0
再查看ipvsadm幫助學習
# ipvsadm -L -n --gatewaying -g gatewaying (direct routing) (default) # DR --ipip -i ipip encapsulation (tunneling) # TUN --masquerading -m masquerading (NAT) # NAT # man ipvsadm rr - Round Robin: distributes jobs equally amongst the available real servers. # 輪詢
能夠看到這裏ipvs使用的是NAT模式(NAT模式可參考其餘文章)。測試
測試,在172.16.20.120 執行 curl http://10.243.21.14:8880 ,在各機器抓包
172.16.20.121:flannel.1 , 看到的是10.244.5.0 -> 10.244.3.32:80
172.16.20.121: eth0 , 看到的是 172.16.20.120 -> 172.16.20.121:8472 是flannel進程的端口 , udp ,這裏有一個OTV ,能夠網上查一查
172.16.20.120: flannel.1 ,和 172.16.20.121 flannel.1看到的是同樣的。
再查看nat轉發表, 能夠看到這是fullnat轉發。 另外兩臺是lvs轉發給5.24和5.23的,這是120本地的容器。
執行curl的大體過程以下:
120機器 請求發起:10.243.21.14:48480->10.243.21.14:8880 IPVS-輪詢,目標爲:10.244.3.32:80 根據路由表,下一跳爲 10.244.3.0 ,出口爲flannel.1 ,flannel.1的ip地址爲10.244.5.0 #10.244.3.0 10.244.3.0 255.255.255.0 UG 0 0 0 flannel.1 根據FULLNAT:10.244.5.0:48480->10.244.3.32:80 (稱爲:原始包), 並記錄nat表。# ipv4 2 tcp 6 112 TIME_WAIT src=10.243.21.14 dst=10.243.21.14 sport=48480 dport=8880 src=10.244.3.32 dst=10.244.5.0 sport=80 dport=48480 [ASSURED] mark=0 zone=0 use=2 根據etcd學習到的 10.244.3.0的mac地址爲ee:d6:38:55:d5:c7 ,封裝vxlan , 包格式: vni| 10.244.5.0的mac , 10.244.3.0的mac | 原始ip包 。 (稱爲:vxlan包) # 10.244.3.0 ether ee:d6:38:55:d5:c7 CM flannel.1 根據etcd學習到 10.244.3.0在172.16.20.121節點, 封裝udp包, udp端口 8472. 包格式: udp封裝部分 | xvxlan包 。 121機器收到包,過程也同樣,目標爲121,接收,端口爲 8472 ,接收 , 解封裝, 目標mac爲3.0的,接收,解封裝,目標爲 3.32 ,到達目的地。 反包這裏就再也不抒寫了。 120接到回包解封裝後,爲10.243.3.32:80 -> 10.244.5.0:48480 ,尋找NAT標, 轉發給 10.243.21.14L48480, curl進程接收, 結束。
再測試,從121節點上的 busybox容器 telnet 10.243.21.14 8880
在121節點, flannel.1抓包, 看到的是10.244.3.10:59528 (busybox) -> 10.244.5.23:80
在121節點,查看nat表
在120節點,eth0抓包,172.16.20.121.50813 > 172.16.20.120.8472 , 有一層udp封裝
這裏只作了目標地址轉換, 由於10.244.3.10在各節點是可達的(經過flannel網絡可達)