연재 시리즈

쿠버네티스 네트워크 스터디 3주차 2편: Calico 모드

악분 2022. 2. 5. 13:40
반응형

스터디 목차

 

안녕하세요. 이 글은 facebook 쿠버네티스 그룹에서 올라온 "쿠버네티스 네트워크 스터디" 3주차 내용을 정리했습니다.

스터디 모집글: https://www.facebook.com/groups/k8skr/posts/3202691746679143

 

1. 3주차 두번째 주제

1편에서는 calico 컨셉과 구조에 대해 살펴봤습니다. 2편에서는 calico 모드를 살펴봅니다. crosssubnet 모드 설정이 꼬여 실습은 진행하지 못했습니다.

 

2. calico 모드

calico는 쿠버네티스 네트워크 통신 제어를 4가지 모드를 동작합니다. 디폴트는 IPIP모드입니다. 아래 그림은 다른 노드에 있는 pod끼리 통신할 때 각 모드 동작입니다. IPIP모드는 Azure클라우드에서 동작하지 않습니다.

  • IPIP모드
  • Direct모드
  • VXLAN모드
  • 패킷 암호화 모드

 

출처: 스터디 공유자료

 

3. IPIP모드

IPIP모드는 디폴트로 설정되는 모드입니다. 다른 노드간 POD통신 시 POD정보를 IP헤더에 추가하는 방법입니다. 추가(캡슐화)와 제거(인캡슐)은 tunl0인터페이스가 담당합니다. IPIP모드는 Azure클라우드에서 지원하지 않습니다.

출처: 스터디 공유자료

 

