Cilium과 함께하는 Kata Containers

Cilium과 함께하는 Kata Containers (Kata Containers with Cilium)

이 가이드는 Kata Containers와 함께 Cilium을 설치하는 방법을 보여줘요. Kata Containers 런타임의 상이한 네트워킹 모델로 인한 제한 사항과 이를 해결하는 작업 방법(workaround)도 설명해요.

출처: Kata Containers with Cilium

본문

Warning Kata Containers의 상이한 네트워킹 모델 때문에 Cilium에서 연결성 중단을 일으킬 수 있는 제한 사항이 있어요. 아래 제한 사항 섹션을 참고하세요.

이 가이드는 Kata Containers와 함께 Cilium을 설치하는 방법을 보여줘요. 공식 Kata Containers installation user guide를 따라 선택한 플랫폼에서 Kata Containers 런타임을 실행 중이지만 아직 Kubernetes를 설정하지 않은 상태라고 가정해요.

Note 이 가이드는 Kata Containers 가이드를 Google Compute Engine(GCE)에 대해 따르고, 패키지된 버전의 Kata Containers, CRI-containerd, Kubernetes 1.18.3과 함께 Ubuntu 18.04 LTS를 사용해 검증됐어요.

CRI로 Kubernetes 설정 (Setup Kubernetes with CRI)

Kata Containers 런타임은 OCI 호환 런타임이며 CRI API 수준과 직접 상호작용할 수 없어요. 이런 이유로 CRI를 OCI로 변환하는 CRI 구현에 의존해요. 이 가이드를 작성할 당시 CRI-O와 CRI-containerd라는 두 가지 지원되는 방식이 있어요. 원하는 것을 선택하면 되지만 반드시 하나는 골라야 해요.

Kubernetes 환경을 준비하는 방법에 대한 자세한 지침은 Requirements 섹션을 참고하고 Kubernetes >= 1.12를 사용해야 해요. 그런 다음 Kubernetes와 함께 Kata Containers를 실행하는 공식 가이드를 따라 하세요.

Note 아래에서 설명하는 Kata Container 런타임의 RuntimeClass Feature를 사용하려면 최소 kubernetes 1.12 버전이 필요해요.

Kubernetes 클러스터가 준비되면 이제 Cilium 배포를 진행할 수 있어요.

Cilium 배포 (Deploy Cilium)

Helm 저장소를 설정하세요:

Helm Repository OCI Registry

helm repo add cilium https://helm.cilium.io/

Cilium 차트는 OCI 레지스트리(Quay.io 및 Docker Hub)에서도 사용할 수 있어요. 설정이 필요 없으며 oci:// URL로 직접 설치할 수 있어요.

차트 서명 검증과 digest 기반 설치를 포함한 자세한 내용은 OCI Registry section을 참고하세요.

Helm으로 Cilium 릴리스를 배포하세요:

Using CRI-O Using CRI-containerd Helm Repository OCI Registry

helm install cilium cilium/cilium --version 1.20.2 \

--namespace kube-system
--set bpf.autoMount.enabled=false


helm install cilium oci://quay.io/cilium/charts/cilium 1.20.2
--namespace kube-system
--set bpf.autoMount.enabled=false


Helm Repository
OCI Registry

helm install cilium cilium/cilium --version 1.20.2
--namespace kube-system


helm install cilium oci://quay.io/cilium/charts/cilium 1.20.2
--namespace kube-system

Warning Kata 컨테이너와 함께 kube-proxy-replacement 또는 그 소켓 수준 로드밸런서를 사용할 때는, socketLB.hostNamespaceOnly=true로 설정해 파드에 대한 소켓 수준 로드밸런서를 비활성화해야 해요. 자세한 내용은 Socket LoadBalancer Bypass in Pod Namespace를 참고하세요.

설치 검증 (Validate the Installation)

Cilium CLI Manually Cilium CLI의 최신 버전을 설치하세요. Cilium CLI는 Cilium 설치, Cilium 설치 상태 조회, 다양한 기능(예: clustermesh, Hubble) 활성화/비활성화에 사용할 수 있어요.

Linux macOS Other

CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "arm64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-darwin-${CLI_ARCH}.tar.gz{,.sha256sum}
shasum -a 256 -c cilium-darwin-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-darwin-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-darwin-${CLI_ARCH}.tar.gz{,.sha256sum}

releases의 전체 페이지를 참고하세요.

