一次“不負(fù)責(zé)任”的 K8s 網(wǎng)絡(luò)故障排查經(jīng)驗(yàn)分享

轉(zhuǎn)自公眾號(hào):爾達(dá) Erda
某天晚上,客戶碰到了這樣的問(wèn)題:K8s 集群一直擴(kuò)容失敗,所有節(jié)點(diǎn)都無(wú)法正常加入集群。在經(jīng)過(guò)多番折騰無(wú)解后,客戶將問(wèn)題反饋到我們這里,希望得到技術(shù)支持。該問(wèn)題的整個(gè)排查過(guò)程比較有意思,本文對(duì)其中的排查思路及所用的方法進(jìn)行了歸納整理并分享給大家,希望能夠?qū)Υ蠹以谂挪榇祟悊?wèn)題時(shí)有些幫助和參考。
問(wèn)題現(xiàn)象
運(yùn)維同學(xué)在對(duì)客戶的 K8s 集群進(jìn)行節(jié)點(diǎn)擴(kuò)容時(shí),發(fā)現(xiàn)新增的節(jié)點(diǎn)一直添加失敗。初步排查結(jié)果如下:
-
在新增節(jié)點(diǎn)上,訪問(wèn) K8s master service vip 網(wǎng)絡(luò)不通。 -
在新增節(jié)點(diǎn)上,直接訪問(wèn) K8s master hostIP + 6443 網(wǎng)絡(luò)正常。 -
在新增節(jié)點(diǎn)上,訪問(wèn)其他節(jié)點(diǎn)的容器 IP 可以正常 ping 通。 -
在新增節(jié)點(diǎn)上,訪問(wèn) coredns service vip 網(wǎng)絡(luò)正常。
該客戶使用的 Kubernetes 版本是 1.13.10,宿主機(jī)的內(nèi)核版本是 4.18(centos 8.2)。
問(wèn)題排查過(guò)程
收到該一線同事的反饋,我們已經(jīng)初步懷疑是 ipvs 的問(wèn)題。根據(jù)以往網(wǎng)絡(luò)問(wèn)題排查的經(jīng)驗(yàn),我們先對(duì)現(xiàn)場(chǎng)做了些常規(guī)排查:
-
確認(rèn)內(nèi)核模塊 ip_tables 是否加載(正常) -
確認(rèn) iptable forward 是否默認(rèn) accpet (正常) -
確認(rèn)宿主機(jī)網(wǎng)絡(luò)是否正常(正常) -
確認(rèn)容器網(wǎng)絡(luò)是否正常(正常) -
...
排除了常規(guī)問(wèn)題后,基本可以縮小范圍,下面我們?cè)倮^續(xù)基于 ipvs 相關(guān)層面進(jìn)行排查。
通過(guò) ipvsadm 命令排查
10.96.0.1 是客戶集群 K8s master service vip。
如上圖所示,我們可以發(fā)現(xiàn)存在異常連接,處于 SYN_RECV 的狀態(tài),并且可以觀察到,啟動(dòng)時(shí) kubelet + kube-proxy 是有正常建連的,說(shuō)明是在啟動(dòng)之后,K8s service 網(wǎng)絡(luò)出現(xiàn)了異常。
tcpdump 抓包分析
兩端進(jìn)行抓包,并通過(guò) telnet 10.96.0.1 443 命令進(jìn)行確認(rèn)。
結(jié)論:發(fā)現(xiàn) SYN 包在本機(jī)沒(méi)有發(fā)送出去。
初步總結(jié)
通過(guò)上述操作,我們初步總結(jié):?jiǎn)栴}基本就在 kube-proxy 身上。我們采用了 ipvs 模式,也依賴了 iptables 配置實(shí)現(xiàn)一些網(wǎng)絡(luò)的轉(zhuǎn)發(fā)、snat、drop 等。
根據(jù)以上排查過(guò)程,我們?cè)俅慰s小了范圍,開(kāi)始分析懷疑對(duì)象 kube-proxy。
查看 kube-proxy 日志
如上圖所示:發(fā)現(xiàn)異常日志,iptables-restore 命令執(zhí)行異常。通過(guò) Google、社區(qū)查看,確認(rèn)問(wèn)題。
相關(guān) issue 鏈接可參考:
-
https://github.com/kubernetes/kubernetes/issues/73360 -
https://github.com/kubernetes/kubernetes/pull/84422/files -
https://github.com/kubernetes/kubernetes/pull/82214/files
繼續(xù)深入
通過(guò)代碼查看(1.13.10 版本 pkg/proxy/ipvs/proxier.go:1427),可以發(fā)現(xiàn)該版本確實(shí)沒(méi)有判斷 KUBE-MARK-DROP 是否存在并創(chuàng)建的邏輯。當(dāng)出現(xiàn)該鏈不存在時(shí),會(huì)出現(xiàn)邏輯缺陷,導(dǎo)致 iptable 命令執(zhí)行失敗。
K8s master service vip 不通,實(shí)際容器相關(guān)的 ip 是通的,這種情況出現(xiàn)的原因,與下面的 iptable 規(guī)則有關(guān):
$ iptables -t nat -A KUBE-SERVICES ! -s 9.0.0.0/8 -m comment --comment "Kubernetes service cluster ip + port for masquerade purpose" -m set --match-set KUBE-CLUSTER-IP dst,dst -j KUBE-MARK-MASQ
根因探究
前面我們已經(jīng)知道了 kube-proxy 1.13.10 版本存在缺陷,在沒(méi)有創(chuàng)建 KUBE-MARK-DROP 鏈的情況下,執(zhí)行 iptables-restore 命令配置規(guī)則。但是為什么 K8s 1.13.10 版本跑在 centos8.2 4.18 內(nèi)核的操作系統(tǒng)上會(huì)報(bào)錯(cuò),跑在 centos7.6 3.10 內(nèi)核的操作系統(tǒng)上卻正常呢?
我們查看下 kube-proxy 的源碼,可以發(fā)現(xiàn) kube-proxy 其實(shí)也就是執(zhí)行 iptables 命令進(jìn)行規(guī)則配置。那既然 kube-proxy 報(bào)錯(cuò) iptables-restore 命令失敗,我們就找一臺(tái) 4.18 內(nèi)核的機(jī)器,進(jìn)入 kube-proxy 容器看下情況。
到容器內(nèi)執(zhí)行下 iptables-save 命令,可以發(fā)現(xiàn) kube-proxy 容器內(nèi)確實(shí)沒(méi)有創(chuàng)建 KUBE-MARK-DROP 鏈(符合代碼預(yù)期)。繼續(xù)在宿主機(jī)上執(zhí)行下 iptables-save 命令,卻發(fā)現(xiàn)存在 KUBE-MARK-DROP 鏈。
這里有兩個(gè)疑問(wèn):
-
為什么 4.18 內(nèi)核宿主機(jī)的 iptables 有 KUBE-MARK-DROP 鏈? -
為什么 4.18 內(nèi)核宿主機(jī)的 iptables 規(guī)則和 kube-proxy 容器內(nèi)的規(guī)則不一致?
第一個(gè)疑惑,憑感覺(jué)懷疑除了 kube-proxy,還會(huì)有別的程序在操作 iptables,繼續(xù)擼下 K8s 代碼。
>>> 結(jié)論:發(fā)現(xiàn)確實(shí)除了 kube-proxy,還有 kubelet 也會(huì)修改 iptables 規(guī)則。
具體代碼可以查看:pkg/kubelet/kubelet_network_linux.go
第二個(gè)疑惑,繼續(xù)憑感覺(jué)······Google 一發(fā)撈一下為何 kube-proxy 容器掛載了宿主機(jī) /run/xtables.lock 文件的情況下,宿主機(jī)和容器 iptables 查看的規(guī)則不一致。
>>> 結(jié)論:CentOS 8 在網(wǎng)絡(luò)方面摒棄 iptables,采用 nftables 框架作為默認(rèn)的網(wǎng)絡(luò)包過(guò)濾工具。
至此,所有的謎團(tuán)都解開(kāi)了。
團(tuán)隊(duì)完成過(guò)大量的客戶項(xiàng)目交付,這里有些問(wèn)題可以再解答下:
-
問(wèn)題一:為什么這么多客戶環(huán)境第一次碰到該情況?
因?yàn)樾枰?K8s 1.13.10 + centos 8.2 的操作系統(tǒng),這個(gè)組合罕見(jiàn),且問(wèn)題必現(xiàn)。升級(jí) K8s 1.16.0+ 就不出現(xiàn)該問(wèn)題。
-
問(wèn)題二:為什么使用 K8s 1.13.10 + 5.5 內(nèi)核卻沒(méi)有該問(wèn)題?
因?yàn)榕c centos 8 操作系統(tǒng)有關(guān),我們手動(dòng)升級(jí) 5.5 版本后,默認(rèn)還是使用的 iptables 框架。
可以通過(guò) iptables -v 命令,來(lái)確認(rèn)是否使用 nftables。
題外話:nftables 是何方神圣?比 iptables 好么?這是另一個(gè)值得進(jìn)一步學(xué)習(xí)的點(diǎn),這里就不再深入了。
總結(jié)與感悟
針對(duì)以上的排查問(wèn)題,我們總結(jié)下解決方法:
-
調(diào)整內(nèi)核版本到 3.10(centos 7.6+),或者手動(dòng)升級(jí)內(nèi)核版本到 5.0 +。 -
升級(jí) Kubernetes 版本,確認(rèn) 1.16.10+ 版本沒(méi)有該問(wèn)題。
以上是我們?cè)谶M(jìn)行 Kubernetes 網(wǎng)絡(luò)故障排查中的一點(diǎn)經(jīng)驗(yàn),希望能夠?qū)Υ蠹腋咝挪椋ㄎ辉蛴兴鶐椭?/p>


你可能還喜歡
點(diǎn)擊下方圖片即可閱讀

云原生是一種信仰 ??
關(guān)注公眾號(hào)
后臺(tái)回復(fù)?k8s?獲取史上最方便快捷的 Kubernetes 高可用部署工具,只需一條命令,連 ssh 都不需要!

點(diǎn)擊 "閱讀原文" 獲取更好的閱讀體驗(yàn)!
發(fā)現(xiàn)朋友圈變“安靜”了嗎?

