Kubernetes

[ Kans 3 Study - 3w ] 3. Calico 기본 통신 이해

su''@ 2024. 9. 21. 14:58
CloudNetaStudy - Kubernets Networtk 3기 실습 스터디 게시글입니다.

 

파드 ↔ 파드 간 통신

 

[ 최종 통신 흐름 ]

  • 결론 : 동일 노드 내의 파드 간 통신은 내부에서 직접 통신됨
  • iptables FORWARD Rule 에 정책(허용) 사용
  • calice# 인터페이스에 proxy arp 설정으로 파드에서 바라보는 게이트웨이의 MAC 정보를 파드가 전달 받음
  • 동일 노드 내에 파드 간 통신에서는 tunnel 인터페이스는 미 관여
  • 참고 링크 : Proxy ARP - 링크
 

[오리뎅이의 LAN 통신 이야기 - 5] Proxy ARP가 없다면?

안녕하세요? 오리뎅이입니다.   지난 시간까지 삼 테이블(Routing Table, ARP Table, MAC T...

blog.naver.com

 


 

[ 파드 배포 전 기본 상태 확인 ]

# 네트워크 인터페이스 정보 확인 : 터널(ipip) 인터페이스가 존재!
ip -c -d addr show tunl0
5: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 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

# 네트워크 네임스페이스 확인
lsns -t net

# 네트워크 라우팅 경로 정보 확인
# 이중 bird 는 bird 데몬이 BGP 라우팅 프로토콜에 의해 파드 네트워크 대역을 전달받거나 전달하는 경로 → 각각 노드의 파드 대역입니다
ip -c route | grep bird
blackhole 172.16.158.0/24 proto 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
172.16.184.0/24 via 192.168.10.102 dev tunl0 proto bird onlink

# 아래 tunl0 Iface 에 목적지 네트워크 대역은 ipip 인캡슐레이션에 의해서 각 노드에 전달됩니다 → 각각 노드의 파드 대역입니다
route -n
root@k8s-w1:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
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.184.0    192.168.10.102  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 *
...

# (옵션) iptables rule 갯수 확인 >> iptables rule 이 모든 노드에서 똑같나요? 다른가요?
iptables -t filter -S | grep cali | wc -l
iptables -t nat -S | grep cali | wc -l
네트워크 라우팅 경로 정보를 확인했을 때  blackhole 라우팅은 왜 있을까요?
   →  자신이 관리하는 대역 / blackhole 라우팅이 없으면 라우팅 루프가 발생할 수 있다.

 


 

[ 파드 배포 후 상태 확인 ]

 

  • 노드(k8s-w1)에 파드 2개 생성
    node1-pod2.yaml 노드이름(nodeName)은 kubectl get node 출력되는 Name 을 사용하면 된다.

node1-pod2.yaml
0.00MB

 

  • 파드 생성 후 확인
    # [터미널1] k8s-m 모니터링
    watch -d calicoctl get workloadEndpoint
    
    # [터미널2] k8s-m 모니터링
    # 파드 생성 : 노드의 이름이 다를 경우 아래 yaml 파일 다운로드 후 수정해서 사용하시면 됩니다
    curl -s -O https://raw.githubusercontent.com/gasida/NDKS/main/4/node1-pod2.yaml
    kubectl apply -f node1-pod2.yaml
    
    # 생성된 파드 정보 확인
    kubectl get pod -o wide
    root@k8s-m:~# kubectl get pod -o wide
    NAME   READY   STATUS    RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES
    pod1   1/1     Running   0          34s   172.16.228.78   k8s-w1   <none>           <none>
    pod2   1/1     Running   0          34s   172.16.228.79   k8s-w1   <none>           <none>
    
    # calicoctl 이용한 endpoint 확인 : veth 정보도 출력!
    calicoctl get workloadendpoints
    WORKLOAD   NODE     NETWORKS          INTERFACE
    pod1       k8s-w1   172.16.158.2/32   calice0906292e2
    pod2       k8s-w1   172.16.158.1/32   calibd2348b4f67
     
  • 파드 생성 된 이후 다시 정보 확인
    # 네트워크 인터페이스 정보 확인 : calice#~ 2개 추가됨!, 각각 net ns(네임스페이스) 0, 1로 호스트와 구별됨
    ip -c link
    root@k8s-w1:~# ip -c link
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
        link/ether 02:70:da:68:71:43 brd ff:ff:ff:ff:ff:ff
    3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
        link/ether 08:00:27:1b:e3:db brd ff:ff:ff:ff:ff:ff
    4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
        link/ether 02:42:34:f0:2c:88 brd ff:ff:ff:ff:ff:ff
    5: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
        link/ipip 0.0.0.0 brd 0.0.0.0
    8: calibd2348b4f67@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP mode DEFAULT group default
        link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid cni-348afd47-fece-7c08-4488-9046da1e6139
    9: calice0906292e2@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP mode DEFAULT group default
        link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid cni-3342c988-81a5-ebfa-058d-193dbbcb1d81
    
    # 네트워크 네임스페이스 확인 : 아래 2개 pause(infra 컨테이너)가 각각 파드별로 생성됨 - 위 link-netnsid 0, link-netnsid 1 매칭됨
    lsns -t net
    root@k8s-w1:~# lsns -t net
            NS TYPE NPROCS   PID USER     NETNSID NSFS                                                COMMAND
    4026531840 net     131     1 root  unassigned                                                     /sbin/init
    4026532216 net       2 31336 65535          0 /run/netns/cni-348afd47-fece-7c08-4488-9046da1e6139 /pause
    4026532277 net       2 31372 65535          1 /run/netns/cni-3342c988-81a5-ebfa-058d-193dbbcb1d81 /pause
    
    # 파드의 IP/32bit 호스트 라우팅 대역이 라우팅 테이블에 추가됨
    ip -c route
    root@k8s-w1:~# ip -c route
    172.16.158.1 dev calibd2348b4f67 scope link
    172.16.158.2 dev calice0906292e2 scope link
    ...
    
    # (옵션) iptables rule 갯수 확인 : 필터(filter)에 기본 39 에서 91개로 룰(rule)이 많이 추가 되었다 >> 파드가 많아지면 rule 갯수는? >> 노드별로 똑같나요? 다른가요?
    root@k8s-w1:~# iptables -t filter -S | grep cali | wc -l
    91
    root@k8s-w1:~# iptables -t nat -S | grep cali | wc -l
    15


 

  • 파드에 Shell 접속 후 확인

<pod1>

 

 

<pod2>

 

 


 

 

[ (심화) 파드간 통신 실행 및 확인 ]

  • 파드간 통신 실행 이해를 위한 준비

 

노드에서 실행)
# iptables 필터 테이블에 FORWARD 리스트 중 cali-FORWARD 룰 정보를 필터링해서 watch 로 확인
watch -d -n 1 "iptables -v --numeric --table filter --list FORWARD | egrep '(cali-FORWARD|pkts)'" 

