동일 노드 내 파드 간 통신은 가상 라우터 calico-node를 통해 내부에서 직접 통신된다.
동일 노드 내에 파드를 2개 생성 한 후 통신을 하며 모니터링 해본다.
# IPIP 통신
root@k8s-w1:~# ip -c -d addr show tunl0
5: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 8981 qdisc noqueue state UNKNOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0 promiscuity 0 minmtu 0 maxmtu 0
ipip any remote any local any ttl inherit nopmtudisc numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
inet 172.16.158.0/32 scope global tunl0
valid_lft forever preferred_lft forever
# Pod가 생성되지 않았기에 네트워크 네임스페이스가 존재하지 않는다.
root@k8s-w1:~# lsns -t net
NS TYPE NPROCS PID USER NETNSID NSFS COMMAND
4026531840 net 137 1 root unassigned /sbin/init
# BGP route protocol에 의해 노드 간에 서로 교환하는 정보
# blackhole = 세부 라우팅 설정(longest prefix match)이 없는 경우 노드의 Pod CIDR 대역(여기에서는 172.16.158.0)으로 들어오는 트래픽의 경우 폐기처분을 한다.
root@k8s-w1:~# ip -c route | grep bird
172.16.34.0/24 via 192.168.20.100 dev tunl0 proto bird onlink
172.16.116.0/24 via 192.168.10.10 dev tunl0 proto bird onlink
blackhole 172.16.158.0/24 proto bird
172.16.184.0/24 via 192.168.10.102 dev tunl0 proto bird onlink
# tunl0인터페이스를 통해 상대방 workernode의 Pod 대역과 통신이 가능하다.
root@k8s-w1:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.10.1 0.0.0.0 UG 100 0 0 eth0
172.16.34.0 192.168.20.100 255.255.255.0 UG 0 0 0 tunl0
172.16.116.0 192.168.10.10 255.255.255.0 UG 0 0 0 tunl0
172.16.158.0 0.0.0.0 255.255.255.0 U 0 0 0 *
172.16.184.0 192.168.10.102 255.255.255.0 UG 0 0 0 tunl0
192.168.0.2 192.168.10.1 255.255.255.255 UGH 100 0 0 eth0
192.168.10.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
192.168.10.1 0.0.0.0 255.255.255.255 UH 100 0 0 eth0
calicoctl을 통해서 workload endpoint를 확인해보았을 때, Pod의 정보를 확인할 수 있다.
Pod가 뜬 k8s-w1에서의 라우팅 테이블에도 파드의 IP/32bit 호스트 라우팅 대역이 라우팅 테이블에 추가된 것을 볼 수 있다.
통신 모니터링을 해보면 아래와 같은 순서대로 진행된다.
1) 파드1에서 게이트웨이의 IP인 169.254.1.1 의 MAC 주소를 알기 위해서 ARP Request 를 보낸다.
2) proxy arp 설정이 되어 있는 veth에 연결된 calice에서 자신의 mac 주소(ee:ee:ee:ee:ee:ee)를 응답하고, 이후 정상 통신이 된다.
파드에서 외부(인터넷) 통신 시에는 해당 노드의 네트워크 인터페이스 IP 주소로 MASQUERADE(출발지 IP가 변경) 되어서 외부에 연결된다.
파드에서 외부 통신을 시도하며 모니터링 해본다.
# 기본 설정 : NAT = true
(⎈|kubernetes-admin@kubernetes:N/A) root@k8s-m:~# calicoctl get ippool -o wide
NAME CIDR NAT IPIPMODE VXLANMODE DISABLED DISABLEBGPEXPORT SELECTOR
default-ipv4-ippool 172.16.0.0/16 true Always Never false false all()
# 노드에서 외부 통신 시 MASQUERADE 룰 존재 확인
(⎈|kubernetes-admin@kubernetes:N/A) root@k8s-m:~# iptables -n -t nat --list cali-nat-outgoing
Chain cali-nat-outgoing (1 references)
target prot opt source destination
MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* cali:flqWnvo8yq4ULQLa */ match-set cali40masq-ipam-pools src ! match-set cali40all-ipam-pools dst random-fully
(⎈|kubernetes-admin@kubernetes:N/A) root@k8s-m:~# ipset list cali40masq-ipam-pools
Name: cali40masq-ipam-pools
Type: hash:net
Revision: 7
Header: family inet hashsize 1024 maxelem 1048576 bucketsize 12 initval 0x7c23000b
Size in memory: 504
References: 1
Number of entries: 1
Members:
172.16.0.0/16
1) pod의 VETH인터페이스에서는 pod IP와 외부 대역 간 통신 패킷이 확인된다.
00:58:58.317730 IP 172.16.34.8 > 8.8.8.8: ICMP echo request, id 31, seq 2, length 64
00:58:58.353223 IP 8.8.8.8 > 172.16.34.8: ICMP echo reply, id 31, seq 2, length 64
2) eth0인터페이스에서는 출발지 IP가 노드의 eth0 네트워크 인터페이스 IP로 변경되어 외부로 패킷이 나간다.
00:59:00.320892 IP 192.168.20.100 > 8.8.8.8: ICMP echo request, id 21320, seq 4, length 64
00:59:00.356195 IP 8.8.8.8 > 192.168.20.100: ICMP echo reply, id 21320, seq 4, length 64
3) 외부 통신 시 nat MASQUERADE rule 카운트가 증가하는 것을 확인할 수 있다.
root@k8s-w0:~# iptables -n -v -t nat --list cali-nat-outgoing
Chain cali-nat-outgoing (1 references)
pkts bytes target prot opt in out source destination
7 517 MASQUERADE all -- * * 0.0.0.0/0 0.0.0.0/0 /* cali:flqWnvo8yq4ULQLa */ match-set cali40masq-ipam-pools src ! match-set cali40all-ipam-pools dst random-fully
pod의 VETH인터페이스와 eth0에서와는 달리 터널 인터페이스에서는 패킷이 확인되지 않는다.
다른 노드 간의 파드 통신은 tunl0 인터페이스를 통해 IP 헤더에 감싸져서 상대측 노드로 도달 후 tunl0 인터페이스에서 Outer 헤더를 제거하고 내부의 파드와 통신된다.
파드에서 다른 노드의 파드와 통신을 시도하며 모니터링 해본다.
1) pod의 VETH인터페이스에서는 pod IP와 다른 노드의 Pod IP간 통신 패킷이 확인된다.
01:36:23.770105 IP 172.16.34.9 > 172.16.158.16: ICMP echo request, id 22, seq 5, length 64
01:36:23.772248 IP 172.16.158.16 > 172.16.34.9: ICMP echo reply, id 22, seq 5, length 64
2) tunl0 인터페이스에서도 pod IP와 다른 노드의 Pod IP간 통신 패킷이 확인된다.
01:36:22.768870 IP 172.16.34.9 > 172.16.158.16: ICMP echo request, id 22, seq 4, length 64
01:36:22.771009 IP 172.16.158.16 > 172.16.34.9: ICMP echo reply, id 22, seq 4, length 64
3) eth0 인터페이스에서 노드와 다른 노드 IP간 통신 패킷이 확인된다. IP Outer 헤더 안쪽에 IP 헤더가 하나 더 있는데, 해당 헤더에는 Pod의 출발지, 목적지 IP정보가 존재한다.
01:36:19.764191 IP 192.168.20.100 > 192.168.10.101: IP 172.16.34.9 > 172.16.158.16: ICMP echo request, id 22, seq 1, length 64
01:36:19.765890 IP 192.168.10.101 > 192.168.20.100: IP 172.16.158.16 > 172.16.34.9: ICMP echo reply, id 22, seq 1, length 64