CNI란?
CNI(Container Network Interface)는 CNCF(Cloud Native Computing Foundation)의 프로젝트로 Specification과 리눅스 컨테이너의 네트워크 인터페이스를 구성하기 위한 plugin을 작성하기 위한 라이브러리로 구성됩니다.
CNI는 컨테이너의 네트워크 연결성과 컨테이너가 삭제되었을 때 할당된 리소스를 제거하는 역할에 집중합니다.
참고: https://github.com/containernetworking/cni
보통 Kubernetes에 어떤 CNI를 쓰느냐라고 얘기를 하면 의미가 통하기는 하지만, 실제로 calico, cilium, flannel 등은 CNI plugin이라고 할 수 있습니다.
Kubernetes 에서 CNI Plugin의 동작은 간략히 아래와 같이 이뤄집니다.
- Kubelet이 Container Runtime에 컨테이너 생성을 요청
- Container Runtime이 컨테이너의 Network Namespace를 생성
- Container Runtime이 CNI 설정과 환경변수를 표준 입력으로 CNI Plugin 호출
- CNI Plugin이 컨테이너의 네트워크 인터페이스를 구성하고, IP를 할당하고, 호스트 네트워크 간의 veth pair 를 생성
- CNI Plugin이 호스트 네트워크 네임스페이스와 컨테이너 네트워크 네임스페이스에 라우팅을 구성
오래되긴 했지만 CNI와 CNI Plugin에 대해 잘 설명한 영상이 있습니다.
https://www.youtube.com/watch?v=4E_l-B988Ek&t=1341s
실습
간단히 영상의 실습을 따라해보겠습니다.
먼저 go가 설치된 환경에서 아래와 같이 샘플 CNI plugin을 가져와 빌드를 진행합니다. 빌드가 끝나면 bin 폴더에 바이너리들이 위치합니다.
root@jumpVM:~# git clone https://github.com/containernetworking/plugins.git
Cloning into 'plugins'...
remote: Enumerating objects: 19825, done.
remote: Counting objects: 100% (268/268), done.
remote: Compressing objects: 100% (180/180), done.
remote: Total 19825 (delta 151), reused 86 (delta 86), pack-reused 19557 (from 2)
Receiving objects: 100% (19825/19825), 16.41 MiB | 19.77 MiB/s, done.
Resolving deltas: 100% (11214/11214), done.
root@jumpVM:~# cd plugins/
root@jumpVM:~/plugins# ls
CONTRIBUTING.md README.md go.mod plugins
DCO RELEASING.md go.sum test_linux.sh
LICENSE build_linux.sh integration test_windows.sh
OWNERS.md build_windows.sh pkg vendor
root@jumpVM:~/plugins# ./build_linux.sh
Building plugins
bandwidth
firewall
portmap
sbr
tuning
vrf
bridge
dummy
host-device
ipvlan
loopback
macvlan
ptp
tap
vlan
dhcp
host-local
static
root@jumpVM:~/plugins# ls
CONTRIBUTING.md README.md build_windows.sh pkg vendor
DCO RELEASING.md go.mod plugins
LICENSE bin go.sum test_linux.sh
OWNERS.md build_linux.sh integration test_windows.sh
root@jumpVM:~/plugins# cd bin
root@jumpVM:~/plugins/bin# ls
bandwidth dummy host-local macvlan sbr tuning
bridge firewall ipvlan portmap static vlan
dhcp host-device loopback ptp tap vrf
그리고 3개의 세션을 만들어서 아래의 명령을 실행합니다.
## 좌측 세션 (demons 생성)
$ sudo ip netns add demons
## 우측 상단 세션 (host ns의 ip/route 정보 확인)
$ watch -d -n 1 'ip a; echo ""; ip route'
## 우측 하단 세션 (domons의 ip/route 정보 확인)
$ watch -d -n 1 'ip netns exec demons ip a; echo ""; ip netns exec demons ip route;'
최초 상태는 아래와 같습니다.
컨테이너와 호스트간에 veth 디바이스를 생성해주는 ptp plugin을 사용합니다.
https://www.cni.dev/plugins/current/main/ptp/
ptp 바이너리를 실행하면 version을 알 수 없다고 합니다. CNI는 단순히 필요한 정보를 환경 변수로, 그리고 spec을 표준 입력으로 전달합니다. CNI_COMMAND로 VERSION을 넣고 다시 바이너리를 실행하면 제공하는 버전을 알려줍니다.
root@jumpVM:~/plugins/bin# ./ptp
CNI ptp plugin version unknown
CNI protocol versions supported: 0.1.0, 0.2.0, 0.3.0, 0.3.1, 0.4.0, 1.0.0, 1.1.0
root@jumpVM:~/plugins/bin# CNI_COMMAND=VERSION ./ptp
{"cniVersion":"1.1.0","supportedVersions":["0.1.0","0.2.0","0.3.0","0.3.1","0.4.0","1.0.0","1.1.0"]}
아래와 같이 표준 입력으로 전달할 CNI 설정도 준비합니다. CNI plugin에는 IPAM과 컨테이너 네트워크를 구성하는 역할을 하는 plugin으로 나뉩니다. 여기에서는 ptp와 ipam으로 host-local을 사용했습니다.
{
"cniVersion": "0.3.1",
"name": "demonet",
"type": "ptp", ## CNI binary
"ipam": {
"type": "host-local", ## CNI binary for IPAM
"subnet": "192.168.0.0/24"
}
}
이제 실제로 ADD 명령을 전달합니다. 하지만 여러가지 변수들이 지정되지 않아 에러가 발생하였습니다.
root@jumpVM:~/plugins/bin# CNI_COMMAND=ADD ./ptp < config
{
"code": 4,
"msg": "required env variables [CNI_CONTAINERID,CNI_NETNS,CNI_IFNAME,CNI_PATH] missing"
}
해당 변수들까지 환경 변수로 지정하고 명령을 다시 수행합니다.
$ CNI_COMMAND=ADD CNI_CONTAINERID=1234 CNI_NETNS=/var/run/netns/demons CNI_IFNAME=domoeth0 CNI_PATH=/root/plugins/bin ./ptp < config
명령 수행 결과로 생성된 interface에 대한 정보와 IPAM에서 전달된 ip 정보를 확인할 수 있으며, 우측 세션을 보면 새로운 veth pair와 라우팅이 추가되었음을 알 수 있습니다.
마지막으로 DEL 명령으로 테스트 구성을 삭제합니다.
CNI_COMMAND=DEL CNI_CONTAINERID=1234 CNI_NETNS=/var/run/netns/demons CNI_IFNAME=domoeth0 CNI_PATH=/root/plugins/bin ./ptp < config
이렇게 샘플 CNI plugin을 실행해 봄으로서 앞서 설명한 과정을 이해할 수 있으며, Container Runtime이 어떤 방식으로 CNI plugin을 호출하는지를 이해할 수 있습니다. 실제로 ADD, DEL 과 같은 요청을 합니다.
'Kubernetes' 카테고리의 다른 글
Vault를 활용한 쿠버네티스 Secret 관리 (0) | 2025.04.13 |
---|---|
Jenkins와 Argo CD를 활용한 Kubernetes 환경 CI/CD 구성 (0) | 2025.03.30 |
쿠버네티스에 containerd 를 사용하는 윈도우 워커노드 추가 (with Calico CNI) (0) | 2022.07.12 |
쿠버네티스 윈도우 워커 노드 추가 (with Calico CNI) (2) | 2022.03.14 |
Kubernetes 업그레이드 (K8S v1.21.x → v1.22.x) (0) | 2022.02.05 |