# (마스터노드) 파드 연결된 veth 를 변수를 확인
VETH1=$(calicoctl get workloadEndpoint | grep pod1 | awk '{print $4}')
echo $VETH1
VETH2=$(calicoctl get workloadEndpoint | grep pod2 | awk '{print $4}')
echo $VETH2

# (워커노드1) 위에서 확인한 파드 연결된 veth 를 변수에 지정
VETH1=calice0906292e2
VETH2=calibd2348b4f67

# 노드1 calice# 인터페이스의 proxy arp 설정 확인
# cat /proc/sys/net/ipv4/conf/<자신의 pod1에 연결된 calice# 이름>/proxy_arp
cat /proc/sys/net/ipv4/conf/$VETH1/proxy_arp
cat /proc/sys/net/ipv4/conf/$VETH2/proxy_arp

# 파드1 혹은 파드2에 veth 로 연결된 호스트 네트워크 인터페이스 calice# 중 1개 선택해서 tcpdump
tcpdump -i $VETH1 -nn
tcpdump -i $VETH2 -nn

 

  • 파드1 → 파드2 ping 통신 및 확인
# 파드1 Shell 에서 실행 : 정상 통신!
kubectl exec pod1 -it -- zsh
--------------------
ping -c 10 <파드2 IP>

# 게이트웨이 169.254.1.1 의 MAC 주소를 ARP 에 의해서 학습되었다
ip -c -s neigh

