Network - CNI(Container Network Interface)

2026. 1. 5. 22:09·CKA

앞선 글에서 우리는 리눅스 네트워크 네임스페이스(netns)로 컨테이너 네트워크 격리가 어떻게 동작하는지 손으로 만들며 확인했습니다.

  • netns를 만들고
  • veth(가상 케이블)로 네임스페이스를 연결하고
  • 브리지(가상 스위치)를 올려 여러 네임스페이스를 같은 L2 네트워크에 붙이고
  • 라우팅 테이블을 구성하고
  • 외부로 나가려면 NAT(마스커레이드)가 필요하며
  • 외부에서 들어오려면 포트포워딩이 필요하다는 것까지

그리고 Docker의 bridge 네트워크(docker0)도 사실상 똑같은 패턴(netns + veth + bridge + iptables) 으로 구현된다는 걸 봤습니다(이름만 다를 뿐).

그런데 여기서 중요한 질문이 생깁니다.

다들 비슷한 방식으로 컨테이너 네트워크를 구성하는데, 왜 각 런타임/오케스트레이터가 네트워크 코드를 매번 다시 구현하지?

이 문제를 해결하기 위해 등장한 것이 CNI(Container Network Interface) 입니다.


1) CNI는 왜 필요한가?

컨테이너 생태계에는 Docker만 있는 게 아닙니다.

  • rkt(rocket)
  • CRI-O
  • containerd
  • Mesos 등…

또한 Kubernetes는 다양한 런타임과 네트워크 솔루션을 받아들이는 방향으로 발전해 왔습니다.

하지만 “컨테이너를 네트워크에 붙이는 작업”은 거의 항상 비슷합니다.

  • 컨테이너(netns) 생성
  • veth pair 생성
  • 한쪽은 컨테이너 netns로 이동
  • 한쪽은 호스트 브리지(또는 다른 네트워크 장치)에 연결
  • IP 할당 + routes 설정
  • 필요하면 NAT/정책/캡슐화(overlay) 등 추가

이걸 각 런타임이 직접 구현하면:

  • 중복 개발
  • 구현 차이로 인한 호환성 문제
  • 특정 오케스트레이터/특정 런타임에 종속되는 네트워크 생태계

그래서 “컨테이너 네트워크 세팅”을 플러그인으로 분리하고, 런타임은 “플러그인을 어떤 방식으로 호출해야 하는지”만 표준화하자 → 그게 CNI입니다.


2) CNI의 핵심 아이디어: 네트워크 설정을 “플러그인 프로그램”으로 분리

강의에서는 예시로 bridge라는 프로그램(플러그인)을 가정합니다.

  • 컨테이너 런타임(Kubernetes, rkt 등)이 컨테이너를 만들 때
  • “이 컨테이너를 브리지 네트워크에 붙여줘”라고 플러그인을 호출하면
  • 플러그인이 필요한 작업을 전부 수행합니다.

즉, 네트워크 설정은 런타임 내부 코드가 아니라 외부 플러그인 실행으로 처리됩니다.


3) CNI가 “표준”으로 정의하는 것들

CNI는 크게 두 축을 정의합니다.

3.1 컨테이너 런타임(Runtime)의 책임

런타임은 네트워크를 직접 구성하는 게 아니라, 아래 책임을 갖습니다.

  • 컨테이너마다 네트워크 네임스페이스(netns) 를 만든다.
  • 컨테이너가 붙어야 할 네트워크(플러그인)를 결정한다.
  • 컨테이너 생성 시 플러그인을 ADD로 호출한다.
  • 컨테이너 삭제 시 플러그인을 DEL로 호출한다.
  • 어떤 플러그인을 쓸지에 대한 설정을 JSON 구성 파일로 관리한다.

3.2 플러그인(Plugin)의 책임

플러그인은 “컨테이너를 네트워크에 실제로 붙이는 역할”을 합니다.

  • ADD, DEL, CHECK 같은 명령을 지원해야 한다.
  • 입력으로 컨테이너 ID, netns 경로 등 필요한 파라미터를 받아야 한다.
  • IP 할당, 라우팅 설정 등을 수행한다.
  • 결과를 CNI가 정한 형식으로 반환한다.

런타임과 플러그인이 이 표준을 지키면, “어떤 런타임이든 어떤 플러그인이든” 조합이 가능해집니다.


4) CNI 플러그인 종류: 기본 플러그인 + 서드파티 플러그인

CNI는 기본적으로 여러 플러그인을 제공합니다.

  • bridge
  • vlan
  • macvlan
  • (Windows용 플러그인도 존재)
  • IPAM 플러그인(주소 할당 전용): host-local, dhcp 등

