k8s的內部服務通訊
首先看看 k8s 叢集中內部各個服務互相訪問的方法
Cluster IP
Kubernetes以Pod作為應用部署的最小單位。Kubernetes會根據Pod的宣告對其進行排程,包括建立、銷燬、遷移、水平伸縮等,因此Pod的IP地址不是固定的,不方便直接採用Pod IP對服務進行訪問。
為解決該問題,Kubernetes提供了Service資源,Service對提供同一個服務的多個Pod進行聚合。一個Service提供一個虛擬的Cluster IP,後端對應一個或者多個提供服務的Pod。在叢集中訪問該Service時,採用Cluster IP即可,Kube-proxy負責將傳送到Cluster IP的請求轉發到後端的Pod上。
Kube-proxy是一個執行在每個節點上的go應用程式,支援三種工作模式:
userspace 模式
該模式下Kube-proxy會為每一個Service建立一個監聽埠。發向Cluster IP的請求被Iptables規則重定向到Kube-proxy監聽的埠上,Kube-proxy根據LB演算法選擇一個提供服務的Pod並和其建立連結,以將請求轉發到Pod上。 該模式下,Kube-proxy充當了一個四層Load balancer的角色。由於Kube-proxy執行在userspace中,在進行轉發處理時會增加兩次核心和使用者空間之間的資料拷貝,效率較另外兩種模式低一些;好處是當後端的Pod不可用時,Kube-proxy可以重試其他Pod。
iptables 模式
為了避免增加核心和使用者空間的資料拷貝操作,提高轉發效率,Kube-proxy提供了iptables模式。在該模式下,Kube-proxy為service後端的每個Pod建立對應的iptables規則,直接將發向Cluster IP的請求重定向到一個Pod IP。 該模式下Kube-proxy不承擔四層代理的角色,只負責建立iptables規則。該模式的優點是較userspace模式效率更高,但不能提供靈活的LB策略,當後端Pod不可用時也無法進行重試。
ipvs 模式
該模式和iptables類似,Kube-proxy監控Pod的變化並建立相應的ipvs rules。ipvs也是在kernel模式下通過netfilter實現的,但採用了hash table來儲存規則,因此在規則較多的情況下,Ipvs相對iptables轉發效率更高。除此以外,ipvs支援更多的LB演算法。如果要設定Kube-proxy為ipvs模式,必須在作業系統中安裝IPVS核心模組。
現在有兩臺伺服器:
master: 10.0.20.4
node1: 10.0.20.11
在 iptables 模式下看看 kube-dns 究竟是怎麼利用 iptables 來進行解析ip的
[root@master ~]# kubectl get svc -n kube-system -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 2d k8s-app=kube-dns
檢視 kube-system 名稱空間中所有的 pod 名字
[root@master ~]# kubectl get pods -n kube-system -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-66bff467f8-4lw92 1/1 Running 0 2d 10.32.0.3 master <none> <none> coredns-66bff467f8-dt56k 1/1 Running 0 2d 10.32.0.4 master <none> <none> etcd-master 1/1 Running 0 2d 10.0.20.4 master <none> <none> kube-apiserver-master 1/1 Running 0 2d 10.0.20.4 master <none> <none> kube-controller-manager-master 1/1 Running 0 2d 10.0.20.4 master <none> <none> kube-proxy-kqc5s 1/1 Running 0 2d 10.0.20.4 master <none> <none> kube-proxy-x8r85 1/1 Running 0 47h 10.0.20.11 node1 <none> <none> kube-scheduler-master 1/1 Running 0 2d 10.0.20.4 master <none> <none> weave-net-ftqmw 2/2 Running 0 2d 10.0.20.4 master <none> <none> weave-net-wlkkf 2/2 Running 0 47h 10.0.20.11 node1 <none> <none>
上面可以看到 kube-dns 是一個 service,背後的 pod 分別是 coredns-66bff467f8-4lw92 和 coredns-66bff467f8-dt56k
所以
service cluster-ip:10.96.0.10
pod ip:10.32.0.3 和 10.32.0.4
其中 10.96.0.10 作為叢集ip,所有node上都可以進行訪問,那麼我們去 node1 上進行檢視相關的 iptables 是怎樣的
[root@master ~]# iptables-save ...... # 對於 kube-dns 的 service 的iptables # tcp埠 53 轉發到 KUBE-SVC-ERIFXISQEP7F7OF4 規則鏈 # tcp埠 9153 轉發到 KUBE-SVC-JD5MR3NA4I4DYORP 規則鏈 # udp埠 53 轉發到 KUBE-SVC-TCOU7JCQXEZGVUNU 規則鏈 -A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp cluster IP" -m tcp --dport 53 -j KUBE-SVC-ERIFXISQEP7F7OF4 -A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:metrics cluster IP" -m tcp --dport 9153 -j KUBE-SVC-JD5MR3NA4I4DYORP -A KUBE-SERVICES -d 10.96.0.10/32 -p udp -m comment --comment "kube-system/kube-dns:dns cluster IP" -m udp --dport 53 -j KUBE-SVC-TCOU7JCQXEZGVUNU # 以tcp埠53檢視 KUBE-SVC-ERIFXISQEP7F7OF4 規則鏈 # 將從規則鏈 KUBE-SVC-ERIFXISQEP7F7OF4 上過來的流量進行50%的分發到 KUBE-SEP-S4MK5EVI7CLHCCS6 -A KUBE-SVC-ERIFXISQEP7F7OF4 -m comment --comment "kube-system/kube-dns:dns-tcp" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-S4MK5EVI7CLHCCS6 # 其他的流量分發到 KUBE-SEP-ZT5TVM6PMFDFQAMO -A KUBE-SVC-ERIFXISQEP7F7OF4 -m comment --comment "kube-system/kube-dns:dns-tcp" -j KUBE-SEP-ZT5TVM6PMFDFQAMO # 檢視 KUBE-SEP-S4MK5EVI7CLHCCS6 規則鏈 # 將流量重定向到 Pod 10.32.0.3:53 -A KUBE-SEP-S4MK5EVI7CLHCCS6 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp" -m tcp -j DNAT --to-destination 10.32.0.3:53
Kube-proxy並不會直接接收該主機埠進入的流量,而是會建立相應的Iptables規則,並通過Iptables將從該埠收到的流量直接轉發到後端的Pod中。