# 노드에서 확인
# iptables 에 기본 FORWARD 는 DROP 이지만, 아래 cali-FORWARD Rule에 의해 허용되며, pkts 카운트가 증가한다
iptables -v --numeric --table filter --list FORWARD | egrep '(cali-FORWARD|pkts)'
watch -d "iptables -v --numeric --table filter --list FORWARD | egrep '(cali-FORWARD|pkts)'"

# 파드1에서 게이트웨이의 IP인 169.254.1.1 의 MAC 주소를 알기 위해서 ARP Request 를 보낸다
# 이때 veth 연결된 calice#~ 에 proxy arp 설정이 되어 있고, 자신의 mac 주소(ee:ee:ee:ee:ee:ee)를 알려주고, 이후 정상 통신됨
tcpdump -i $VETH1 -nn
tcpdump -i $VETH2 -nn
root@k8s-w1:~# tcpdump -i calice0906292e2 -nn
08:25:44.216545 ARP, Request who-has 169.254.1.1 tell 172.16.228.78, length 28
08:25:44.216566 ARP, Reply 169.254.1.1 is-at ee:ee:ee:ee:ee:ee, length 28
08:25:45.144618 IP 172.16.228.78 > 172.16.228.79: ICMP echo request, id 45451, seq 7, length 64
08:25:45.144674 IP 172.16.228.79 > 172.16.228.78: ICMP echo reply, id 45451, seq 7, length 64

# 호스트에서 calice0906292e2 의 MAC 주소 다시 확인
root@k8s-w1:~# ip -c -d link
...
12: calice0906292e2@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP mode DEFAULT group default
    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0 minmtu 68 maxmtu 65535
    veth addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535

 

다음 실습을 위해 파드 삭제 kubectl delete -f node1-pod2.yaml

 

 


 

파드 → 외부(인터넷) 통신

 

[ 최종 통신 흐름 ]

결론 : 파드에서 외부(인터넷) 통신 시에는 해당 노드의 네트워크 인터페이스 IP 주소로 MASQUERADE(출발지 IP가 변경) 되어서 외부에 연결됨

  • calico 기본 설정은 natOutgoing: true 이다. 즉, iptables 에 MASQUERADE Rule(룰) 에 의해서 외부에 연결됨
  • calice# 인터페이스에 proxy arp 설정
  • 파드와 외부간 직접 통신에서는 tunnel 인터페이스는 미 관여

 

[ 파드 배포 전 기본 상태 확인 ]

  • calico 설정 정보 확인 & 노드에 iptables 확인
# 마스터 노드에서 확인 : natOutgoing 의 기본값은 true 이다
calicoctl get ippool -o wide
NAME                  CIDR            NAT    IPIPMODE   VXLANMODE   DISABLED   SELECTOR
default-ipv4-ippool   172.16.0.0/16   true   Always     Never       false      all()

# 노드에서 확인 : 노드에서 외부로 통신 시 MASQUERADE 동작 Rule 확인
iptables -n -t nat --list cali-nat-outgoing
root@k8s-w1:~# 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

ipset list
ipset list cali40masq-ipam-pools

 

 


 

 

[ 파드 배포 전 기본 상태 확인 ]

  • calico 설정 정보 확인 & 노드에 iptables 확인
