Kubernetes/Architecture

CNI - Spec

Operation CWAL 2021. 1. 24. 18:10

 

Container Runtime은 Pod 생성시, 다음과 같은 방법으로 CNI에게 Network 설정을 요청한다.

CNI 플러그인 Invocation

CNI 플러그인이 지원해야하는 Operation

CNI 플러그인은 실행가능한 파일로 구현하여, 각 Container Runtime Engine(Docker, rkt 등)에 의해 호출된다. 네트워크 인터페이스를 컨테이너의 Network Namespace에 추가하고, 호스트와 연결(veth pair)한다. 또한 IPAM 플러그인을 통해인터페이스에 IP를 할당하고, Routing Rule을 갱신할 수 있어야 한다.

CNI Spec v0.4.0을 기준으로 다음과 같은 4개의 Operation을 지원해야 한다.

  • ADD: 네트워크에 Container 추가
  • DEL: 네트워크에서 Container 제거
  • CHECK: Container의 Network 설정이 spec과 동일한지 확인
  • VERSION: Version 정보 확인

 

입력

Network Configuration

JSON 포맷으로 작성된 네트워크 설정이며, 일반적으로 Node에 저장된 파일(ex: /etc/cni/net.d/)을 가져와 stdin을 통해 CNI 플러그인에 전달한다. 자주 사용하는 필드는 다음과 같다.

  • cniVersion: 해당 플러그인이 구현한 CNI Spec 버전 명시, 현재 0.4.0까지 존재(2021-01-24 기준)
  • name: Network 이름
  • type: CNI 플러그인 실행파일(binary or script) 이름, 해당 파일이 '/opt/cni/' 경로에 실제로 존재해야 함
  • ipam(optional)
    • type: IPAM 플러그인 실행파일명
  • dns(optional)
    • nameservers: 현재 네트워크서 사용하는 DNS Nameserver를 우선순위대로 명시
    • domain: Hostname hookup에 사용할 local domain명
    • search: hostname hookup에 사용할 search domain
    • options: resolver에 전달할 옵션들
  • args(optional)
    • Container Runtime이 추가적으로 전달할 argument를 'args' 아래에 명시

예시

Calico 설치시, 아래와 같은 Network Configuration을 /etc/cni/net.d/10-calico.conflist 파일에 저장한다.

{
  "name": "k8s-pod-network",
  "cniVersion": "0.3.1",
  "plugins": [
    {
      "type": "calico",
      "log_level": "info",
      "log_file_path": "/var/log/calico/cni/cni.log",
      "datastore_type": "kubernetes",
      "nodename": "master",
      "mtu": 0,
      "ipam": {
          "type": "calico-ipam"
      },
      "policy": {
          "type": "k8s"
      },
      "kubernetes": {
          "kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
      }
    },
    {
      "type": "portmap",
      "snat": true,
      "capabilities": {"portMappings": true}
    },
    {
      "type": "bandwidth",
      "capabilities": {"bandwidth": true}
    }
  ]
}

 

하나의 CNI 플러그인이 아닌 여러개의 플러그인(calico, portmap, bandwidth)의 Configuration이 리스트 형식으로 정의되었음을 알 수 있다. 또한 name 필드는 따로 존재하지 않으며, args 대신 자체 정의한 필드(ex: log_level, policy 등)를 사용하고 있다. type 필드의 경우, 해당 경로(/opt/cni/bin)에 실제 실행파일이 아래와 같이 존재한다.

 

 

Runtime Information

CNI 플러그인 실행파일은 Runtime Information에 대한 Parameter를 환경변수(Environment Variable)를 통해 전달받는다.

  • CNI_COMMAND: 어떤 동작을 해야하는지 명시(ADD, DEL, CHECK, VERSION)
  • CNI_CONTAINERID: Container ID
  • CNI_NETNS: Network Namespace 파일(ex: /proc/[pid]/ns/net)
  • CNI_IFNAME: 설치할 Interface 이름
  • CNI_ARGS: 별도 추가할 Argument, "FOO=BAR;ABC=123" 형식으로 작성
  • CNI_PATH: CNI 플러그인 실행파일의 경로, ':'으로 여러개의 파일을 구분

출력

성공

플러그인은 ADD 동작 성공시, Exit Code 0을 반환하며 stdout에 아래와 같은 JSON 형식의 메시지를 출력한다.

{
  "cniVersion": "1.0.0",
  "interfaces": [                                            (this key omitted by IPAM plugins)
      {
          "name": "<name>",
          "mac": "<MAC address>",                            (required if L2 addresses are meaningful)
          "sandbox": "<netns path or hypervisor identifier>" (required for container/hypervisor interfaces, empty/omitted for host interfaces)
      }
  ],
  "ips": [
      {
          "address": "<ip-and-prefix-in-CIDR>",
          "gateway": "<ip-address-of-the-gateway>",          (optional)
          "interface": <numeric index into 'interfaces' list>
      },
      ...
  ],
  "routes": [                                                (optional)
      {
          "dst": "<ip-and-prefix-in-cidr>",
          "gw": "<ip-of-next-hop>"                           (optional)
      },
      ...
  ],
  "dns": {                                                   (optional)
    "nameservers": <list-of-nameservers>                     (optional)
    "domain": <name-of-local-domain>                         (optional)
    "search": <list-of-additional-search-domains>            (optional)
    "options": <list-of-options>                             (optional)
  }
}

 

실패

0이 아닌 Exit Code를 반환하며, stdout에 아래와 같은 JSON 형식의 메시지를 출력한다.

{
  "cniVersion": "1.0.0",
  "code": <numeric-error-code>,
  "msg": <short-error-message>,
  "details": <long-error-message> (optional)
}

 

 

참고
CNI SPEC
Writing a CNI - as easy as pie Write you own CNI (Container Network Interface)

 

 

'Kubernetes > Architecture' 카테고리의 다른 글

Pod Lifecycle  (0) 2021.03.07
Calico Components  (0) 2021.02.11
Linux Namespaces  (0) 2021.02.02
Cluster Networking  (0) 2021.01.22
Scheduler  (0) 2021.01.15