Cilium이 제대로 설치됐는지 검증하려면 다음을 실행하면 돼요:

$ cilium status --wait
   /¯\
/¯\__/¯\    Cilium:         OK
\__/¯\__/    Operator:       OK
/¯\__/¯\    Hubble:         disabled
\__/¯\__/    ClusterMesh:    disabled
   \__/

DaemonSet         cilium             Desired: 2, Ready: 2/2, Available: 2/2
Deployment        cilium-operator    Desired: 2, Ready: 2/2, Available: 2/2
Containers:       cilium-operator    Running: 2
                  cilium             Running: 2
Image versions    cilium             quay.io/cilium/cilium:v1.9.5: 2
                  cilium-operator    quay.io/cilium/operator-generic:v1.9.5: 2

다음 명령을 실행해 클러스터에 올바른 네트워크 연결성이 있는지 검증하세요:

$ cilium connectivity test
ℹ️  Monitor aggregation detected, will skip some flow validation steps
✨ [k8s-cluster] Creating namespace for connectivity check...
(...)
---------------------------------------------------------------------------------------------------------------------
📋 Test Report
---------------------------------------------------------------------------------------------------------------------
✅ 69/69 tests successful (0 warnings)

Note 연결성 테스트는 파드 하나 이상에서 열린 파일이 너무 많아 배포에 실패할 수 있어요. 이 오류가 보이면 호스트 머신의 inotify 리소스 한도를 늘리면 돼요 ("too many open files"로 인한 파드 오류 참고).

축하합니다! Cilium이 탑재된 완전히 동작하는 Kubernetes 클러스터를 갖추셨어요. 🎉

Cilium과 모든 필수 컴포넌트가 설치되는 것을 모니터링할 수 있어요:

$ kubectl -n kube-system get pods --watch
NAME                                    READY   STATUS              RESTARTS   AGE
cilium-operator-cb4578bc5-q52qk         0/1     Pending             0          8s
cilium-s8w5m                            0/1     PodInitializing     0          7s
coredns-86c58d9df4-4g7dd                0/1     ContainerCreating   0          8m57s
coredns-86c58d9df4-4l6b2                0/1     ContainerCreating   0          8m57s

모든 컴포넌트가 뜨는 데 몇 분 걸릴 수 있어요:

cilium-operator-cb4578bc5-q52qk         1/1     Running   0          4m13s
cilium-s8w5m                            1/1     Running   0          4m12s
coredns-86c58d9df4-4g7dd                1/1     Running   0          13m
coredns-86c58d9df4-4l6b2                1/1     Running   0          13m

"connectivity-check"를 배포해 파드 간 연결성을 테스트할 수 있어요. 이를 위해 별도의 네임스페이스를 만드는 것이 좋아요.

kubectl create ns cilium-test

다음으로 체크를 배포하세요:

kubectl apply -n cilium-test -f https://raw.githubusercontent.com/cilium/cilium/1.20.2/examples/kubernetes/connectivity-check/connectivity-check.yaml

이것은 다양한 연결성 경로를 사용해 서로 연결되는 일련의 deployment를 배포해요. 연결성 경로에는 서비스 로드 밸런싱 유무와 다양한 네트워크 정책 조합이 포함돼요. 파드 이름은 연결성 변형을 나타내고, readiness 및 liveness 게이트는 테스트의 성공/실패를 나타내요:

$ kubectl get pods -n cilium-test
NAME                                                     READY   STATUS    RESTARTS   AGE
echo-a-76c5d9bd76-q8d99                                  1/1     Running   0          66s
echo-b-795c4b4f76-9wrrx                                  1/1     Running   0          66s
echo-b-host-6b7fc94b7c-xtsff                             1/1     Running   0          66s
host-to-b-multi-node-clusterip-85476cd779-bpg4b          1/1     Running   0          66s
host-to-b-multi-node-headless-dc6c44cb5-8jdz8            1/1     Running   0          65s
pod-to-a-79546bc469-rl2qq                                1/1     Running   0          66s
pod-to-a-allowed-cnp-58b7f7fb8f-lkq7p                    1/1     Running   0          66s
pod-to-a-denied-cnp-6967cb6f7f-7h9fn                     1/1     Running   0          66s
pod-to-b-intra-node-nodeport-9b487cf89-6ptrt             1/1     Running   0          65s
pod-to-b-multi-node-clusterip-7db5dfdcf7-jkjpw           1/1     Running   0          66s
pod-to-b-multi-node-headless-7d44b85d69-mtscc            1/1     Running   0          66s
pod-to-b-multi-node-nodeport-7ffc76db7c-rrw82            1/1     Running   0          65s
pod-to-external-1111-d56f47579-d79dz                     1/1     Running   0          66s
pod-to-external-fqdn-allow-google-cnp-78986f4bcf-btjn7   1/1     Running   0          66s