# 마스터 노드에서 확인 : natOutgoing 의 기본값은 true 이다
calicoctl get ippool -o wide
NAME                  CIDR            NAT    IPIPMODE   VXLANMODE   DISABLED   SELECTOR
default-ipv4-ippool   172.16.0.0/16   true   Always     Never       false      all()

# 노드에서 확인 : 노드에서 외부로 통신 시 MASQUERADE 동작 Rule 확인
iptables -n -t nat --list cali-nat-outgoing
root@k8s-w1:~# 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

ipset list
ipset list cali40masq-ipam-pools

 


 

 

[ 파드 배포 및 외부 통신 확인  ]

  • 노드(k8s-w1)에 파드 1개 생성
    node1-pod1.yaml : : 노드이름(nodeName)은 kubectl get node 출력되는 Name 을 사용하면 된다.
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  nodeName: k8s-w1
  containers:
  - name: pod1
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0

 

  • 파드 생성 후 확인

 

# 파드 생성
curl -O https://raw.githubusercontent.com/gasida/NDKS/main/4/node1-pod1.yaml
kubectl apply -f node1-pod1.yaml

# 생성된 파드 정보 확인
kubectl get pod -o wide

 

  • 외부 통신 확인
    [AWS EC2 k8s-w1] 혹은 [vagrant ssh k8s-w1] 노드 접속 : 통신 전 준비
# 노드에서 실행
# iptables NAT MASQUERADE 모니터링 : pkts 증가 확인
watch -d 'iptables -n -v -t nat --list cali-nat-outgoing'

# (컨트롤플레인 노드) 파드 연결된 veth 를 변수를 확인
VETH1=$(calicoctl get workloadEndpoint | grep pod1 | awk '{print $4}')
echo $VETH1

# (워커노드1) 위에서 확인한 파드 연결된 veth 를 변수에 지정
VETH1=<각자 실습 환경에 따라 다름>
VETH1=calice0906292e2

# 패킷 덤프 실행 >> 어떤 인터페이스에서 패킷 캡쳐 확인이 되나요?
tcpdump -i any -nn icmp
tcpdump -i $VETH1 -nn icmp
tcpdump -i tunl0 -nn icmp
tcpdump -i ens5 -nn icmp    # [실습환경 A Type]
tcpdump -i enp0s8 -nn icmp  # [실습환경 B Type]
tcpdump -i enp0s3 -nn icmp  # [실습환경 B Type]
  • 외부 통신 실행 및 확인
# 파드에서 외부 정상 통신 확인
kubectl exec pod1 -it -- zsh
----------------------------

# 혹은 통신 확인 
pod1> ping -c 10 8.8.8.8

# The right way to check the weather - 링크
curl wttr.in/seoul
curl 'wttr.in/seoul?format=3'
curl 'wttr.in/busan?format=3'
curl -s 'wttr.in/{London,Busan}'
curl v3.wttr.in/Seoul.sxl
curl wttr.in/Moon
curl wttr.in/:help

# 패킷 덤프 내용 확인
tcpdump -i <각자 실습 환경에 따라 다름> -nn icmp
root@k8s-w1:~# tcpdump -i calice0906292e2 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on calice0906292e2, link-type EN10MB (Ethernet), capture size 262144 bytes
09:27:29.236878 IP 172.16.228.82 > 8.8.8.8: ICMP echo request, id 56376, seq 1, length 64
09:27:29.311810 IP 8.8.8.8 > 172.16.228.82: ICMP echo reply, id 56376, seq 1, length 64


# [실습환경 A Type] 아래 192.168.10.101는 노드의 외부(인터넷) 연결된 네트워크 인터페이스의 IP이며, 출발지 IP가 변경되어서 외부로 나감
root@k8s-w1:~# tcpdump -i ens5 -nn icmp
15:37:56.579286 IP 192.168.10.101 > 8.8.8.8: ICMP echo request, id 57122, seq 1, length 64
15:37:56.610585 IP 8.8.8.8 > 192.168.10.101: ICMP echo reply, id 57122, seq 1, length 64

