KubeCon 18會議分享 -- k8s網路複雜性和診斷
在剛剛過去的北美KubeCon 18中,有一位來自Redhat的老哥分享了k8s網路的診斷的方法,阿里雲容器服務在客戶問題中有挺多是網路的問題,這個分享可以幫助在使用k8s網路遇到問題時的診斷流程。
為啥k8s網路那麼複雜
首先介紹了k8s網路為啥這麼複雜,都有哪些考慮到的地方,這部分介紹的很多內容也是我們團隊在做網路時遇到的一些坑。
k8s網路方案設計需要考慮很多方面:
- 宿主機間的網路:是採用純硬體的網路還是虛擬的網路(例如openstack)的vxlan,關係到宿主機的效能以及容器網路可以選擇的方案,比如宿主機是虛擬網路的話容器網路一般只能採用overlay的方案。
- 容器間網路:採用Overlay(封包成宿主機的包)的網路還是 Non-overlay的網路以及各自的效能和限制,容器的IP地址管理,容器的網路訪問控制(Network Policy), 網路頻寬管理(Qos/Traffic sharping)
- K8S本身的網路結構適配:負載均衡(kube-proxy...), K8S的Network Policy, Ingress服務等等。
需要協調很多層次的網路元件:
- 容器網路的包會被各個層次去修改,在容器中會有istio等service mesh元件, 在宿主機上也會有kube-proxy/kubelet會修改包的源/目的地址等等
- 需要考慮到底層網路的一些限制,比如頻寬限制,比如arp劫持/防欺騙等等
k8s網路配置過程以及診斷:
上面講了很多網路的複雜度,下面講師以kubeadm為例介紹了網路的配置過程,針對配置的過程以及每一步做的事情和完成的原因可以瞭解網路初始化的過程,方便出現問題時排查:
大體上的k8s網路從叢集初始化到ready是這樣的流程:
- 先是叢集創建出來,節點加入到叢集中,這個時候每個節點(kubelet)都通過宿主機網路連通到master節點的管控的元件(apiserver等)上。這個時候在叢集中能看到節點列表(kubectl get node),但是每個節點都是NotReady的狀態,這個時候非Host網路的Pod都會在Pending狀態,因為沒有節點網路是Ready的,如下圖Coredns就是Pending的,說明宿主機的網路已經聯通了,但是容器網路還沒有好:
-
然後每個節點再配置CNI的plugin和配置,比如最常見的我們通過flannel的模板部署flannel的外掛,節點在監聽到外掛和配置存在時會上報狀態,這個時候整個節點的網路才ready,這時候k8s會將需要容器網路的容器排程到ready的節點上,Pending狀態就會變成Creating狀態,然後由節點上的kubelet再呼叫CNI外掛去配置容器的網路,容器就能變成Running狀態,這個時候容器的網路也就Ready了:
容器網路配置這一步會有哪些問題呢?
在CNI外掛和配置檔案安裝到節點上後,節點就會變成ready了,就會有容器排程到節點上,但不一定容器能正確執行:
- CNI外掛執行失敗了,容器一直在Creating,通過kubelet日誌或者容器事件可以看到cni的報錯
- CNI外掛執行沒問題,容器也能變成Running,但是容器網路通訊不行(容器間,容器和宿主機(健康檢查等)
對於第一種情況:
我們能看到的現象是這樣的:容器一直在Creating,通過kubelet日誌或者容器事件可以看到cni的報錯
對於第二種情況:
通常可以通過健康檢查日誌或者容器本身的網路請求的日誌看到容器網路是不連通的:
如何排查這些問題:
對於容器網路不通的情況,我們要如何排查呢,這裡講師介紹了一些簡單的容器虛擬化網路和排查的知識,可以從中入手:
如何區分容器的網絡卡
ip -d -d link show dev {網絡卡名} 這個命令可以看到網絡卡的型別以及詳細的一些資訊,比如
cni0是一個bridge裝置,可以比作物理網路中的交換機
這個截圖是在容器內部執行的,容器的eth0網絡卡,是一個veth型別的裝置,veth是用來聯通不同的namespace的,通常用來聯通容器和宿主機的網橋,後面的if33代表它聯通的另外一端的網絡卡的編號,到宿主機的namespace中執行ip -d link show我們就能看到這個網絡卡編號對應的網絡卡
如果有的容器沒有ip 命令,那我們要怎麼進到容器中排查呢?可以通過nsenter的命令進入到容器的網路名稱空間操作,例如:
其中的pid就是容器程序的ID,PID可以通過ps -ef | grep <容器程序>,也可以通過kubectl get pod -o yaml | grep containerID , 然後docker inspect 來找到對應的pid。
排查Iptables:
很多時候遇到網路配置成功,但是容器網路不通的問題都是iptables在從中作梗,比如增加了什麼防火牆規則,Chain的Policy被改掉啦之類的。
iptables工作的地方:
容器程序訪問網路時,會首先經過容器內部的iptables,然後到宿主機上面,在宿主機上面會通過宿主機的iptables和routing最終決定包的取捨和去向。
那麼誰會新增iptables規則呢?
答案是誰都會。。。
iptables新增為了幾個功能: 負載均衡(在PREROUTING中去做DNAT+RAMDOM), 訪問控制(在FORWARD/INPUT/OUTPUT)中去做限制, 源地址裝換(POSTROUTING中轉換成宿主機的IP地址)等等
最後介紹抓包大法:
上面的介紹可見網路的過程和複雜度,但是通常排查時沒辦法一條一條規則的順著去排查,何況規則還是由那麼多元件操控隨時會變化,這時候可以使用抓包工具排查在哪一層包被丟掉了來一一排除的解決問題:
我們可以在不同層次的網絡卡上抓包來看到底包丟在什麼地方,或者被改成了啥熊樣。
在容器服務這邊,通常情況下,我們採用tcpdump的方式通過容器IP等過濾條件抓包排查,如果需要詳細的包的解析,可以tcpdump -w寫到檔案中,然後通過wireshark去解析,這裡講師展示了另外一個工具: kokotap
可以建立一個拷貝的介面,將容器的流量也匯入到這個介面上方便wireshark直接在宿主機上也能抓到容器的包。
總結
整個分享就是這些,這個分享中前面介紹了很多k8s網路的複雜度,這塊介紹的比較全面,我們在做網路外掛時在那些點上也都會遇到一些坑,在後面的介紹中主要是網路排查的入門以及工具,通過這些工具可以上手排查問題了,但排查到現象後具體的原因沒有詳細介紹,可能因為遇到的問題場景就太多了,大家可以在排查的過程中多多增加經驗。
容器服務在k8s網路上有深入的實踐,另外有開源的網路外掛Terway,覆蓋了k8s網路的方方面面,這是之前的介紹文章 ofollow,noindex" target="_blank">https://www.atatech.org/articles/102813 。