본문 바로가기
K8s/Advanced Network

[KANS3] 3. Calico CNI + Mode

by okms1017 2024. 9. 22.
728x90

✍ Posted by Immersive Builder  Seong

 

1. Calico CNI

Calico 란?

Calico는 쿠버네티스를 포함한 다양한 플랫폼에서 워크로드의 네트워크 통신과 보안 기능을 제공하는 솔루션입니다. 

쿠버네티스의 CNI를 준수하여 파드 간 네트워크 통신 환경을 구성해줍니다. 

 

Component Architecture

  • calico datastore : Calico 설정 정보가 반영되는 저장소입니다. - kdd(Kubernetes API datastore) / etcd 
  • calicoctl : Calico를 관리하기 위한 CLI 명령줄 도구입니다. 
  • calico-node : Calico CNI 설치 시 노드마다 구성되는 데몬셋입니다. 
  • bird : BGP(Border Gateway Protocol) 프로토콜 기반으로 노드 간 라우팅 정보를 교환합니다. 노드가 생성/삭제될 때 동적으로 라우팅 정보를 광고/삭제합니다. 
  • felix : bird를 통해서 광고받은 라우팅 정보를 호스트의 라우팅 테이블에 반영합니다. 추가로 IPtables와 같은 리눅스 커널 기능을 활용하여 네트워크 패킷을 처리합니다. 
  • confd : calico datastore로부터 설정 정보를 동적으로 가져와 변경된 네트워크 설정 파일을 생성하고 bird에 반영합니다. 
  • typha : 대규모 클러스터에서 felix와 쿠버네티스 API 서버 간의 트래픽을 줄이기 위해 사용되는 컴포넌트입니다.
  • IPAM : Calico는 자체 IPAM(IP Adress Management) 모듈을 사용합니다. Calico IPAM은 네트워크를 서브넷으로 나누고, 각 노드에 고유한 서브넷을 할당하여 네트워크 충돌을 방지합니다. 블록 기반 IP 할당을 사용하여 각 노드에 IP 블록을 분배하고 IP 주소의 효율적인 사용을 보장합니다. 

 

Calico Component Architecture

 

* Calico Component 확인

calico-kube-controllers 파드는 디플로이먼트로 생성됩니다. 

 

calico-node는 데몬셋으로 동작하며, 호스트의 네트워크 네임스페이스를 공유합니다. 

 

Calico IPAM Name과 파드의 네트워크 대역, 가용 IP 수, 사용률 정보입니다. 

 

클러스터 각 노드에 할당된 IP 블록 정보를 조회합니다. 

 

Calico는 host-local IPAM 을 사용하지 않고, 자체 Calico IPAM 모듈을 사용합니다. 

아래 CNI 설정 파일에서 데이터 저장소로 kdd를 사용하고, IPAM 모듈로는 calico-ipam을 사용함을 확인할 수 있습니다. 

host-local IPAM
CNI Configuration

 

※ host-local IPAM vs Calico IPAM ? 

일반적으로 IPAM은 kubernetes annotations> CNI Configuration> IP pool node selectors 순으로 적용됩니다. 

별도의 IPAM 모듈을 사용하면 서로 다른 파드 그룹 또는 네임스페이스에 IP Pool을 할당하거나 특정 파드 레이블, 네임스페이스, 네트워크 정책에 따라 IP를 할당하는 방식 등 세부적인 제어가 가능합니다. 따라서 고급 기능을 제공하는 대부분의 CNI는 자체 IPAM 모듈을 가지고 있습니다. 

 

각 노드는 BGP 라우터가 되어 파드의 네트워크 대역을 BGP Peer(또는 neighbor)에 전파합니다. 

calicoctl 명령어로 노드 상태를 조회할 시에는 자신을 제외한 BGP Peer들의 정보가 출력됩니다. 

 

Calico IP Pool, Mode 에 대한 정보입니다. 현재 디폴트 Pool은 IPIP 모드를 사용하며 VXLAN 모드는 사용하지 않습니다. 

그리고 NAT가 true이면 파드가 외부로 통신할 때 노드의 IP로 마스커레이딩한다는 의미입니다. 