# [실습환경 B Type] 아래 10.0.2.15는 VM의 1번 네트워크 인터페이스의 IP이며, 출발지 IP가 변경되어서 외부로 나감
root@k8s-w1:~# tcpdump -i enp0s3 -nn icmp
06:05:12.356260 IP 10.0.2.15 > 8.8.8.8: ICMP echo request, id 15671, seq 5, length 64
06:05:12.402586 IP 8.8.8.8 > 10.0.2.15: ICMP echo reply, id 15671, seq 5, length 64


# nat MASQUERADE rule 카운트(pkts)가 증가!
## 출발지 매칭은 cali40masq-ipam-pools 을 사용
watch -d 'iptables -n -v -t nat --list cali-nat-outgoing'
root@k8s-w1:~# iptables -n -v -t nat --list cali-nat-outgoing
Chain cali-nat-outgoing (1 references)
 pkts bytes target     prot opt in     out     source               destination
    3   252 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

# IPSET 으로 의 cali40masq-ipam-pools IP 대역 정보 확인 : 172.16.0.0/16 대역임을 확인
ipset list cali40masq-ipam-pools
Name: cali40masq-ipam-pools
Type: hash:net
Revision: 7
Header: family inet hashsize 1024 maxelem 1048576 bucketsize 12 initval 0x97754149
Size in memory: 504
References: 1
Number of entries: 1
Members:
172.16.0.0/16

 

  • (옵션) calico 설정을 natOutgoing: false 로 변경 시
    • calico 설정을 natOutgoing: false 로 변경
      # 마스터노드에서 calico ippools 에서 nat 설정 변경
      calicoctl get ippool default-ipv4-ippool -o yaml
      calicoctl get ippool default-ipv4-ippool -o yaml | sed -e "s/natOutgoing: true/natOutgoing: false/" | calicoctl apply -f -
      
      #
      calicoctl get ippool -owide
      NAME                  CIDR            NAT     IPIPMODE   VXLANMODE   DISABLED   DISABLEBGPEXPORT   SELECTOR   
      default-ipv4-ippool   172.16.0.0/16   false   Always     Never       false      false              all()

    • 변경 후 iptables 정보 화인
      # 기존에 존재하던 MASQ Rule 이 삭제되었다!
      iptables -n -v -t nat --list cali-nat-outgoing
      root@k8s-w1:~# iptables -n -v -t nat --list cali-nat-outgoing
      Chain cali-nat-outgoing (1 references)
       pkts bytes target     prot opt in     out     source               destination
      
      # 파드 생성 후 외부 통신 확인 : 아래 처럼 MASQ 미적용으로 요청 패킷만 있고 응답 패킷은 없다.
      pod1> ping -c 10 8.8.8.8
      
      # 즉, 외부 통신이 불가능하다!
      root@k8s-w1:~# tcpdump -i ens5 -nn icmp   # [실습환경 A Type]
      root@k8s-w1:~# tcpdump -i enp0s3 -nn icmp # [실습환경 B Type]
      tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
      listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes
      09:35:40.715554 IP 172.16.228.83 > 8.8.8.8: ICMP echo request, id 569, seq 1, length 64
      09:35:41.720588 IP 172.16.228.83 > 8.8.8.8: ICMP echo request, id 569, seq 2, length 64
      ...

    • calico 설정을 natOutgoing: true 로 원복
      # 마스터노드에서 calico ippools 에서 nat 설정 변경
      calicoctl get ippool default-ipv4-ippool -o yaml > ippool.yaml
      vi ippool.yaml
      ...
        natOutgoing: true
        
      # 추가된 ippoo.yaml 다시 적용
      calicoctl apply -f ippool.yaml