그리고 실제 Kubernetes에서 많이 쓰는 네트워크 솔루션들은 대부분 CNI 기반입니다.

  • Flannel
  • Calico
  • Cilium
  • Weave
  • VMware NSX 등

이들이 “쿠버네티스에서 네트워크가 되게 만드는 방식”은 결국 CNI 표준을 따르는 플러그인을 제공하는 것입니다.


5) “근데 Docker는 CNI가 아니잖아?” → Docker는 CNM(Container Network Model)

여기서 많은 분들이 혼란스러워하는 지점이 나옵니다.

  • Docker는 CNI 표준을 “네이티브로” 구현한 런타임이 아닙니다.
  • Docker는 Docker 자체 네트워킹 모델인 CNM(Container Network Model) 을 사용합니다.

그래서 “Docker run 하면서 CNI 플러그인을 지정해서 바로 쓰기”는 일반적으로 불가능합니다.


6) 그렇다면 Kubernetes는 Docker를 쓸 때 CNI를 어떻게 썼나?

정답은 의외로 단순합니다.

“Docker(CNM) 네트워크를 쓰게 하는 게 아니라, Docker에게는 ‘netns만 가진 컨테이너’를 만들게 하고, 실제 네트워크 세팅은 Kubernetes가 CNI로 해버린다.”

전형적인 흐름은 다음과 같습니다(개념 설명용).

  1. Kubernetes가 파드 샌드박스(일명 pause 컨테이너)를 네트워크 없이 만든다(= Docker 네트워크 구성을 최소화)
  2. kubelet이 CNI 플러그인을 호출하면서 그 샌드박스의 netns 경로를 넘긴다
  3. CNI 플러그인이 리눅스 커널 레벨에서 veth/bridge/IP/route 등을 구성한다
  4. 파드 안의 다른 컨테이너는 “pause 컨테이너의 netns를 공유”하는 방식으로 실행되어 Pod 단위로 IP 1개를 갖는다

핵심은 이겁니다.

  • CNI는 “Docker의 CNM 위에서 동작하는 기능”이 아니라
  • 리눅스의 네트워크 네임스페이스(netns)를 대상으로 네트워크를 세팅하는 표준입니다.
  • Docker는 netns를 만들어주는 런타임일 뿐이고, CNI는 그 netns에 네트워크를 붙입니다.

7) (추가) Kubernetes 클러스터 노드(마스터/워커) 네트워킹 준비 체크리스트

CNI를 설치하고 파드 네트워크가 잘 붙으려면, 그 전에 노드 레벨 기본 네트워킹이 정상이어야 합니다. 강의에서 강조하는 포인트는 다음입니다.

7.1 모든 노드는 네트워크 인터페이스와 IP가 있어야 한다

  • 마스터(컨트롤 플레인) 노드와 워커 노드 모두
    • 최소 1개 이상 네트워크 인터페이스가 필요
    • 각 인터페이스에는 IP 주소가 설정되어야 함

확인:

ip link
ip addr
ip route

7.2 각 노드는 “유니크한 hostname”과 “유니크한 MAC 주소”가 필요

특히 VM을 클론(clone) 해서 만들면 hostname이나 MAC이 겹치는 경우가 있습니다. 이러면 네트워크/클러스터에서 이상한 문제가 발생할 수 있습니다.

확인:

hostname
hostnamectl
cat /etc/hostname

