Multus CNI 연동

Prev Next

Multus CNI를 사용하여 다중 네트워크 인터페이스를 가지는 Pod 생성 방법을 설명합니다.

Multus CNI는 단일 Pod에 여러 네트워크 인터페이스를 연결하고 각각을 다른 주소 범위로 연결할 수 있도록 하는 고급 네트워크 구성 기능을 제공하는 CNI 플러그인입니다.

  • Kubernetes 에서 각 Pod 은 기본적으로 Loopback 외에 하나의 네트워크 인터페이스만 가지고 있습니다. Multus CNI를 이용하면 여러 인터페이스가 있는 Multi-Home Pod을 만들 수 있습니다.
  • Multus CNI는 다른 CNI 플러그인을 호출할 수 있는 일종의 메타 플러그인의 역할을 합니다. 따라서 Multus CNI와 연동될 다른 CNI를 필요로 합니다.
참고

Multus CNI 에 대한 더 자세한 설명은 Multus CNI 저장소를 참고해 주십시오.

Multus CNI를 설치하는 방법은 다음과 같습니다.

  1. 아래 명령을 통해 Cilium CNI의 CNI-Exclusive 모드를 비활성화해 주십시오.

    kubectl patch daemonset cilium -n kube-system --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/lifecycle/postStart/exec/command/2", "value": "--cni-exclusive=false"}]'
    
    Plain text
  2. Multus CNI의 Github 저장소를 복제한 후 Daemonset을 설치해 주십시오.

    git clone https://github.com/k8snetworkplumbingwg/multus-cni.git && cd multus-cni
    cat ./deployments/multus-daemonset.yml | kubectl apply -f -
    
    Plain text
    • Multus Daemonset 은 각 워커 노드에서 Multus 의 실행 파일을 /opt/cni/bin 위치에 배치합니다. 그리고 CNI 의 구성을 위한 /etc/cni/net.d/00-multus.conf 설정 파일을 생성합니다.
    • kubectl get pods --all-namespaces | grep -i multus 를 통해 각 노드에 Multus Pod이 성공적으로 실행됐는지 확인할 수 있습니다.
    • Multus CNI를 통해 연동될 ipvlan 을 워커 노드에 다운로드합니다.
      root@afaf-w-1vhl:~# curl -L https://github.com/containernetworking/plugins/releases/download/v1.2.0/cni-plugins-linux-amd64-v1.2.0.tgz | tar zx -C /opt/cni/bin ./host-local ./ipvlan
      
      Plain text
  3. 추가 인터페이스를 생성해 주십시오.

    • Server 사용 가이드의 Network Interface를 참고하여 네트워크 인터페이스를 생성한 다음 워커 노드에 할당합니다.
    • 생성된 인터페이스에 Secondary IP를 할당합니다. 이때 Secondary IP는 연속된 IP로 구성되어야 합니다.
    • 다음과 같이 eth1 인터페이스가 성공적으로 생성됐는지 확인할 수 있습니다.
      root@afaf-w-1vhl:~# ip a
      ...
      2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 8950 qdisc mq state UP group default qlen 1000
          link/ether f2:20:af:24:62:41 brd ff:ff:ff:ff:ff:ff
          inet 192.168.1.104/26 brd 192.168.1.127 scope global eth0
          valid_lft forever preferred_lft forever
      1304: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
          link/ether f2:20:af:a6:0a:e2 brd ff:ff:ff:ff:ff:ff
          inet 192.168.0.12/24 brd 192.168.0.255 scope global eth1
          valid_lft forever preferred_lft forever
      
      Plain text
  4. Network Attachment Definition CRD를 생성해 주십시오.

    • Pod에서 사용할 추가 ipvaln 인터페이스를 위한 설정을 제공하기 위해 Network Attachment Definition을 생성합니다. Network Attachment Definition은 네트워크를 Pod에 연결하는 방법을 정의하는 Custom Resource Definition입니다.
    • 다음과 같이 ipvlan을 사용하기 위한 설정을 생성합니다.
      apiVersion: "k8s.cni.cncf.io/v1"
      kind: NetworkAttachmentDefinition
      metadata:
        name: ipvlan-conf-1
      spec:
        config: '{
          "cniVersion": "0.3.0",
          "type": "ipvlan",
          "master": "eth1",
          "mode": "l3",
          "ipam": {
              "type": "host-local",
              "subnet": "192.168.1.0/24",
              "rangeStart": "192.168.1.13",
              "rangeEnd": "192.168.1.17",
              "gateway": "192.168.1.1"
          }
        }'
      
      Plain text
    • rangeStart, rangeEnd 를 이용해 앞에서 인터페이스에 할당된 Secondary IP 대역을 지정합니다.
    • kubectl get network-attachment-definitions 를 통해 생성된 설정을 확인할 수 있습니다.
    • 본 예제에서 사용된 host-local ipam은 노드 단위로 IP 풀을 관리합니다. 전체 클러스터 범위의 IP 풀이 필요한 경우 whereabouts ipam을 사용해야 합니다.