다음 실습을 위해 파드 삭제 kubectl delete -f node1-pod2.yaml

 


 

다른 노드에서 파드 ↔ 파드간 통신

 

[ 최종 통신 흐름 ]

결론 : 다른 노드 환경에서 파드 간 통신 시에는 IPIP 터널(기본값) 모드를 통해서 이루어 집니다

  • 각 노드에 파드 네트워크 대역은 Bird 에 의해서 BGP 로 광고 전파/전달 되며, Felix 에 의해서 호스트의 라우팅 테이블에 자동으로 추가 및 삭제 됩니다
  • 다른 노드 간의 파드 통신은 tunl0 인터페이스를 통해 IP 헤더에 감싸져서 상대측 노드로 도달 후 tunl0 인터페이스에서 Outer 헤더를 제거하고 내부의 파드와 통신됩니다 - 링크
 

IP in IP - Wikipedia

From Wikipedia, the free encyclopedia IP in IP is an IP tunneling protocol that encapsulates one IP packet in another IP packet. To encapsulate an IP packet in another IP packet, an outer header is added with Source IP, the entry point of the tunnel, and D

en.wikipedia.org

 

  •  실제 패킷 확인 시 Outer IP 헤더와 Inner IP 헤더가 보인다!

  • calico-eth0.pcap

calico-eth0.pcap
0.00MB

 

 

[ 파드 배포 전 기본 상태 확인 ]

  • 노드간 BGP 로 Pod 대역 정보 전파 확인
  • 노드에서 BGP 에 의해서 전달 받은 정보가 호스트 라우팅 테이블에 존재하는지 확인
    # 아래 명령어로 확인 시 나머지 노드들의 파드 대역을 자신의 호스트 라우팅 테이블에 가지고 있고, 해당 경로는 tunl0 인터페이스로 보내게 된다
    route | head -2 ; route -n | grep tunl0
    
    # 마스터노드, 노드1~
    root@k8s-m:~# route | head -2 ; route -n | grep tunl0
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    172.16.46.0     192.168.100.102 255.255.255.192 UG    0      0        0 tunl0
    172.16.197.0    192.168.100.103 255.255.255.192 UG    0      0        0 tunl0
    172.16.228.64   192.168.100.101 255.255.255.192 UG    0      0        0 tunl0
    
    # 노드1
    root@k8s-w1:~# route | head -2 ; route -n | grep tunl0
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    172.16.29.0     192.168.100.10  255.255.255.192 UG    0      0        0 tunl0
    172.16.46.0     192.168.100.102 255.255.255.192 UG    0      0        0 tunl0
    172.16.197.0    192.168.100.103 255.255.255.192 UG    0      0        0 tunl0
    ...

  • 노드의 tunl0 정보 확인
    # 터널 인터페이스에 IP가 할당되어 있고, MTU는 1480(IP헤더 20바이트 추가를 고려)을 사용하며, 현재 TX/RX 카운트는 0 이다
    # Calico 사용 시 파드의 인터페이스도 기본 MTU 1480 을 사용한다
    ifconfig tunl0
    
    # 노드1
    root@k8s-w1:~# ifconfig tunl0
    tunl0: flags=193<UP,RUNNING,NOARP>  mtu 1480
            inet 172.16.228.76  netmask 255.255.255.255
            tunnel   txqueuelen 1000  (IPIP Tunnel)
            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
    
    # 노드2
    root@k8s-w2:~# ifconfig tunl0
    tunl0: flags=193<UP,RUNNING,NOARP>  mtu 1480
            inet 172.16.46.10  netmask 255.255.255.255
            tunnel   txqueuelen 1000  (IPIP Tunnel)
            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


 

 

[ 파드 배포 ]

  • 노드1과 노드2에 각각 파드 1개씩 생성
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  nodeName: k8s-w1
  containers:
  - name: pod1
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
  name: pod2
spec:
  nodeName: k8s-w2
  containers:
  - name: pod2
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0

 

  • 파드 생성 후 확인
# 파드 생성
curl -s -O https://raw.githubusercontent.com/gasida/NDKS/main/4/node2-pod2.yaml
kubectl apply -f node2-pod2.yaml

# calicoctl 이용한 endpoint 확인
calicoctl get workloadendpoints

 

  • 파드간 통신을 처리하는 라우팅 정보 확인 : 각각 상대방 노드의 IP를 게이트웨이로 전달하게 됩니다
route -n | head -2 ; route -n | grep 172.16.

# 노드1
root@k8s-w1:~# route -n | head -2 ; route -n | grep 172.16.
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.16.46.0     192.168.100.102 255.255.255.192 UG    0      0        0 tunl0
...

# 노드2
root@k8s-w2:~# route -n | head -2 ; route -n | grep 172.16.
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.16.228.64   192.168.100.101 255.255.255.192 UG    0      0        0 tunl0
...

 

 


 

[ 파드간 통신 실행 및 확인 ]

  • 파드간 통신 실행 이해를 위한 준비 ⇒ IPIP(IP Protocol 4 허용이 필요, Azure 는 불가능 - Link
  • 지금까지 tunl0 인터페이스가 사용되지 않았는데, 다른 노드의 파드간 통신시에 사용되는지 확인을 해보자

  • 노드1 기준 설명
    # tunl0 인터페이스 TX/RX 패킷 카운트 모니터링 실행
    watch -d 'ifconfig tunl0 | head -2 ; ifconfig tunl0 | grep bytes'
    root@k8s-w1:~# watch -d 'ifconfig tunl0 | head -2 ; ifconfig tunl0 | grep bytes'
    tunl0: flags=193<UP,RUNNING,NOARP>  mtu 1480
            inet 172.16.228.76  netmask 255.255.255.255
            RX packets 0  bytes 0 (0.0 B)
            TX packets 0  bytes 0 (0.0 B)
    
    # (옵션) 패킷 덤프 : calice#
    tcpdump -i -nn <calice#>
    
    # 패킷 덤프 : tunl0
    tcpdump -i tunl0 -nn
    혹은 패킷을 파일로 추출시
    tcpdump -i tunl0 -nn -w /tmp/calico-tunl0.pcap
    
    # 패킷 덤프 : IP 헤더에 상위 프로토콜을 IPIP(4)인 패킷만 필터
    #tcpdump -i <각자 자신의 노드의 eth0> -nn proto 4
    tcpdump -i ens5 -nn proto 4    # [실습환경 A Type]
    tcpdump -i enp0s8 -nn proto 4  # [실습환경 B Type]
    혹은 패킷을 파일로 추출시
    tcpdump -i ens5 -nn proto 4 -w /tmp/calico-ipip.pcap   # [실습환경 A Type]
    tcpdump -i enp0s8 -nn proto 4 -w /tmp/calico-ipip.pcap # [실습환경 B Type]
    
    
    # [실습환경 A Type] 자신의 PC로 패킷 복사
    scp ubuntu@<node 유동공인 IP>:/tmp/calico-ipip.pcap .
    scp ubuntu@3.35.229.92:/tmp/calico-ipip.pcap .
    
    
    # [실습환경 B Type] 자신의 PC로 패킷 복사 : https://github.com/invernizzi/vagrant-scp
    ## vagrant scp 플러그인 설치
    vagrant plugin install vagrant-scp
    vagrant plugin list
    
    ## k8s-w1 VM 내부의 파일을 자신의 PC(호스트)에 복사
    vagrant scp k8s-w1:/tmp/calico-ipip.pcap ./


 

[ 파드1 -> 파드2 통신 및 확인 ]

 

 

 

 

 

 

 

 

다음 실습을 위해 파드 삭제 kubectl delete pod pod1