물론 디폴트 외에 추가 Pool을 생성하여 보다 세밀하고 복잡한 네트워크 구성을 가져갈 수도 있습니다. 

 

다음 명령어로 Calico에 의해 할당된 파드들의 IP, 인터페이스 정보를 확인할 수 있습니다. 

 

** 노드에서 컨테이너 프로세스 확인 

$ ps axf 

   8987 ?        Sl     0:44 /usr/bin/containerd-shim-runc-v2 -namespace k8s.io -id 10d6af2c50bad6be2f2da9435dcdf805b9f9c8ca
   9008 ?        Ss     0:00  \_ /pause
   9483 ?        Ss     0:00  \_ /usr/local/bin/runsvdir -P /etc/service/enabled
   9559 ?        Ss     0:00      \_ runsv node-status-reporter
   9567 ?        Sl     0:01      |   \_ calico-node -status-reporter
   9560 ?        Ss     0:00      \_ runsv bird6
   9834 ?        S      0:02      |   \_ bird6 -R -s /var/run/calico/bird6.ctl -d -c /etc/calico/confd/config/bird6.cfg
   9561 ?        Ss     0:00      \_ runsv bird
   9844 ?        S      0:03      |   \_ bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg
   9562 ?        Ss     0:00      \_ runsv felix
   9568 ?        Sl     4:16      |   \_ calico-node -felix
   9563 ?        Ss     0:00      \_ runsv cni
   9573 ?        Sl     0:01      |   \_ calico-node -monitor-token
   9564 ?        Ss     0:00      \_ runsv confd
   9569 ?        Sl     0:02      |   \_ calico-node -confd
   9565 ?        Ss     0:00      \_ runsv monitor-addresses
   9571 ?        Sl     0:01      |   \_ calico-node -monitor-addresses
   9566 ?        Ss     0:00      \_ runsv allocate-tunnel-addrs
   9572 ?        Sl     0:02          \_ calico-node -allocate-tunnel-addrs

 

** felix : IPtables 규칙 설정 확인 

$ iptables -t filter -S | grep cali