# MAC 주소 확인(인터페이스별)
ip link | grep -E "link/ether|^[0-9]+:"
# 또는
for i in /sys/class/net/*/address; do echo "$i: $(cat $i)"; done

7.3 컨트롤 플레인/노드에서 열려 있어야 하는 포트들

클러스터 구성요소가 통신하려면 특정 포트들이 열려 있어야 합니다(방화벽/iptables/클라우드 SG 포함).

Control Plane(마스터)가 받아야 하는 대표 포트

  • 6443: kube-apiserver (kubectl, 워커 kubelet, 컨트롤플레인 컴포넌트들이 접근)
  • 10257: kube-controller-manager
  • 10259: kube-scheduler
  • 2379: etcd (멀티 마스터/외부 etcd 등에서 클라이언트 접근)
  • 2380: etcd peer 통신(멀티 etcd 멤버 간)

참고: kubelet은 마스터 노드에도 존재할 수 있습니다(컨트롤플레인 노드에서 파드가 돌 수 있는 구성이라면 더더욱).

Worker Node에서 중요한 포트

  • 10250: kubelet이 리슨(마스터/클러스터 구성요소가 kubelet에 접근할 때 사용)
  • 30000–32767: NodePort 서비스 범위(외부 노출용)

포트 상태 확인:

# 리슨 중인 포트 확인(둘 중 하나)
sudo ss -lntp
sudo netstat -lntp

# kube-apiserver(6443) 도달성 테스트 예시
curl -k https://<control-plane-ip>:6443/healthz

7.4 “뭔가 안 된다” 싶을 때 제일 먼저 보는 곳

  • 노드 간 라우팅/방화벽/보안그룹 규칙
  • 위 포트들이 실제로 열려 있는지
  • hostname/MAC 중복 여부(특히 VM 클론 환경)

클라우드 환경(AWS/GCP/Azure)이라면:

  • Security Group / NSG / Firewall Rules에서 포트 허용 여부를 먼저 확인하는 게 빠릅니다.

8) (중요) CNI 설치/네트워크 애드온과 CKA 시험 팁

실습(랩)에서 네트워크 애드온(CNI 플러그인)을 설치하는 문제가 나옵니다. 강의에서는 weave-net을 예로 들었지만, 실제로는 다양한 CNI를 사용할 수 있습니다.

CNI/네트워크 애드온 관련 공식 문서 링크(시험 주의사항 때문에 본문에서는 코드 블록으로 첨부):

https://kubernetes.io/docs/concepts/cluster-administration/addons/
https://kubernetes.io/docs/concepts/cluster-administration/networking/#how-to-implement-the-kubernetes-networking-model

CKA 시험에서의 포인트

  • “네트워크 애드온 설치” 문제가 나오면, 문제에서 특정 솔루션을 지시하지 않는 이상 위 범주에 속하는 어떤 솔루션을 써도 됩니다.
  • 다만 Kubernetes 공식 문서는 의도적으로 벤더 중립을 유지하므로,
    • “특정 서드파티 CNI를 설치하는 정확한 커맨드”를 쿠버네티스 공식 문서에서 직접 제공하지 않습니다.
    • 위 문서 링크는 결국 서드파티/벤더 사이트나 GitHub로 리다이렉트될 수 있고,
    • 시험 환경에서는 그런 외부 벤더 문서/깃헙을 그대로 볼 수 없는 제약이 있을 수 있습니다.

강의에서 강조한 결론:

  • 공식 시험에서는 필요한 CNI 배포 세부정보(명령/매니페스트 등)를 문제에 제공됩니다.

9) 한 문장 요약 + 다음에 이어질 내용

CNI를 한 문장으로 정리하면

컨테이너 네트워크를 구성하는 작업을 런타임에서 분리해 “플러그인”으로 만들고, 런타임과 플러그인이 어떻게 상호작용해야 하는지를 표준화한 인터페이스다.

  • 런타임: netns 만들고 플러그인(ADD/DEL) 호출
  • 플러그인: veth/bridge/IP/route 등을 실제로 설정
  • 표준만 지키면 조합 가능

그리고 실제 운영/시험 관점에서는:

  • 노드 기본 네트워크(인터페이스/IP/hostname/MAC/필수 포트)가 먼저 정상이어야 하고
  • 그 위에서 CNI가 pod 네트워크를 구성하며
  • 문제가 생기면 “CNI 이전(노드 레벨)”과 “CNI 이후(pod 네트워크 레벨)”를 나눠서 진단하는 게 핵심입니다.

 

Practice Test - https://uklabs.kodekloud.com/topic/practice-test-explore-environment-2/

'CKA' 카테고리의 다른 글

Network - Pod Networking & CNI  (1) 2026.01.05
Network - 정리(1)  (1) 2026.01.05
Network - Docker Network  (0) 2026.01.05
Network - 네트워크 기초(veth, bridge, routing, NAT, port-forward)  (1) 2026.01.05
Network - 네트워크 기초(DNS)  (0) 2026.01.05
'CKA' 카테고리의 다른 글
  • Network - Pod Networking & CNI
  • Network - 정리(1)
  • Network - Docker Network
  • Network - 네트워크 기초(veth, bridge, routing, NAT, port-forward)
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (243)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (119)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      @discriminatorcolumn
      프록시 팩토리
      자바
      조회 성능 최적화
      JPQL
      단방향 맵핑
      프록시
      @within
      락
      cglib
      스레드
      requset scope
      WAS
      양방향 맵핑
      jdk 동적 프록시
      버퍼
      빈 후처리기
      jpq
      log trace
      Target
      페치 조인
      김영한
      hibernate5module
      @discriminatorvalue
      고급
      gesingleresult
      typequery
      reentarantlock
      @args
      Thread
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    Network - CNI(Container Network Interface)
    상단으로

    티스토리툴바