kubernetes calico網路不通的排查思路
舉個例子
容器A訪問不了容器B,也就是容器A ping 不通容器B
排查思路:
正向
1 容器A的內容是否傳送到容器A所在的node上
2 容器A所在的節點node是否傳送出去
3 容器B所在的節點node是否接收到容器A所在的節點node傳送的報文
4 容器B所在的節點node是否把報文傳送到容器B中
- 反向
1 容器B的內容是否傳送到容器B所在的node上
2 容器B所在的節點node是否傳送出去
3 容器A所在的節點node是否接收到容器B所在的節點node傳送的報文
4 容器A所在的節點node是否把報文傳送到容器A中
具體實踐
[[email protected]
~]# kubectl get pods -owide -n qateam NAME READY STATUS RESTARTS AGE IP NODE asa-532345087-td4wp 1/1 Running 0 1d 192.168.123.209 dev-master-105 aws-3789938515-mkfs5 1/1 Running 1 30d 192.168.123.254 dev-master-105 demo-0 2/2 Running 0 37d 192.168.4.36 dev-slave-110 demo-1-0 2/2 Running 0 37d 192.168.19.20 dev-slave-108 demo22-0 2/2 Running 0 37d 192.168.4.35 dev-slave-110 erfasd-842565593-h94fh 1/1 Running 1 30d 192.168.123.249 dev-master-105 sas-3732401954-fmq45 1/1 Running 1 30d 192.168.123.247 dev-master-105
先用calicoctl檢視容器A的workloadEndpoint:
[[email protected] ~]# calicoctl get workloadendpoint --workload=qateam.asa-532345087-td4wp -oyaml - apiVersion: v1 kind: workloadEndpoint metadata: labels: ClusterID: CID-f794208bc85f UserID: "45" calico/k8s_ns: qateam name: asa pod-template-hash: "532345087" name: eth0 node: dev-master-105 orchestrator: k8s workload: qateam.asa-532345087-td4wp spec: interfaceName: calicc354b946ce ipNetworks: - 192.168.123.209/32 mac: f6:77:d3:29:1a:50 profiles: - k8s_ns.qateam
- 可以看到容器A的相關網路的資訊
1 容器A的繫結的網絡卡 calicc354b946ce
2 容器A的mac地址f6:77:d3:29:1a:50
3 容器的IP地址192.168.123.209/32 所在的節點dev-master-105
檢視容器A內的網絡卡是否正確,ip和mac是否與從calico中查詢到的一致:
[[email protected] ~]# kubectl exec -it asa-532345087-td4wp -n qateam sh
sh-4.2# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.123.209 netmask 255.255.255.255 broadcast 0.0.0.0
inet6 fe80::f477:d3ff:fe29:1a50 prefixlen 64 scopeid 0x20<link>
ether f6:77:d3:29:1a:50 txqueuelen 0 (Ethernet)
RX packets 5041 bytes 13366685 (12.7 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3953 bytes 263623 (257.4 KiB)
TX errors 0 dropped 1 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
可以看到mac地址以及ip地址 跟通過calicoctl 取到的是一致的
檢視容器A的預設路由是否是169.254.1.1,且沒有額外的路由:
sh-4.2# ip route
default via 169.254.1.1 dev eth0
169.254.1.1 dev eth0 scope link
在node上執行,檢視calicc354b946ce的網絡卡的mac地址是否跟之前通過calicoctl查詢得到的結果一致
[[email protected] ~]# ip link show calicc354b946ce
18: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT
link/ether 22:49:04:09:0b:cd brd ff:ff:ff:ff:ff:ff link-netnsid 3
檢視容器A內記錄的169.254.1.1的mac地址是否是node上的calico網絡卡的mac
sh-4.2# ip neigh
169.254.1.1 dev eth0 lladdr 22:49:04:09:0b:cd STALE
這裡需要一點說明,使用calico後,在容器內只有一條預設路由,所有的報文都通過169.254.1.1送出。但是這個IP是RFC約定保留的無效IP,報文怎麼還能送出去呢?
祕密就是容器內的arp記錄,在容器A內記錄的169.254.1.1的mac地址是:
node上的caliXX網絡卡的mac。
node上的caliXX網絡卡和容器內的eth0網絡卡,是一對veth裝置。veth網絡卡的特性是,向eth0寫入的報文,會通過caliXX流出。
在容器A中向eth0寫入的報文,它目的mac是caliXX網絡卡的mac,當報文經caliXX流出時,就 進入到了node的協議棧中,開始在node的網路空間中流轉。
在容器A所在的node上用tcpdump監聽calicc354b946ce網絡卡,檢視是否能夠收到容器A發出的報文:
[[email protected] ~]# tcpdump -i calicc354b946ce
tcpdump: WARNING: calicc354b946ce: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on calicc354b946ce, link-type EN10MB (Ethernet), capture size 65535 bytes
檢查傳送端node上的路由,目標IP的下一跳地址是否正確,目標IP是容器的地址,檢查下一跳是否對應了正確的node ip:
...
192.168.19.0/26 via 10.39.0.105 dev tunl0 proto bird onlink
...
這條路由是通過BGP協議得知的,它的意思是說192.168.19.0/26這個網段可以通過10.39.0.105到達。
然後還需要檢查傳送端node上的iptables規則,看一下iptable是否拒絕了這個報文。
很多元件都會設定iptables規則,有可能是別的元件,譬如docker,設定的規則導致不通。
從calico中獲取接收端容器B的資訊:
[[email protected] ~]# calicoctl get workloadendpoint --workload=qateam.dev-3629875698-b58t6 -oyaml
- apiVersion: v1
kind: workloadEndpoint
metadata:
labels:
ClusterID: CID-f794208bc85f
UserID: "45"
calico/k8s_ns: qateam
name: dev
pod-template-hash: "3629875698"
tenxcloud.com/appName: dev
tenxcloud.com/svcName: dev
name: eth0
node: dev-master-105
orchestrator: k8s
workload: qateam.dev-3629875698-b58t6
spec:
interfaceName: cali9ee0bd99a15
ipNetworks:
- 192.168.123.248/32
mac: 56:eb:69:42:68:d9
profiles:
- k8s_ns.qateam
可以得到容器B的以下資訊:
1.容器的網路介面(網絡卡)cali9ee0bd99a15
2.容器的節點dev-master-105
監聽容器B所在node的網絡卡,檢查是否收到了容器A所在的node傳送來的報文:
[[email protected] ~]# tcpdump -i cali9ee0bd99a15
tcpdump: WARNING: cali9ee0bd99a15: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on cali9ee0bd99a15, link-type EN10MB (Ethernet), capture size 65535 bytes
檢查容器B所在node上的路由,檢查目標IP是否對應了正確的calico網絡卡:
[[email protected] ~]# ip route
...
192.168.123.248 dev cali9ee0bd99a15 scope link
...
前面我們說明了報文如何從容器A到達容器A所在的node,那麼還有一個問題是, 報文又是怎樣從node到達容器內部的呢?
答案是node上的路由。
上面那條路由的意思是,192.168.60.173這個IP對應的網絡卡是caliXXX,報文會被寫入到這個網絡卡中。 這個網絡卡和容器內的網絡卡是一對veth裝置,寫入caliXX的報文會通過容器內的eth0流出,從而進入到容器的網路空間中。
這裡同樣需要檢查接收端node上的iptables規則,看一下報文是否被iptables拒絕。
參考: