
CNI(Container Network Interface) 는 컨테이너의 네트워크를 구성하고 관리하기 위한 표준 인터페이스이다.
kubectl run
명령으로 파드를 생성하면, 몇 초 안에 그 파드는 고유한 IP를 부여받고 클러스터 내 다른 파드들과 통신할 수 있게 된다.
이러한 IP 할당과 네트워크 연결 설정을 실제로 수행하는 역할을 하는 것이 바로 CNI이다.
CNI는 “쿠버네티스가 직접 네트워크를 설정하지 않는다”는 철학을 따른다.
즉, 쿠버네티스는 네트워크 설정의 책임을 외부 플러그인에게 위임하고,
이때 어떤 방식으로 통신하고 설정을 전달할지 정의한 표준 명세가 바로 CNI이다.
쿠버네티스는 선언형 시스템이기 때문에,
사용자가 “이 파드를 생성하겠다”고 선언하면,
쿠버네티스는 파드 생성 시점에 CNI 플러그인을 자동으로 호출하여
-> 즉, 쿠버네티스는 “파드를 만들 테니, 나머지 네트워크 설정은 CNI가 알아서 처리하라.”는 식으로 동작한다.
쿠버네티스 공식 문서에서는 다음과 같이 설명한다.
“쿠버네티스는 클러스터 네트워킹을 위해 CNI 플러그인을 지원하며,
CNI 플러그인을 사용하려면 쿠버네티스 네트워크 모델을 구현해야 한다.”
이 말은 다음과 같은 의미이다.
참고
쿠버네티스 1.24 이전까지는 cni-bin-dir과 network-plugin 커맨드 라인 파라미터를 사용해 kubelet이 CNI 플러그인을 관리하게 할 수도 있었다. 하지만, 이 커맨드 라인 파라미터들은 쿠버네티스 1.24에서 제거되었으며, CNI 관리는 더 이상 kubelet 범위에 포함되지 않는다.
이 말의 의미는 쿠버네티스는 1.24버전부터는
--network-plugin
플래그 자체가 제거 되었고, kubelet은 더 이상 CNI 플러그인을 "직접" 관리하지 않는다.라는 의미이다.
따라서 사용자가 CNI를 따로 "직접 설치 및 구성" 해야하며 kubele은 단순히
/etc/cni/net.d 아래의 CNI 설정 파일을 읽어서 호출만 한다.
!/usr/bin/env bash
# Copyright The containerd Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Builds and installs cni plugins to /opt/cni/bin,
# and create basic cni config in /etc/cni/net.d.
# The commit defined in go.mod
#
set -eu -o pipefail
CNI_COMMIT=${1:-$(go list -f "{{.Version}}" -m github.com/containernetworking/plugins)}
CNI_DIR=${DESTDIR:=''}/opt/cni
CNI_CONFIG_DIR=${DESTDIR}/etc/cni/net.d
: "${CNI_REPO:=https://github.com/containernetworking/plugins.git}"
# e2e and Cirrus will fail with "sudo: command not found"
SUDO=''
if (( $EUID != 0 )); then
SUDO='sudo'
fi
TMPROOT=$(mktemp -d)
git clone "${CNI_REPO}" "${TMPROOT}"/plugins
pushd "${TMPROOT}"/plugins
git checkout "$CNI_COMMIT"
./build_linux.sh
$SUDO mkdir -p $CNI_DIR
$SUDO cp -r ./bin $CNI_DIR
$SUDO mkdir -p $CNI_CONFIG_DIR
$SUDO cat << EOF | $SUDO tee $CNI_CONFIG_DIR/10-containerd-net.conflist
{
"cniVersion": "1.0.0",
"name": "containerd-net",
"plugins": [
{
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": true,
"promiscMode": true,
"ipam": {
"type": "host-local",
"ranges": [
[{
"subnet": "10.88.0.0/16"
}],
[{
"subnet": "2001:4860:4860::/64"
}]
],
"routes": [
{ "dst": "0.0.0.0/0" },
{ "dst": "::/0" }
]
}
},
{
"type": "portmap",
"capabilities": {"portMappings": true}
}
]
}
EOF
popd
rm -fR "${TMPROOT}"
위 명령어는 쿠버네티스 공식 홈페이지에서 cni를 관리하는 방법에 대해 깃허브에 올려준 명령어이다.
하나하나씩 살펴보면,
이 스크립트는 크게 세 단계로 나뉜다.
즉, 1번과 2번은 사용자가 직접 해줘야 하는 부분이고,
3번은 kubelet/containerd가 자동으로 수행하는 부분이다.
1. 사용자가 직접 해야하는 부분 (핵심)
(1)CNI 플러그인 서치
CNI_DIR=${DESTDIR:=''}/opt/cni
...
git clone "${CNI_REPO}" "${TMPROOT}"/plugins
./build_linux.sh
$SUDO mkdir -p $CNI_DIR
$SUDO cp -r ./bin $CNI_DIR
사용자는
CNI 플러그인(bridge, host-local, portmap 등)을 직접 빌드 및 복사하고
/opt/cni/bin에 설치한다.
-> 이 디렉토리(/opt/cni/bin)는 CNI 플러그인 바이너리가 저장되는 표준 경로다.
쿠버네티스는 나중에 파드 생성 시, 이 경로에서 “bridge”, “host-local” 같은 플러그인을 찾아 실행한다.
(2) CNI 설정 파일 생성
$SUDO mkdir -p $CNI_CONFIG_DIR
$SUDO cat << EOF | $SUDO tee $CNI_CONFIG_DIR/10-containerd-net.conflist
{
"cniVersion": "1.0.0",
"name": "containerd-net",
"plugins": [
{
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": true,
"promiscMode": true,
"ipam": {
"type": "host-local",
"ranges": [
[{
"subnet": "10.88.0.0/16"
}],
[{
"subnet": "2001:4860:4860::/64"
}]
]
}
},
{
"type": "portmap",
"capabilities": {"portMappings": true}
}
]
}
EOF
어떤 네트워크 플러그인을 사용할지 (bridge, portmap 등)
IP 대역(subnet), 게이트웨이 설정, NAT 여부(ipMasq)
IPv6 사용 여부, 포트 매핑 정책
등을 직접 JSON 파일로 정의한다.
이게 바로 “CNI 구성 파일”이자,
CNI가 쿠버네티스와 연동될 때 필요한 핵심 설정 영역이다.
이 파일이 /etc/cni/net.d 안에 있으면,
kubelet은 파드가 뜰 때 해당 설정을 자동으로 읽어
bridge 플러그인 실행 → veth 인터페이스 생성 → IP 할당 과정을 수행한다.
과거 쿠버네티스 1.24 이전에는 어떻게 했는지 비교 (플러그인 제공 및, kubelet이 직접 관리)
--network-plugin=cni \ --cni-bin-dir=/opt/cni/bin \ --cni-conf-dir=/etc/cni/net.dkubelet이 직접 /opt/cni/bin 경로를 탐색해서 CNI 플러그인을 실행했고,
/etc/cni/net.d의 설정 파일(.conflist)을 직접 읽어서 CNI를 관리했다.
사용자가 별도 설치하지 않아도 kubeadm으로 클러스터 생성 시 자동 구성되기도 했다.
그러나 1.24 이후에는
--network-plugin 옵션이 완전히 제거되었고,
kubelet이 CNI를 “직접 관리”하지 않는다.
요약 표
| 구분 | 1.24 이전 | 1.24 이후 | | ---------- | ----------------------------------------------------- | ---------------------------------------- | | CNI 관리 주체 | kubelet이 직접 관리 | 사용자가 설치 및 설정 | | 주요 옵션 | `--network-plugin`, `--cni-bin-dir`, `--cni-conf-dir` | 제거됨 | | 설정 경로 | `/etc/cni/net.d` | 동일 | | 동작 방식 | kubelet이 플러그인 실행 및 관리 | kubelet이 단순히 호출만 수행 | | 사용 예시 | kubeadm에서 자동 설치 | 사용자가 직접 구성 (예: Calico, Flannel 등) |
참고자료
[wikidocs - 08장: 쿠버네티스 네트워킹 아키텍처 심층 분석]
https://wikidocs.net/303565
[쿠버네티스 공식 홈페이지 - Network Plugins]
https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/
[쿠버네티스 공식 깃허브 - install-cni]
https://github.com/containerd/containerd/blob/main/script/setup/install-cni
[CNF - Container Network Interface]
https://www.cncf.co.kr/community/container-network-interface/