环境准备
查看节点状态
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
calico-vxlan-control-plane NotReady control-plane,master 3m59s v1.23.17 172.18.0.4 <none> Debian GNU/Linux 12 (bookworm) 6.5.0-35-generic containerd://1.7.13
calico-vxlan-worker NotReady <none> 3m19s v1.23.17 172.18.0.2 <none> Debian GNU/Linux 12 (bookworm) 6.5.0-35-generic containerd://1.7.13
calico-vxlan-worker2 NotReady <none> 3m32s v1.23.17 172.18.0.3 <none> Debian GNU/Linux 12 (bookworm) 6.5.0-35-generic containerd://1.7.13
下载 Calico 清单文件
$ wget https://raw.githubusercontent.com/projectcalico/calico/v3.25.2/manifests/calico-vxlan.yaml
编辑calico-vxlan.yaml
文件,修改以下配置
4574 # Enable or Disable VXLAN on the default IP pool.
4575 - name: CALICO_IPV4POOL_VXLAN
4576 value: "Always"
应用清单文件
$ kubectl apply -f ./calico-vxlan.yaml
查看创建的 Pod
$ kubectl -n kube-system get pod -l k8s-app=calico-node
NAME READY STATUS RESTARTS AGE
calico-node-5d5cf 1/1 Running 0 8m41s
calico-node-ktw42 1/1 Running 0 8m41s
calico-node-rhlb9 1/1 Running 0 8m41s
$ kubectl -n kube-system get pod -l k8s-app=calico-kube-controllers
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-7fcf54d9fb-q9lhg 1/1 Running 0 9m8s
确保节点处于 Ready 状态
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
calico-vxlan-control-plane Ready control-plane,master 10m v1.23.17 172.18.0.4 <none> Debian GNU/Linux 12 (bookworm) 6.5.0-35-generic containerd://1.7.13
calico-vxlan-worker Ready <none> 9m37s v1.23.17 172.18.0.2 <none> Debian GNU/Linux 12 (bookworm) 6.5.0-35-generic containerd://1.7.13
calico-vxlan-worker2 Ready <none> 9m50s v1.23.17 172.18.0.3 <none> Debian GNU/Linux 12 (bookworm) 6.5.0-35-generic containerd://1.7.13
创建测试 Pod
$ kubectl create deployment test --image nginx:alpine --port 80 --replicas 4
deployment.apps/test created
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-578c4f7954-bc6q4 1/1 Running 0 56s 10.244.177.66 calico-vxlan-worker <none> <none>
test-578c4f7954-d8bqc 1/1 Running 0 56s 10.244.110.65 calico-vxlan-control-plane <none> <none>
test-578c4f7954-ff9m7 1/1 Running 0 56s 10.244.70.197 calico-vxlan-worker2 <none> <none>
test-578c4f7954-kt4lz 1/1 Running 0 56s 10.244.177.65 calico-vxlan-worker <none> <none>
同节点 Pod 间通信
10.244.177.66 => 10.244.177.65
查看源 Pod 的路由表
$ kubectl exec -it test-578c4f7954-bc6q4 -- sh
/ # ip route
default via 169.254.1.1 dev eth0
169.254.1.1 dev eth0 scope link
- 默认网关是 169.254.1.1。它是 169.254.0.0/16 范围内的链路本地地址,仅用于广播域中的主机通信
- Pod 需要知道该 IP 地址对应的 MAC 地址,因此会发送一个 ARP 请求,ARP 请求到达对端的 veth 接口(节点的网络命名空间),该 veth 接口启用了 Proxy ARP,使其行为就像网关一样,响应 169.254.1.1 的 ARP 请求并返回自己的 MAC 地址,而不需要在接口上配置网关地址,这样做能够节省宝贵的 IP 地址
查看源 Pod 对端 veth 接口的索引号
/ # ethtool -S eth0
NIC statistics:
peer_ifindex: 6
查看该 veth 接口
root@calico-vxlan-worker:/# ip addr show cali66aab13841c
6: cali66aab13841c@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netns cni-f37e1ef9-ec00-4e76-3b22-ec7ffd4c9cd3
inet6 fe80::ecee:eeff:feee:eeee/64 scope link
valid_lft forever preferred_lft forever
cali* 接口的 MAC 地址都是 ee:ee:ee:ee:ee:ee,这是由 Calico 分配的,因为同节点 Pod 间的通信不使用 Linux 网桥,而是直接通过节点上的路由。节点可以看作一台路由器。路由器不会用 MAC 地址标识目标设备,因此 cali* 接口使用相同的 MAC 地址不会冲突
验证该 veth 接口启用了 Proxy ARP
root@calico-vxlan-worker:/# cat /proc/sys/net/ipv4/conf/cali66aab13841c/proxy_arp
1
查看节点路由表
root@calico-vxlan-worker:/# ip route show 10.244.177.65
10.244.177.65 dev cali44434f702fc scope link
查看cali44434f702fc
对端 veth 接口的索引号
root@calico-vxlan-worker:/# ethtool -S cali44434f702fc
NIC statistics:
peer_ifindex: 3
查看目的 Pod,eth0
即cali44434f702fc
的对端 veth 接口
$ kubectl exec -it test-578c4f7954-kt4lz -- sh
/ # ip addr show eth0
3: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP
link/ether 4a:92:2f:10:fb:82 brd ff:ff:ff:ff:ff:ff
inet 10.244.177.65/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::4892:2fff:fe10:fb82/64 scope link
valid_lft forever preferred_lft forever
网络拓扑如下:
跨节点 Pod 间通信
10.244.110.65 => 10.244.177.66
查看源 Pod 所在节点的路由表
root@calico-vxlan-control-plane:/# ip route | grep 177
10.244.177.64/26 via 10.244.177.64 dev vxlan.calico onlink
查看 vxlan.calico 设备,它是一个 VxLAN 接口
root@calico-vxlan-control-plane:/# ip addr show vxlan.calico
4: vxlan.calico: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
link/ether 66:40:d4:7a:17:07 brd ff:ff:ff:ff:ff:ff
inet 10.244.110.64/32 scope global vxlan.calico
valid_lft forever preferred_lft forever
inet6 fe80::6440:d4ff:fe7a:1707/64 scope link
valid_lft forever preferred_lft forever
root@calico-vxlan-control-plane:/# ip -d link show vxlan.calico
4: vxlan.calico: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/ether 66:40:d4:7a:17:07 brd ff:ff:ff:ff:ff:ff promiscuity 0 allmulti 0 minmtu 68 maxmtu 65535
vxlan id 4096 local 172.18.0.4 dev eth0 srcport 0 0 dstport 4789 nolearning ttl auto ageing 300 udpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 524280 tso_max_segs 65535 gro_max_size 65536
10.244.177.64/32 即对端 VxLAN 接口的地址,VxLAN 接口通过 ARP 请求获取该地址对应的 MAC 地址,作为内层数据包的目的 MAC 地址
抓取数据包
root@calico-vxlan-control-plane:/# tcpdump -i eth0 -w vxlan.pcap
源 Pod 访问目的 Pod
/ # curl 10.244.177.66
网络拓扑如下: