Ssoon

[3주차] Calico Mode : Direct 모드 / CrossSubnet 모드 본문

쿠버네티스 네트워크 스터디 3기

[3주차] Calico Mode : Direct 모드 / CrossSubnet 모드

구구달스 2024. 9. 13. 18:07
CloudNet@ 가시다님이 진행하는 쿠버네티스 네트워크 스터디 3기

✅ Direct 모드

[ k8s-m ]

(⎈|SsoonLab: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()

 

[ k8s-m ]

(⎈|SsoonLab:N/A) root@k8s-m:~# calicoctl get ippool default-ipv4-ippool -o yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  creationTimestamp: "2024-09-13T01:29:35Z"
  name: default-ipv4-ippool
  resourceVersion: "4751"
  uid: 39e31d54-8836-47e7-b5b1-9d2a90d91c26
spec:
  allowedUses:
  - Workload
  - Tunnel
  blockSize: 24
  cidr: 172.16.0.0/16
  ipipMode: Always
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: Never

 

[ k8s-m ]

(⎈|SsoonLab:N/A) root@k8s-m:~# calicoctl get ippool default-ipv4-ippool -o yaml | sed -e "s/ipipMode: Always/ipipMode: Never/" | calicoctl apply -f -
Successfully applied 1 'IPPool' resource(s)

(⎈|SsoonLab:N/A) root@k8s-m:~# calicoctl get ippool default-ipv4-ippool -o yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  creationTimestamp: "2024-09-13T01:29:35Z"
  name: default-ipv4-ippool
  resourceVersion: "44677"
  uid: 39e31d54-8836-47e7-b5b1-9d2a90d91c26
spec:
  allowedUses:
  - Workload
  - Tunnel
  blockSize: 24
  cidr: 172.16.0.0/16
  ipipMode: Never
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: Never

 

[ k8s-m ]

(⎈|SsoonLab: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   Never      Never       false      false              all()

 

[ k8s-m ]

(⎈|SsoonLab:N/A) root@k8s-m:~# route -n | egrep '(Destination|UG)'
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.1    0.0.0.0         UG    100    0        0 ens5
172.16.34.0     192.168.10.1    255.255.255.0   UG    0      0        0 ens5
172.16.158.0    192.168.10.101  255.255.255.0   UG    0      0        0 ens5
172.16.184.0    192.168.10.102  255.255.255.0   UG    0      0        0 ens5
192.168.0.2     192.168.10.1    255.255.255.255 UGH   100    0        0 ens5

 

동작 확인

[ k8s-m ]

  • 각 Node 에 Pod 생성합니다.
(⎈|SsoonLab:N/A) root@k8s-m:~# cat node3-pod3.yaml
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
---
apiVersion: v1
kind: Pod
metadata:
  name: pod3
spec:
  nodeName: k8s-w0
  containers:
  - name: pod3
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
  
(⎈|SsoonLab:N/A) root@k8s-m:~# kubectl apply -f node3-pod3.yaml
pod/pod1 created
pod/pod2 created
pod/pod3 created

 

[ k8s-m ]

  • pod1, pod2, pod3가 각각 k8s-w1, k8s-w2, k8s-w0 노드에서 실행 중이며, 각 파드는 정상적으로 Running 상태입니다.
  • 각 파드는 Calico에 의해 네트워크 인터페이스를 통해 할당된 IP 주소를 가지고 있으며, 각 노드에서의 네트워크 인터페이스 이름도 확인할 수 있습니다.
(⎈|SsoonLab:N/A) root@k8s-m:~# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
pod1   1/1     Running   0          47s   172.16.158.8   k8s-w1   <none>           <none>
pod2   1/1     Running   0          47s   172.16.184.2   k8s-w2   <none>           <none>
pod3   1/1     Running   0          47s   172.16.34.1    k8s-w0   <none>           <none>

(⎈|SsoonLab:N/A) root@k8s-m:~# calicoctl get wep
WORKLOAD   NODE     NETWORKS          INTERFACE
pod1       k8s-w1   172.16.158.8/32   calice0906292e2
pod2       k8s-w2   172.16.184.2/32   calibd2348b4f67
pod3       k8s-w0   172.16.34.1/32    cali49778cadcf1

 

[ pod1 ]

🧿 pod1 Shell 접속하고 pod1 에서 pod2 로 핑 통신을 확인합니다.

(⎈|SsoonLab:N/A) root@k8s-m:~# kubectl exec -it pod1 -- zsh
                    dP            dP                           dP
                    88            88                           88
88d888b. .d8888b. d8888P .d8888b. 88d888b. .d8888b. .d8888b. d8888P
88'  `88 88ooood8   88   Y8ooooo. 88'  `88 88'  `88 88'  `88   88
88    88 88.  ...   88         88 88    88 88.  .88 88.  .88   88
dP    dP `88888P'   dP   `88888P' dP    dP `88888P' `88888P'   dP

Welcome to Netshoot! (github.com/nicolaka/netshoot)
Version: 0.13

 pod1  ~  ping -c 1 172.16.184.2
PING 172.16.184.2 (172.16.184.2) 56(84) bytes of data.
64 bytes from 172.16.184.2: icmp_seq=1 ttl=62 time=0.409 ms

--- 172.16.184.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.409/0.409/0.409/0.000 ms

 

[ k8s-w1 ]

🧿 ens5 네트워크 인터페이스에서 패킷을 캡처합니다.

  • pod1 (172.16.158.8) ▶ pod2 (172.16.184.2) 로 패킷이 (ping 요청) 전송되었습니다.
  • pod2 (172.16.184.2) ▶ pod1 (172.16.158.8) 로 패킷이 (ping 요청에 대한 응답) 전송되었습니다.
root@k8s-w1:~# tcpdump -i ens5 -nn icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens5, link-type EN10MB (Ethernet), snapshot length 262144 bytes
17:30:14.027539 IP 172.16.158.8 > 172.16.184.2: ICMP echo request, id 114, seq 1, length 64
17:30:14.028147 IP 172.16.184.2 > 172.16.158.8: ICMP echo reply, id 114, seq 1, length 64

 

[ k8s-w2 ]

🧿 ens5 네트워크 인터페이스에서 패킷을 캡처합니다.

  • pod1 (172.16.158.8)  pod2 (172.16.184.2) 로 패킷이 (ping 요청) 전송되었습니다.
  • pod2 (172.16.184.2)  pod1 (172.16.158.8) 로 패킷이 (ping 요청에 대한 응답) 전송되었습니다.
root@k8s-w2:~# tcpdump -i ens5 -nn icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens5, link-type EN10MB (Ethernet), snapshot length 262144 bytes
17:30:14.027603 IP 172.16.158.8 > 172.16.184.2: ICMP echo request, id 114, seq 1, length 64
17:30:14.027700 IP 172.16.184.2 > 172.16.158.8: ICMP echo reply, id 114, seq 1, length 64

 

[ pod1 ]

🧿 ens5 네트워크 인터페이스에서 패킷을 캡처합니다.

 pod1  ~  ping -c 1 172.16.34.1
PING 172.16.34.1 (172.16.34.1) 56(84) bytes of data.

--- 172.16.34.1 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

 

[ k8s-w1 ] , [ k8s-w3 ]

🧿 모든 네트워크 인터페이스에서 IPv4 패킷을 캡처합니다.

  • 정보가 표시되지 않습니다.
root@k8s-w1:~# tcpdump -i any proto 4 -nn
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes

root@k8s-w0:~# tcpdump -i any proto 4 -nn
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
  • k8s-w3 (192.168.20.0/24) 은  k8s-w1 (192.168.10.0/24)다른 네트워크 대역으로 라우팅 되는데 라우팅 테이블에 pod (172.16.) 에 대한 라우팅정보가 없어 패킷을 전달하지 못합니다.


 CrossSubnet 모드

🧿 Node 간 같은 네트워크 대역 ▶ Direct 모드로 동작

🧿 Node 간 다른 네트워크 대역   IPIP 모드로 동작

 

[ k8s-m ]

  • Calico의 설정 파일에서 ipipMode를 CrossSubnet으로 설정합니다.
(⎈|SsoonLab:N/A) root@k8s-m:~# calicoctl patch ippool default-ipv4-ippool -p '{"spec":{"ipipMode":"CrossSubnet"}}'
Successfully patched 1 'IPPool' resource

(⎈|SsoonLab:N/A) root@k8s-m:~# calicoctl get ippool default-ipv4-ippool -o yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  creationTimestamp: "2024-09-13T01:29:35Z"
  name: default-ipv4-ippool
  resourceVersion: "54993"
  uid: 39e31d54-8836-47e7-b5b1-9d2a90d91c26
spec:
  allowedUses:
  - Workload
  - Tunnel
  blockSize: 24
  cidr: 172.16.0.0/16
  ipipMode: CrossSubnet
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: Never
  
  (⎈|SsoonLab: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   CrossSubnet   Never       false      false              all()

🧿 라우팅 테이블에서 "UG" 플래그가 붙은 경로들만 필터링합니다.

[ k8s-m ]

  • "UG"는 "Up"과 "Gateway"를 의미하며, 해당 경로가 활성화되어 있고 게이트웨이를 통해 라우팅된다는 것을 나타냅니다.
  • 172.16.34.0 192.168.20.100 255.255.255.0 UG 0 0 0 tunl0
    • pod3 (172.16.34.0) 네트워크로 가는 트래픽은 192.168.20.100 게이트웨이를 통해 tunl0 인터페이스를 사용하여 전달됩니다. IPIP 모드
  • 172.16.158.0 192.168.10.101 255.255.255.0 UG 0 0 0 ens5: 
    • pod1 (172.16.158.0) 네트워크로 가는 트래픽은 192.168.10.101 게이트웨이를 통해 ens5 인터페이스를 사용하여 전달됩니다. ▶ Direct 모드
  • 172.16.184.0 192.168.10.102 255.255.255.0 UG 0 0 0 ens5: 
    • pod2 (172.16.184.0) 네트워크로 가는 트래픽은 192.168.10.102 게이트웨이를 통해 ens5 인터페이스를 사용하여 전달됩니다.  Direct 모드
(⎈|SsoonLab:N/A) root@k8s-m:~# route -n | grep UG
0.0.0.0         192.168.10.1    0.0.0.0         UG    100    0        0 ens5
172.16.34.0     192.168.20.100  255.255.255.0   UG    0      0        0 tunl0
172.16.158.0    192.168.10.101  255.255.255.0   UG    0      0        0 ens5
172.16.184.0    192.168.10.102  255.255.255.0   UG    0      0        0 ens5
192.168.0.2     192.168.10.1    255.255.255.255 UGH   100    0        0 ens5

 

[ pod1 ]

  • pod1 (172.16.158.8)pod3 (172.16.34.1) 로 ping 테스트를 합니다.
 pod1  ~  ping -c 1 172.16.34.1
PING 172.16.34.1 (172.16.34.1) 56(84) bytes of data.
64 bytes from 172.16.34.1: icmp_seq=1 ttl=62 time=1.25 ms

--- 172.16.34.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.252/1.252/1.252/0.000 ms

 

[ k8s-w1 ]

🧿  IPIP 모드로 동작중

  • 패킷 전송:
    • k8s-w1 (192.168.10.101) 에서 k8s-w0 (192.168.10.100) 로 전송됨.
  • 내부 데이터 전송:
    • pod1 (172.16.158.8)  에서 pod3 (172.16.34.1) 로 이동.
  • k8s-w1 (192.168.10.101) 에서 k8s-w0 (192.168.10.100) 로 가는 패킷 내부의 데이터가 pod1 (172.16.158.8)  pod3 (172.16.34.1)  사이에서 이동하고 있습니다.
root@k8s-w1:~# tcpdump -i any proto 4 -nn
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
19:12:46.669779 ens5  Out IP 192.168.10.101 > 192.168.20.100: IP 172.16.158.8 > 172.16.34.1: ICMP echo request, id 218, seq 1, length 64
19:12:46.670934 ens5  In  IP 192.168.20.100 > 192.168.10.101: IP 172.16.34.1 > 172.16.158.8: ICMP echo reply, id 218, seq 1, length 64

 

[ k8s-w0 ]

🧿  IPIP 모드로 동작중

root@k8s-w0:~# tcpdump -i any proto 4 -nn
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
19:12:46.670262 ens5  In  IP 192.168.10.101 > 192.168.20.100: IP 172.16.158.8 > 172.16.34.1: ICMP echo request, id 218, seq 1, length 64
19:12:46.670477 ens5  Out IP 192.168.20.100 > 192.168.10.101: IP 172.16.34.1 > 172.16.158.8: ICMP echo reply, id 218, seq 1, length 64
Comments