새소식

Kubernetes

[Study 3주차] 쿠버네티스 Calico CNI 기본 통신 이해

  • -

CloudNet@ 팀의 가시다님께서 리딩하시는 KANS Study (Kubernetes Advanced Networking Study) 3주차 스터디 내용 정리

 

칼리코 CNI 가 실제 동작하는 통신 방식에 대해 알아보겠습니다.

 

실습을 위해서는 칼리코가 설치된 쿠버네티스가 필요하며, 컨트롤 플레인을 제외하고 3대의 노드가 필요합니다.

 

 

 

1. 동일 노드 내의 Pod 간 통신

 

편의를 위해 데몬셋을 제외한 아무런 파드가 배포되어 있지 않은 노드에서 실습을 진행합니다.
그런 파드가 없다면, cordondrain 을 통해서 해당 노드를 비워줍니다.

# 노드 스케쥴링 방지
kubectl cordon k8s-w1

# Pod eviction
kubectl drain k8s-w1 --ignore-daemonsets

# 노드 스케쥴링 방지 해제
kubectl uncordon k8s-w1

 

그 후 아래 칼리코 cli 를 입력하면 k8s-w1 노드에 아무런 파드가 없다고 나옵니다.

calicoctl get workloadEndpoint -A

 

 

 

1.1. 노드의 기본 정보 확인

 

해당 실습을 진행할 노드에 ssh 접속을 하여 기본 정보를 확인해줍니다.

 

ip -c -d addr show

 

 

현재 노드 내부는 다음과 같습니다.

 

1.2. 파드 배포

 

k8s-w1 노드에 2개의 파드를 배포합니다.

 

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-w1
  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/node1-pod2.yaml
kubectl apply -f node1-pod2.yaml

 

 

K8S-W1 노드에서 네트워크 인터페이스 확인

 

ip -c -d addr show

 

 

2개의 Calice 인터페이스가 생성된 것을 확인할 수 있습니다.
해당 인터페이스가 어떤 파드에 연결되었는 지 확인하기 위해, 파드에 직접 접속해줍니다.

 

# Pod 1 번에 zsh 로 접속
kubectl exec pod1 -it -- zsh

# IP Address 확인
ip -c addr

 

 

Pod1 은 9 번 네트워크 인터페이스와 페어링 연결되어 있는 것을 알 수 있습니다.

 

즉, 현재 노드 내부 네트워크 인터페이스 구조는 다음과 같습니다.

 

 

1.3. 파드 통신 실행

 

Pod 1 에서 Pod 2 Ping 을 날려봅니다.

kubectl exec pod1 -it -- zsh

# Pod 2 로 ICMP
ping -c 10 172.16.158.5

 

 

다음 실습을 위해 파드를 삭제합니다.

kubectl delete -f node1-pod2.yaml



 

2. 파드와 외부 인터넷 간 통신

 

칼리코의 기본 설정은 natOutgoing: true 입니다.
즉, iptables 에서 MASQUERADE Rule 에 의해 외부와 연결이 가능합니다.

 

 

2.1. 노드의 기본 정보 확인

 

calicoctl get ippool -o wide

 

 

 

2.2. 파드 배포

 

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

 

 

2.3. 외부 통신 확인

 

# Pod1 접속
kubectl exec pod1 -it -- zsh

# 외부 통신
ping -c 10 8.8.8.8

 

노드의 각 네트워크 인터페이스에서 패킷 캡처

 

VETH1=calice0906292e2

tcpdump -i $VETH1 -nn icmp
tcpdump -i tunl0 -nn icmp
tcpdump -i ens5 -nn icmp

 



3. 다른 노드 간 Pod 통신

 

각 노드에서 네트워크 대역은 Bird 에 의해 BGP 전파되며, Felix 에 의해서 라우팅 테이블에 등록됩니다.

 

다른 노드 간 파드 통신은 tunl0 인터페이스를 통해 IP 헤더로 감싸져서,

상대측 노드로 도달 후 tunl0 인터페이스에서 Outer 헤더를 제거하고 내부 파드와 통신됩니다. (IPIP 방식)

 

3.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

 

3.3. 파드 간 통신 확인

 

 

# pod1 이 배포된 노드에서 tcpdump 확인
tcpdump -i tunl0 -nn

# IPIP 프로토콜 패킷 확인
tcpdump -i ens5 -nn proto 4

 

 

Contents

포스팅 주소를 복사했습니다