1. 程式人生 > 其它 >k8s的內部服務通訊

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中。