Note 연결성 체크를 단일 노드 클러스터에 배포하면 multi-node 기능을 확인하는 파드는 Pending 상태로 남아 있어요. 이 파드들은 성공적으로 스케줄링되려면 최소 2개 노드가 필요하므로 예상된 동작이에요.

테스트가 끝나면 cilium-test 네임스페이스를 삭제하세요:

kubectl delete ns cilium-test

Cilium CNI로 Kata Containers 실행 (Run Kata Containers with Cilium CNI)

이제 Kubernetes 클러스터가 Kata Containers 런타임과 CNI인 Cilium으로 구성되었으니, 이 지침에 따라 샘플 워크로드를 실행할 수 있어요.

제한 사항 (Limitations)

상이한 Networking Design Architecture 때문에 Kata 런타임은 Cilium이 만든 컨테이너 네트워킹 네임스페이스(이하 "outer") 안에 추상화 계층을 추가해요. 그 네임스페이스에서 Kata는 추가 컨테이너 네트워킹 네임스페이스(이하 "inside")를 가진 격리된 VM을 만들어 요청된 Pod를 호스팅해요 (아래 그림 참고).

outer 컨테이너 네트워킹 네임스페이스 생성 시 Cilium CNI는 다음 두 가지 작업을 수행해요:

  1. 감지된 하위 네트워크의 device MTU 또는 Cilium ConfigMap에 지정된 MTU와 같은 값으로 eth0 인터페이스를 생성해요.
  2. Cilium 구성이 주는 추가 네트워킹 오버헤드(예: VXLAN의 경우 +50B, WireGuard의 경우 +80B 등)를 고려하도록 default route MTU(device MTU - overhead로 계산)를 조정해요.

그러나 inner 컨테이너 네트워킹 네임스페이스(즉 VM 안의 파드) 생성 중에는 Kata가 outer eth0 device MTU(1)만 inner eth0에 복사하고, default route MTU(2)는 무시돼요. 이런 이유로 연결 유형에 따라 사용자는 전통적인 파드와 KataPod 연결 사이에서 여러 (예상치 못한) 조각화로 인한 성능 저하나 패킷 드롭을 겪을 수 있어요.

현재 두 가지 방법이 가능하며 (b)가 권장돼요:

  1. Cilium ConfigMap에서 오버헤드를 고려하도록 더 낮은 MTU 값을 설정. 이렇게 하면 KataPod가 더 낮은 디바이스 MTU를 갖고 원치 않는 조각화를 방지할 수 있어요. 그러나 모든 Cilium 관리 인터페이스에 더 낮은 디바이스 MTU 값이 설정되므로 다른 모든 유형의 통신(예: 전통적인 pod-to-pod, pod-to-node 등)에 상당한 영향을 미쳐 권장되지 않아요.

  2. KataPod 배포에 initContainer(NET_ADMIN 사용)를 추가해 inner pod 안의 라우트 MTU를 조정. 이는 KataPod 구성을 다른 모든 파드와 일치시킬 뿐 아니라 KataPod 자체 안에 자체 포함된 해결책이므로 다른 모든 유형의 연결에도 해를 끼치지 않아요. 설정할 올바른 route MTU 값은 수동으로 계산하거나 Cilium Pod(또는 전통적인 파드)에서 ip route를 실행해 얻을 수 있어요. 다음은 Cilium VXLAN만 활성화된 클러스터(route MTU = 1500B - 50B = 1450)의 KataPod 배포(runtimeClassName: kata-clh) 예시예요:

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-pod
      labels:
        app: nginx
    spec:
      runtimeClassName: kata-clh
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
      initContainers:
        - name: set-mtu
          image: busybox:latest
          command:
            - sh
            - -c
            - |
              DEFAULT="$(ip route show default)"
              ip route replace "$DEFAULT" mtu 1450
          securityContext:
            capabilities:
              add:
                - NET_ADMIN
    

더 알아보기 (Learn more)