```

-A cali-tw-cali84f9fe2ffac -m comment --comment "cali:VXwCWi_NqN-ioEZ7" -m comment --comment "Return if profile accepted" -j RETURN
-A cali-tw-cali84f9fe2ffac -m comment --comment "cali:zydsyRJzKrWecynf" -j cali-pri-_u2Tn2rSoAPffvE7JO6
-A cali-tw-cali84f9fe2ffac -m comment --comment "cali:j4gIvfrg44s_Qh6W" -m comment --comment "Return if profile accepted" -j RETURN
-A cali-tw-cali84f9fe2ffac -m comment --comment "cali:s600mJijUlJIDlMC" -m comment --comment "Drop if no profiles matched" -j DROP
-A cali-wl-to-host -m comment --comment "cali:Ee9Sbo10IpVujdIY" -j cali-from-wl-dispatch
-A cali-wl-to-host -m comment --comment "cali:nSZbcOoG1xPONxb8" -m comment --comment "Configured DefaultEndpointToHostAction" -j ACCEPT

 

$ iptables -t nat -S | grep cali

-N cali-OUTPUT
-N cali-POSTROUTING
-N cali-PREROUTING
-N cali-fip-dnat
-N cali-fip-snat
-N cali-nat-outgoing
-A PREROUTING -m comment --comment "cali:6gwbT8clXdHdC1b1" -j cali-PREROUTING
-A OUTPUT -m comment --comment "cali:tVnHkvAo15HuiPy0" -j cali-OUTPUT
-A POSTROUTING -m comment --comment "cali:O3lYWMrLQYEMJtB5" -j cali-POSTROUTING
-A cali-OUTPUT -m comment --comment "cali:GBTAv2p5CwevEyJm" -j cali-fip-dnat
-A cali-POSTROUTING -m comment --comment "cali:Z-c7XtVd2Bq7s_hA" -j cali-fip-snat
-A cali-POSTROUTING -m comment --comment "cali:nYKhEzDlr11Jccal" -j cali-nat-outgoing
-A cali-POSTROUTING -o tunl0 -m comment --comment "cali:SXWvdsbh4Mw7wOln" -m addrtype ! --src-type LOCAL --limit-iface-out -m addrtype --src-type LOCAL -j MASQUERADE --random-fully
-A cali-PREROUTING -m comment --comment "cali:r6XmIziWUJsdOK6Z" -j cali-fip-dnat
-A cali-nat-outgoing -m comment --comment "cali:flqWnvo8yq4ULQLa" -m set --match-set cali40masq-ipam-pools src -m set ! --match-set cali40all-ipam-pools dst -j MASQUERADE --random-fully

 

calico-node에 접속하여 bird 라우팅 정보를 확인합니다. bird 데몬은 birdcl 명령줄 도구를 제공합니다. 

Mesh 표기된 규칙들이 다른 노드로의 파드 네트워크 라우팅 정보에 해당합니다. 

 

Calico 설치 

  • Calico CNI v3.28.1 / Calicoctl v3.28.1 
  • k8s-m (Control Plane) 
# Calico CNI 설치 
$ kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.1/manifests/calico.yaml

# Calicoctl 설치 
$ curl -L https://github.com/projectcalico/calico/releases/download/v3.28.1/calicoctl-linux-amd64 -o calicoctl
$ chmod +x calicoctl && mv calicoctl /usr/bin
$ ls -l /usr/bin/calicoctl
-rwxr-xr-x 1 root root 67560884 Sep 21 00:16 /usr/bin/calicoctl

# Calicoctl 설치 확인 
$ calicoctl version
Client Version:    v3.28.1
Git commit:        601856343
Cluster Version:   v3.28.1
Cluster Type:      k8s,bgp,kubeadm,kdd

 

  • Calico 설치 확인 

Calico 컨트롤러 파드(calico-kube-controllers)와 노드별로 동작하는 데몬셋(calico-node)이 하나씩 배포됩니다. 

그리고 파드의 IP를 할당할 수 있는 상태가 되어 coredns가 정상적으로 동작합니다. 

 

CNI 기본 경로에 calico와 calico-ipam 실행파일이 추가됩니다. 

 

라우팅 테이블에는 tunl0, bird, blackhole 등 Calico 관련한 규칙들이 추가됩니다. 

예를 들어 172.16.34.0/24 파드 대역과 통신하기 위해서 k8s-w0(192.168.20.100)로 트래픽을 보내고, 172.16.158.0/24 파드 대역과 통신하기 위해서는 k8s-w1(192.168.10.101)으로 트래픽을 보낸다는 의미입니다. 

 

Calico CNI 관련 인터페이스도 추가된 모습입니다. 

 

파드 ↔ 파드 간 통신 

동일 노드 내 파드 간 통신은 내부에서 직접 통신합니다. 

 

[ 파드 생성 이전 (k8s-w1) ]

 

IPIP 모드의 터널 인터페이스가 존재합니다. 

 

자식 네트워크 네임스페이스는 없는 상태입니다. 

 

bird 라우팅 규칙은 tunl0 인터페이스를 통해 다른 노드의 파드 네트워크 대역으로 트래픽을 전달합니다. 

blackhole 라우팅 규칙은 로컬호스트로의 통신을 처리하며 라우팅 루프를 방지합니다. 

 

IPtables의 filter, nat 테이블의 규칙 수는 각각 39개, 15개입니다. 

 

[ 파드 생성 이후 (k8s-w1) ]

 

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

 

# w1-pod2.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-w1
  containers:
  - name:pod2
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0

 

 

파드가 배포됨과 동시에 veth 인터페이스가 할당됩니다. 

 

파드별로 자식 네트워크 네임스페이스가 생성되고 pause 컨테이너가 관리합니다. 

link-netns id 0, link-netns id 1이 각각 매칭됩니다. 

 

파드의 32bit 라우팅 규칙이 라우팅 테이블에 추가됩니다. 

 

IPtables의 filter 테이블 규칙이 파드 배포 이전과 비교하여 39개에서 91개로 증가한 모습입니다. 

이처럼 파드가 배포될 때마다 IPtables의 규칙 수가 배수로 증가합니다. 그러나 파드 수량이 많아질수록 위에서부터 순차적으로 찾기 때문에 결국 비효율적이게 됩니다. 

 

1번 파드(pod1)에 접속하여 네트워크 정보를 확인합니다. (IP: 172.16.158.1/32) 

파드의 인터페이스(eth0)는 호스트 네트워크 인터페이스 6번(calice0906292e2)과 veth 연결되어 있습니다. 

 

그리고 169.254.1.1 IP를 디폴트 게이트웨이 주소로 사용합니다. 

 

ARP 정보는 아무것도 존재하지 않습니다. 

 

2번 파드(pod2)에 접속하여 네트워크 정보를 확인합니다. (IP: 172.16.158.2/32) 

파드의 인터페이스(eth0)는 호스트 네트워크 인터페이스 7번(calibd2348b4f67)과 veth 연결되어 있습니다. 

 

게이트웨이 주소와 ARP 정보는 1번 파드의 결과와 동일합니다. 

 

[ 파드 간 통신 실행 (pod1 → pod2) ] 

 

파드는 32bit IP 주소를 가지고 있고 게이트웨이는 169.254.1.1 주소인 상황에서 파드 간 통신이 어떻게 가능할까요? 

 

Ping 통신을 시도하면 ARP 프로토콜에 의해 게이트웨이의 MAC 주소(ee:ee:ee:ee:ee:ee)가 학습됩니다. 

 

** 모든 cali* 인터페이스가 동일한 MAC 주소(ee:ee:ee:ee:ee:ee)를 사용해도 문제 없을까요?

- 일부 커널이 고정 MAC 주소 생성을 지원하지 않아서 Calico가 자체 MAC 주소를 생성합니다. 

- 또한 파드 인터페이스와 cali* 인터페이스는 p2p 통신을 하므로 호스트의 데이터링크 레이어(L2)까지 도달하지 않아 모든 cali* 인터페이스가 동일한 MAC 주소를 사용하여도 문제가 없습니다. 

 

그리고 IPTables의 cali-FORWARD 규칙에 의해 통신이 허용되며 ping을 보낼 때마다 pkts 카운트가 증가합니다. 

 

패킷을 캡처하여 살펴보면 1번 파드에서 게이트웨이(169.254.1.1)의 MAC 주소를 알기 위해서 ARP Request를 보내고, 이 때 veth로 연결된 calice0906292e2 인터페이스에 proxy-arp 설정이 되어 있어 자신의 MAC 주소( ee:ee:ee:ee:ee:ee)를 알려주고 통신이 가능하게 됩니다. 

 

** 32bit IP 주소로 구성된 라우터 인터페이스끼리는 어떠한 IP를 할당하더라도 서로 Neighbor가 될 수 있습니다. 

이것이 파드의 인터페이스(172.16.158.1/32)에서 169.254.1.1 IP 주소를 게이트웨이로 설정할 수 있는 이유입니다. 

단, Calico CNI에서 동일 노드 내 파드 간 통신이 가능하려면 파드와 peer로 연결된 veth cali* 인터페이스에 반드시 proxy_arp 설정이 활성화되어 있어야 합니다. (proxy_arp=1) 

 

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

파드에서 외부(인터넷) 통신 시에는 해당 노드의 IP 주소로 마스커레이딩되어 연결됩니다. 

 

[ 파드 생성 이전 (k8s-w1) ]

 

Calico 기본 설정은 natOutgoing:true 입니다. 

 

IPAM Pool(cali40masq-ipam-pools)은 파드 네트워크 대역(172.16.0.0/16)을 의미하며, cali-nat-outgoing 체인에 해당하는 규칙은 파드 네트워크 대역으로부터 파드 네트워크 대역에 해당하지 않는 대역으로 트래픽을 보낼 시 SNAT로 마스커레이딩한다는 의미입니다. 즉, 파드 간 통신이 아닌 외부로 나가는 트래픽을 제어하는 규칙입니다. 

 

[ 파드 생성 이후 (k8s-w1) ]

 

k8s-w1 워커 노드에 1개의 테스트 파드를 배포합니다. 

 

# netshoot-pod.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

 

 

외부 통신 이전의 IPtables NAT Masquerade pkts 상태를 확인합니다. 

 

[ 외부 통신 실행 (pod1 → Internet) ] 

 

1번 파드 내부에서 외부로 ping 통신을 시도합니다. 

 

cali* veth 인터페이스에서 request/reply 패킷이 캡처되고, src ip는 파드의 ip 주소를 가지고 있습니다. 

 

tunl0 인터페이스에서는 패킷이 없습니다. 즉, 파드와 외부 간 통신에는 tunl0 인터페이스는 관여하지 않습니다. 

 

호스트의 인터페이스인 ens5에서는 request 패킷의 src ip 주소가 노드의 ip 주소로 변환되어 전송됩니다. 

그리고 이후에 인스턴스의 공인 IP로 한 번 더 SNAT하여 전송될 것입니다. 

 

도메인 통신도 정상적으로 연결됩니다. 

 

외부로 통신이 성공할 때마다 cali-nat-outgoing 체인의 pkts가 증가합니다. 

 

[ natOutgoing:false 변경 ] 

 

보통 Egress Gateway를 구성한 경우에 적용하는 설정입니다. 

Calico 설정을 natOutgoing:false 로 변경하면 외부 통신이 되지 않습니다. 

 

그리고 기존에 존재하던 Masquerade 규칙이 삭제됩니다. 

 

다시 설정을 원복합니다. (natOutgoing:true 추가)

 

다른 노드 파드 ↔ 파드 간 통신 : IPIP 모드 

다른 노드 환경에서 파드 간 통신 시에는 IPIP 터널 모드를 통해서 이루어집니다. 

IPIP 터널 모드는 tunl0 인터페이스를 통해 IP Header를 en/decapsulation 합니다. 

IP in IP Encapsulation

 

[ 파드 생성 이전 (k8s-w1, k8s-w2) ]

 

각 노드에서 BGP에 의해 전달 받은 라우팅 정보가 호스트의 라우팅 테이블에 존재하는지 확인합니다. 

k8s-w1
k8s-w2

 

다음은 각 노드의 tunl0 인터페이스 정보입니다. 

k8s-w1
k8s-w2

 

[ 파드 생성 이후 (k8s-w1, k8s-w2) ]

 

k8s-w1, k8s-2 워커 노드에 파드를 하나씩 배포합니다. 

 

# w12-pod2.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

 

 

각 노드에는 자신의 파드 IP 주소를 목적지로 하는 규칙이 생성됩니다. (Longest Match Rule) 

k8s-w1
k8s-w2

 

[ 파드 간 통신 실행 (pod1 → pod2) ] 

 

서로 다른 노드의 파드 간 통신을 위해서 사전에 접근제어에서 IPIP 프로토콜이 허용되어야 합니다. (IP Protocol 4) 

 

1번 파드(pod1)에 접속하여 2번 파드(pod2)로 ping 통신을 시도합니다. 

 

tunl0 인터페이스의 TX/RX 패킷 카운트가 10 증가합니다. 

 

tunl0 인터페이스에서 파드의 IP 주소로 request/reply 패킷을 주고 받습니다. 

 

호스트의 인터페이스인 ens5에서 패킷을 캡처하기 위해서는 IP Protocol을 4(IPIP)로 설정하여야 합니다. 

proto 4 옵션을 통해 Outer IP Header 정보와 Inner IP Header 정보가 모두 출력됩니다. 

 

※ Wireshark 패킷 분석 

Outer Header의 src/dst IP는 노드의 IP를 가지며, Inner Header의 src/dst IP는 파드의 IP를 가집니다. 

 

 


2. Calico Mode

Calico 라우팅 모드 

  • IPIP 모드 : 서로 다른 노드 간 파드 통신은 IPIP En/Decapsulation을 통해 이루어집니다. 
  • Direct 모드 : 오버레이 통신 없이 파드의 IP를 가지고 원본 패킷이 그대로 전달됩니다. 
  • VXLAN 모드 : 원본패킷을 UDP Header로 캡슐화하여 오버레이 통신을 합니다. (Flannel CNI와 동일) 
  • Pod 패킷 암호화 : 내부망일지라도 민감한 정보를 전달하는 경우 원본 패킷을 wireg로 암호화하는 통신 방식입니다. 

CloudNet@

 

Direct 모드 

오버레이 통신 없이 파드의 IP를 가지고 원본 패킷을 그대로 전달합니다. 

CSP 환경(ex: AWS)의 경우, NIC에 매칭되지 않는 IP 패킷은 기본 차단하므로 Source/Destination Check 기능을 비활성화하여야 Direct 모드가 동작합니다. 

 

AWS - Change Source/destination check Stop

 

[ Direct 모드 설정 ]

 

IPIP 모드를 "Always"에서 "Never"로 변경하면 Direct 모드가 적용됩니다. 

 

파드 네트워크 대역에 대한 라우팅 인터페이스가 기존 tunl0에서 ens5로 변경됩니다. 

k8s-w1
k8s-w2

 

[ 파드 배포 (k8s-w0, k8s-w1, k8s-w2) ]

 

k8s-w0, k8s-w1, k8s-w2 워커 노드에 파드를 하나씩 배포합니다.

 

노드 k8s-w1
(192.168.10.101) 
k8s-w2
(192.168.10.102) 
k8s-w0
(192.168.20.100) 
파드 pod1
(172.16.158.5)
pod2
(172.16.184.3)
pod3
(172.16.34.2)

# 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

 

 

[ 파드 간 통신 실행 (pod1 → pod2) ] 

 

k8s-w1 노드와 k8s-w2 노드는 동일한 서브넷에 위치하므로 파드 간에 통신이 정상적으로 이루어집니다. 

 

파드의 IP를 가지고 request/reply 패킷을 주고 받습니다. 

 

[ 파드 간 통신 실행 (pod1 → pod3) ] 

 

k8s-w1 노드와 k8s-w0 노드는 다른 서브넷에 위치하므로 파드 간에 통신이 이루어지지 않습니다. 

 

k8s-w1 노드에서 요청하는 패킷은 확인이 되나, k8s-w0 노드에서 인입되는 패킷이 확인되지 않습니다. 

k8s-w1
k8s-w0

그 이유는 AWS VPC 라우터에 서브넷에 대한 라우팅 정보는 존재하지만, 파드의 네트워크 대역에 대한 라우팅 정보는 가지고 있지 않기 때문입니다. 

 

서로 통신이 되도록 라우터의 라우팅 테이블에 파드의 네트워크 대역을 추가하여 오버헤드가 없는 고속의 네트워크 환경을 구성할 수 있으나 네트워크 팀의 협조가 필요한 부분입니다. 역으로 생각해보면 오버레이 통신이 처음 나온 이유는 네트워크, 스토리지 벤더의 종속사항을 피하기 위해 최대한 서버와 어플리케이션만으로 통신환경을 구현하였음을 유추해볼 수 있습니다. 

 

CrossSubnet 모드

동일한 서브넷에 위치한 노드 간에는 Direct 모드로 동작하고, 서로 다른 서브넷에 위치한 노드 간에는 IPIP 모드로 동작합니다. 

 

IPIP 모드를 CrossSubnet 모드로 변경하여 적용합니다. 

 

아래와 같이 서브넷이 다른 노드로의 라우팅 인터페이스는 tunl0로 변경됩니다. 

k8s-w1
k8s-w2

 

이제 1번 파드(pod1)에서 3번 파드(pod3)로 통신이 정상적으로 연결됩니다.   

 

VXLAN 모드

다른 노드 간 파드 통신은 vxlan 인터페이스를 통해 L2 Frame이 UDP - VXLAN에 감싸져서 상대 측 노드로 도달한 후 vxlan 인터페이스에서 Outer Header를 제거하고 내부의 파드와 통신합니다. BGP 프로토콜을 사용하지 않으므로 다른 노드의 파드 네트워크 대역 정보를 felix가 etcd 로부터 가져와서 업데이트합니다. 

 

Pod 패킷 암호화 

Calico의 다양한 네트워크 모드 환경 위에서 WireGuard 터널을 자동으로 생성하고 파드 트래픽을 암호화하여 노드 간 전송합니다. 

 

* WireGuard 란?

- 전통적인 IPSecVPN 및 OpenVPN의 대항마로 등장한 오픈소스 VPN 프로젝트

- Linux 5.6 커널에 WireGuard v1.0.0 기본 패키지로 탑재

- 간결한 코드 구조와 빠른 성능

- 모든 것이 커널 단에서 동작함

- 이동 중에 망 변경으로 Peer 장비의 IP 주소가 변경되더라도 터널이 유지됨 (Peer Hash Table 운용) 

 

[ WireGuard 설치 ] 

 

$ apt install -y wireguard

$ wg version

wireguard-tools v1.0.20210914 - https://git.zx2c4.com/wireguard-tools/

 

[ WireGuard 설정 ] 

 

wireguardEnabled:true 로 변경하여 WireGuard를 활성화합니다. 

 

노드별 wireguard 암호화에 사용할 공개키 목록입니다. 

 

wireguard 전용 인터페이스가 생성됩니다. 

 

기본 51820/UDP 포트를 사용합니다. 연결된 Peer 장비의 정보와 암호화에 사용할 공개키를 저장하고 있습니다. 

 

Peer 장비와 통신할 때 IP를 사용하지 않고 고유한 index 값을 사용합니다. 

 

[ 파드 간 통신 실행 후 패킷 암호화 확인 ] 

 

1번 파드(172.16.158.8/32)에서 2번 파드(172.16.184.6/32)로 ping 통신을 시도합니다. 

 

그리고 트래픽을 파일로 출력하여 분석해보면 WireGuard Header 내부에 파드 패킷이 암호화된 것을 확인할 수 있습니다. 

 

암호화 여부를 확인하고 다시 WireGuard 설정을 비활성화합니다. 

$ calicoctl patch felixconfiguration default --patch '{"spec":{"wireguardEnabled": false}}'

$ calicoctl get felixconfiguration default -o yaml | grep wireguardEnabled
  wireguardEnabled: false

 

파드에 고정 IP를 지정하여 배포하기

kubernetes annotations는 IPAM 중에서 가장 우선합니다. 

# static-ip-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: static-ip-pod
  annotations:
    "cni.projectcalico.org/ipAddrs": "[\"172.16.100.100\"]"
spec:
  containers:
  - name: static-ip-pod
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0

 

annotation으로 지정한 IP가 파드에 고정으로 할당됩니다. 

 

Calico 모니터링 시스템 구축 : Prometheus + Grafana

1. Prometheus

 

A. Configure Calico to enable metrics reporting

  • "prometheusMetricsEnabled": true

  • felix-metrics-svc 

 

B. Cluster preparation

  • namespace/calico-monitoring

  • serviceaccount/calico-prometheus-user

 

C. Install Prometheus

  • configmap/prometheus-config

  • pod/prometheus-pod

 

D. View metrics

  • service/prometheus-dashboard-svc

  • prometheus dashboard

 

2. Grafana

 

E. Use Grafana dashboard to view Calico component metrics

  • configmap/grafana-config

  • configmap/grafana-dashboards-config

  • pod/grafana-pod

  • service/grafana

  • grafana dashboard

 

 

 


[출처]

1) CloudNet@, KANS 실습 스터디 

2) https://docs.tigera.io/calico/latest/about

 

About Calico | Calico Documentation

A brief description of Calico, deployment options, and features.

docs.tigera.io

3) https://en.wikipedia.org/wiki/IP_in_IP

 

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

4) https://docs.tigera.io/calico/latest/networking/ipam/use-specific-ip

 

Use a specific IP address with a pod | Calico Documentation

Specify the IP address for a pod instead of allowing Calico to automatically choose one.

docs.tigera.io

5) https://docs.tigera.io/calico/latest/operations/monitor/

 

Monitor | Calico Documentation

Tools for scraping useful metrics

docs.tigera.io

728x90