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中

具体实践

[root@dev-master-105 ~]# 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:

[root@dev-master-105 ~]# 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中查询到的一致:

[root@dev-master-105 ~]# kubectl exec -it asa-532345087-td4wp -n qateam sh
sh-4.2# ifconfig 
eth0: flags=4163  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
        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  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10
        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查询得到的结果一致

[root@dev-master-105 ~]# ip link show calicc354b946ce
18: calicc354b946ce@if4:  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发出的报文:

[root@dev-master-105 ~]# 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的信息:

[root@dev-master-105 ~]# 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发送来的报文:

[root@dev-master-105 ~]# 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网卡:

[root@dev-master-105 ~]# 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

你可能感兴趣的:(kubernetes)