kube-proxy與iptables
kube-proxy
kube-proxy是一個執行在k8s cluster中的worker node中,負責讓流量可以正確被傳送到Pod上的Component。
不知道大家有沒有想過,為什麼我們在建立Service後拿到的ClusterIP可以直接打到Pod上,中間是藉由什麼方式達成的?其實都是靠這個kube-proxy來替我們做到的,而它後面有以下三種模式來達成
- userspace
- iptables
- ipvs
如果我們不特別去修改ProxyMode,預設就會使用iptables的方式。在使用iptables做為ProxyMode時,一但有新的service或endpoints被建立時,就會去修改iptables。我們可以在iptables nat的表格中看到封包都怎麼轉發的。
iptables簡介
擁有三個大項:
- 表(Tables)
- 鏈(chain)
- 規則(rules)
而表又分成了四種,
- filter: 通常是用來過濾封包。(預設的表)
- nat: 用於位址轉換(來源IP[SNAT] 與 目標IP[DNAT])
- mangle: 用於處理封包
- raw: 用於處理異常
以下為列出iptables的command
# 列出預設表格(filter)的iptables
iptables -L# 列出NAT表格的iptables
iptables -L -t nat
Deployment & Service
雖然知道會去kube-proxy會去修改iptables來處理封包的轉發,但對iptables不太熟悉,所以一直都沒有實際往下追。趁著這次機會重新來好好的認識kube-proxy是怎麼跟iptables合作的。
建立一個deployment: nginx與service來試試
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
kube-proxy — iptables
我們來看看kube-proxy是怎麼幫助我們轉發Service的資料,以下截取部分的iptables的資料
$ sudo iptables -L -t nat
...
Chain KUBE-SVC-V2OKYYMBY3REGZOG (1 references)
target prot opt source destination
KUBE-SEP-X7WBOA4PTAJA3GNK all -- anywhere anywhere /* default/nginx-service */ statistic mode random probability 0.33333333349
KUBE-SEP-I53TFYWHN2OKR6FH all -- anywhere anywhere /* default/nginx-service */ statistic mode random probability 0.50000000000
KUBE-SEP-WU6475GP2VYJZBGF all -- anywhere anywhere /* default/nginx-service */Chain KUBE-SEP-X7WBOA4PTAJA3GNK (1 references)
target prot opt source destination
KUBE-MARK-MASQ all -- 192.168.104.146 anywhere /* default/nginx-service */
DNAT tcp -- anywhere anywhere /* default/nginx-service */ tcp DNAT [unsupported revision]
...
💡 一開始只有使用 sudo iptables -L
的方式,想來找kube-proxy修改的部分。但一直都沒找到,後來發現直接下 -L 不使用 -t
指定 table的話預設為filter
在我們YAML的設計中,deployment的replicas設定為3。iptables的rules是從上到下執行的,我們可以看到在 Chain KUBE-SVC-V2OKYYMBY3REGZOG 的第一條rule,觸發的機率是 0.33,後面一條為0.5。乍看之下好像怪怪的,但其實是很平均的。
讓我們來精算一下
- 33.33 % (這應該沒懸念)
- 此時要選到第二條的機率看似 50%,但因為前面已經先有 33.33%了。所以結果是 (100% — 33%) * 0.5 大約也是33.33 %
- 如果前面都沒選到,就直接最後一條。
來看看 KUBE-SEP-X7WBOA4PTAJA3GNK(192.168.104.146
) 會將封包發送的目標IP是不是pod的endpoints
$ kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 10.140.0.25:6443 24h
nginx-service 192.168.104.146:80,192.168.104.147:80,192.168.238.78:80 75m$ kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-66b6c48dd5-d8jvg 1/1 Running 0 79m 192.168.104.147 cka-training-master01 <none> <none>
nginx-deployment-66b6c48dd5-g2whs 1/1 Running 0 79m 192.168.104.146 cka-training-master01 <none> <none>
nginx-deployment-66b6c48dd5-wlwg4 1/1 Running 0 79m 192.168.238.78 cka-training-worker01 <none> <none>
Summary
kube-proxy在進入iptables的方式後,其實也慢慢的也在cluster的規模愈來愈大的情況遇到了效能的瓶頸。所以開始有了使用IPVS做底層來處理k8s cluster中的proxy。不過對網路實在有點苦手,下次有機會再來研究看看IPVS的kube-proxy是怎麼回事。