1. 程式人生 > >kubernetes calico網路不通的排查思路

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拒絕。 
參考:

http://mp.weixin.qq.com/s/MZIj_cvvtTiAfNf_0lpfTg