추가되는 IP헤더(출처: https://en.wikipedia.org/wiki/IP_in_IP)

 

IPIP모드는 실습과정은 1편(https://malwareanalysis.tistory.com/256)에서 살펴보았기 때문에 생략하겠습니다.

출처: 스터디 공유자료 수정

 

4. vxlan모드

4.1 정의

vxlan모드는 POD정보를 VXLAN패킷에 저장하여 통신합니다. Flannel CNI(https://malwareanalysis.tistory.com/254)처럼 UDP 프로토콜을 사용합니다. 그리고, IPIP모드와 다르게 BGP프로토콜을 사용하지 않고 FELIX컴퍼넌트가 ETCD 에서 타 노드의 podCIDR 정보를 가져와서 업데이트합니다.

출처: 스터디 공유자료

 

4.2 설정

vxlan모드는 디폴트 모드가 아니여서 별도 설정이 필요합니다. bird컴퍼넌트를 사용하지 않는 설정과 현재 모드를 변경하는 설정이 필요합니다.

brid컴퍼넌트 비활성화는 스터디에서 공유한 yaml파일을 사용했습니다.

kubectl apply -f https://raw.githubusercontent.com/gasida/KANS/main/3/calico-vxlan-kans.yaml

 

ipip모드를 비활성화하고 vxlan모드를 사용하겠다는 설정을 적용합니다. 저는 현재 calico설정을 yaml파일로 추출하고 yaml필드를 수동으로 적용했습니다.

calicoctl get ippool default-ipv4-ippool  -o yaml > mode.yaml
# 필드 수정 후 설정 적용
calicoctl apply -f mode.yaml

calico 모드 수정
calico 설정 적용

 

calico 모드를 확인하면 vxlan모드가 활성화 되었습니다.

calicoctl get ippool default-ipv4-ippool  -o wide

 

지금까지 설정한 설정을 calico pod에 적용하기 위해 calico pod를 재실행합니다.

 kubectl delete pod -n kube-system -l k8s-app=calico-node

calico설정 적용을 위한 pod재실행

 

vxlan모드는 BGP프로토콜을 사용하지 않으므로 전체 노드(control plane, worker)의 라우팅 테이블을 비활성화 합니다.

route -n && echo && ip link set enp0s8 down && sleep 1 && ip link set enp0s8 up && route -n

 

라우팅 테이블 정보를 확인하면 vxlan모드가 적용된 것을 확인할 수 있습니다.

ip -c nei

 

4.3 pod 통신 실습

pod3개를 생성합니다.

apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-w0
  containers:
  - name: pod1
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
  name: pod2
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-w1
  containers:
  - name: pod2
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
  name: pod3
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-w0
  containers:
  - name: pod3
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0

 

k8s-w0노드에 pod 2개, k8s-w1노드에 pod 1개가 생성되었습니다.

 

pod1->pod2로 ping통신이 어떻게 가는지 관찰해보겠습니다. k8s-w0노드에서 외부로 나가는 네트워크 인터페이스 enps8에 tcpdump 실행합니다. vxlan은 udp 프로토콜을 사용합니다.

# k8s-w0 노드에서
tcpdump -i enp0s8 udp port 4789

 

tcpdump에서 결과를 확인하면 vxlan패킷이 캡처됩니다.

vxlan모드 tcpdump결과

 

5. CrossSubnet모드 - 실습제외

5.1 정의

CrossSubnet모드는 IPIP모드와 Direct모드를 혼합해서 사용하는 모드입니다. 같은 네트워크 대역은 Direct모드로 동작하고 다른 네트워크 대역은 IPIP모드로 동작합니다.

 

5.2 설정

부록 챕터 [calico 기본 설정 적용 또는 리셋]를 참고하여 vxlan모드에서 비활성화 했던 BGP를 활성화합니다. 

 kubectl apply -f https://docs.projectcalico.org/archive/v3.21/manifests/calico.yaml

 

calico설정에서는 vxlan모드를 비활성화 하고 CrossSubent모드로 변경합니다. 저는 현재 calico설정을 yaml파일로 추출하고 yaml필드를 수동으로 적용했습니다.

calicoctl get ippool default-ipv4-ippool  -o yaml > mode.yaml
# 필드 수정 후 설정 적용
calicoctl apply -f mode.yaml

subnet모드 활성화

 

그리고 설정적용을 위해 calico pod를 재실행합니다.

 kubectl delete pod -n kube-system -l k8s-app=calico-node

 

그리고 각 노드 라우트테이블을 초기화합니다.

 route -n && echo && ip link set enp0s8 down && sleep 1 && ip link set enp0s8 up && route -n

 

calico 모드를 확인하면 CrossSubnet모드로 설정되어 있습니다.

calicoctl get ippool -o wide

calico 모드 확인

설정이 꼬여... 다음을 기약하며

 

5.3 pod 통신 실습

pod는 챕터 [4.3]에서 생성한 pod를 사용합니다.

설정이 꼬여... 다음을 기약하며

 

6. WireGuard 모드

6.1 정의

WireGuard모드는 패킷을 암호화하여 통신하는 모드입니다. wireg네트워크 인터페이스가 패킷 암호화/복호화 역할을 담당합니다. 

ISMS심사 등 calico에서 네트워크 통신 암호화가 필요할 때 사용하면 좋을 것 같습니다. 암호화/복호화 동작시간 때문에 네트워크 약간의 네트워크 속도 저하가 있을 것으로 생각합니다.

출처: 스터디 공유자료

 

6.2 설정

각 노드에 wireguard를 설치합니다.

apt install wireguard -y

 

wg버전이 잘 설치되면 버전을 확인할 수 있습니다.

wg version

 

calico에 wireguard모드를 활성화합니다.

calicoctl patch felixconfiguration default --type='merge' -p '{"spec":{"wireguardEnabled":true}}'

wireguard 모드 활성화

 

wireguard모드 설정 확인은 felixconfiguration설정에서 확인할 수 있습니다.

calicoctl get felixconfiguration default -o yaml | grep wireguardEnabled

wireguard 설정 활성화 확인

 

wireguard가 활성화되면 각 노드에 wireguard 네트워크 인터페이스가 생성됩니다.

ip -c -d addr show wireguard.cali

worker노드에서 wireguard 네트워크 인터페이스 확인

 

패킷 암호화를 위한 공개키/개인키 정보를 확인할 수 있습니다.

wg showconf wireguard.cali

패킷암호화을 위한 공개키/개인키 확인

 

부록 calico 기본 설정 적용 또는 리셋

calicoctl 버전에 맞는 쿠버네티스 calico 리소스를 설정합니다.

calico version
kubectl apply -f https://docs.projectcalico.org/archive/<version>/manifests/calico.yaml

 

calico 기본 설정 적용

 

6.3 pod 통신 실습

챕터 [4.3]에서 생성한 pod를 이용하여 실습을 진행합니다.

 

외부로 나가는 인터페이스인 enp0s8에 tcpdump를 실행합니다. tcpdump를 파일로 확인하기 위해 /tmp경로에 캡처 결과를 저장했습니다.

 tcpdump -i enp0s8 udp port 51820 -w /tmp/calico-wireguard.pcap

 

pod1에서 pod2로 ping통신을 합니다.

 

와이어샤크로 패킷을 확인하면 데이터가 암호화되어 있어 데이터를 확인할 수 없습니다.

데이터 암호화 확인

 

참고자료

[1] [블로그] https://cwal.tistory.com/12

[2] [블로그] https://velog.io/@200ok/Kubernetes-Calico-CNI-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0#%EC%8B%A4%EC%8A%B5-2-wireguard

반응형