Multus CNI를 연동하는 방법은 다음과 같습니다.

  1. 추가 인터페이스를 사용하는 Pod을 생성해 주십시오.
    • 이제 추가 인터페이스를 사용하는 Pod 을 생성할 수 있습니다. 사용할 추가 인터페이스는 k8s.v1.cni.cncf.io/networks annotation을 통해 지정할 수 있습니다. 해당 필드에 지정되는 이름은 앞서 생성한 Network Attachment Definition의 이름입니다.
    • 만약 다수의 인터페이스를 연결하고자 한다면 이 annotation에 쉼표를 구분자로 여러 네트워크 설정을 지정합니다.
    apiVersion: v1
    kind: Pod
    metadata:
      name: sampleapp-1
      annotations:
        k8s.v1.cni.cncf.io/networks: ipvlan-conf-1
    spec:
      containers:
      - name: multitool
        command: ["sh", "-c", "trap : TERM INT; sleep infinity & wait"]
        image: praqma/network-multitool
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: sampleapp-2
      annotations:
        k8s.v1.cni.cncf.io/networks: ipvlan-conf-1
    spec:
      containers:
      - name: multitool
        command: ["sh", "-c", "trap : TERM INT; sleep infinity & wait"]
        image: praqma/network-multitool
    
    Plain text
  2. 추가 인터페이스를 확인해 주십시오.
    • kubectl describe pod sampleapp-1을 통해 k8s.v1.cni.cncf.io/network-status annotation이 모든 네트워크 인터페이스를 표시하는지 확인합니다.
      $ kubectl describe pod sampleapp-1
      Name:         sampleapp-1
      Namespace:    default
      Priority:     0
      Node:         afaf-w-293f/192.168.1.104
      Start Time:   Mon, 06 Feb 2023 16:18:38 +0900
      Labels:       <none>
      Annotations:  k8s.v1.cni.cncf.io/networks: ipvlan-conf-1
                  k8s.v1.cni.cncf.io/networks-status:
                      [{
                          "name": "cilium",
                          "interface": "eth0",
                          "ips": [
                              "198.18.1.173"
                          ],
                          "mac": "12:7d:62:5b:2e:57",
                          "default": true,
                          "dns": {}
                      },{
                          "name": "default/ipvlan-conf-1",
                          "interface": "net1",
                          "ips": [
                              "192.168.1.13"
                          ],
                          "mac": "f2:20:af:a6:0a:e2",
                          "dns": {}
                      }]
      
      Plain text
    • 실제로 Pod에 연결된 추가 인터페이스(net1)가 위에 나열된 IP로 실행 중인지 확인합니다.
      $ kubectl exec -it sampleapp-1 -- ip a
      ...
      2: net1@if1304: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
          link/ether f2:20:af:a6:0a:e2 brd ff:ff:ff:ff:ff:ff
          inet 192.168.1.13/24 brd 192.168.1.255 scope global net1
          valid_lft forever preferred_lft forever
      1975: eth0@if1976: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 8950 qdisc noqueue state UP group default
          link/ether 12:7d:62:5b:2e:57 brd ff:ff:ff:ff:ff:ff link-netnsid 0
          inet 198.18.1.173/32 scope global eth0
          valid_lft forever preferred_lft forever
      
      Plain text
    • 추가된 net1 인터페이스에 대한 라우팅 정보와 통신 가능 여부를 확인합니다.
      # kubectl exec -it sampleapp-1 -- route -n
      Kernel IP routing table
      Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
      0.0.0.0         198.18.1.209    0.0.0.0         UG    0      0        0 eth0
      192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 net1
      198.18.1.209    0.0.0.0         255.255.255.255 UH    0      0        0 eth0
      
      # kubectl exec -it sampleapp-1 -- ping -I net1 192.168.1.14
      PING 192.168.1.14 (192.168.1.14) from 192.18.1.13 net1: 56(84) bytes of data.
      64 bytes from 192.168.1.14: icmp_seq=1 ttl=64 time=0.055 ms
      64 bytes from 192.168.1.14: icmp_seq=2 ttl=64 time=0.055 ms
      
      Plain text

수동으로 추가된 Network Interface 는 새로 증설되는 워커 노드에는 적용되지 않습니다. 또한 노드 풀 변경 과정에서 추가 Network Interface 가 할당된 워커 노드에 제거될 경우 기 운영중엔 Pod 에 영향이 있을 수 있습니다.