Container Runtime은 Pod 생성시, 다음과 같은 방법으로 CNI에게 Network 설정을 요청한다.
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 |