[cilium] flannel에서 cilium으로 마이그레이션 해보기

2025.07.16 - [K8S/🔥 network study🔥] - [cilium] flannel 설치하기

 

[cilium] flannel 설치하기

먼저 flannel 배포를 위한 네임스페이스를 생성합니다. kubectl create ns kube-flannel helm차트로 배포하는 가이드에는 다음과 같은 라벨을 추가하게 되어있습니다.네임스페이스에 라벨을 붙여 파드 시큐

nuguni.tistory.com

이전 글에서 flannel을 설치했다면 이번엔 cilium으로 마이그레이션을 해보겠습니다.

 

마이그레이션 공식 가이드를 참고해서 진행했습니다.

https://docs.cilium.io/en/stable/installation/k8s-install-migration/

 

시작하기 전

kubelet은 파드를 생성할때 /etc/cni/net.d/ 의 cni를 이용해서 파드의 네트워크를 구성합니다. flannel이 먼저 구성되어있는 환경에서 /etc/cni/net.d를 확인해보면 flannel 설정이 있는것을 확인할 수 있습니다.

이 설정을 이제 cilium으로 변경해야합니다. 설정을 변경한다고 해서 바로 신규 cni로 변경되는 것은 아니고 새로 생성되는 파드들에 대해서만 신규 cni를 통해 구성되게 됩니다. 

 

이렇기 때문에 노드에 모든 cni 설정을 변경한뒤 노드를 재시작 시키면 신규 cni로 쉽게 변경할 수 있습니다. 하지만 이렇게 하면 신규 cni로 모두 변경되기까지 통신이 불안정하기 때문에 cilium에서는 듀얼 오버레이를 사용하여 cni를 변경하게 됩니다.

 

듀얼 오버레이 모드를 사용하여 이전하기 

Cilium은 하이브리드 모드를 지원하여 클러스터 내에 두 개의 오버레이 네트워크를 동시에 구성할 수 있습니다. 각 노드의 파드는 하나의 네트워크에만 연결되지만, 마이그레이션 중에는 Cilium 및 기존 CNI에 구성된 파드 모두와 통신이 가능합니다. Cilium과 기존 CNI가 서로 다른 IP 대역을 사용하면, 리눅스 라우팅 테이블이 트래픽을 자동으로 분리해줍니다.

 

하지만 주의할 점이 있습니다. Cilium을 설치할 때는 기존 CNI와 다른 CIDR 범위 및 캡슐화 포트를 사용해야 합니다. 그리고 서로 다른 IP 대역을 사용해야 합니다. 그렇게 하면, 리눅스 라우팅 테이블이 트래픽을 올바르게 처리할 수 있습니다.

 

참고로 마이그레이션 중에는 Cilium의 NetworkPolicy 및 CiliumNetworkPolicy 적용이 비활성화됩니다.

 

 

cilium으로 이전 준비

이전 글에서 생성한 클러스터를 이어서 사용하겠습니다. 

이전 하기 전 가이드에 나와있는 것처럼 goldpinger를 통해 통신에 이상이 없는지도 확인해보겠습니다.

helm repo add goldpinger https://bloomberg.github.io/goldpinger
helm repo update
kubectl create ns observability
helm install goldpinger -n observability goldpinger/goldpinger

 

기존에 사용하던 파드 대역이 10.244.0.0/16이기 때문에 새로운 cni의 파드 대역은 10.245.0.0/16으로 설정하겠습니다.

flannel도 vxlan으로 구성되어있기 때문에 geneve로 변경하거나 다른 vxlan 포트를 사용해야하는데 기본 vxlan 포트는 4789이기 때문에 다른 포트인 8473을 사용해보겠습니다. 

 

cat <<EOF > values-migration.yaml
operator:
  unmanagedPodWatcher:
    restart: false
routingMode: tunnel
tunnelProtocol: vxlan
tunnelPort: 8473
cni:
  customConf: true
  uninstall: false
ipam:
  mode: "cluster-pool"
  operator:
    clusterPoolIPv4PodCIDRList: ["10.245.0.0/16"]
policyEnforcementMode: "never"
bpf:
  hostLegacyRouting: true
EOF

 

Cilium을 Helm으로 설치할 때는 다양한 설정값(Helm values)을 지정해줘야 합니다. 하지만 처음부터 모든 값을 수동으로 구성하기는 쉽지 않기 때문에, Cilium은 클러스터 환경을 기반으로 필요한 설정값을 자동 감지할 수 있는 기능을 제공합니다. cilium 명령어를 설치해봅시다. 

brew install cilium-cli

 

정상 값인지 확인해봅니다. 

 

cilium install --version 1.17.6 --values values-migration.yaml \
  --dry-run-helm-values > values-initial.yaml
cat values-initial.yaml

 

이제 정말 설치해보겠습니다.

helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --namespace kube-system --values values-initial.yaml

 

이제 상태를 확인해보겠습니다

cilium status --wait

 

9개의 파드가 있고 cilium에 의해 관리되는 파드는 없는것을 확인할 수 있습니다. 

 

 

이제 cilium node를 설정합니다. 아래의 설정을 적용한다고 바뀌는 노드는 없지만 마이그레이션 작업을 진행하면서 점차 적용될 예정입니다. 

cat <<EOF | kubectl apply --server-side -f -
apiVersion: cilium.io/v2
kind: CiliumNodeConfig
metadata:
  namespace: kube-system
  name: cilium-default
spec:
  nodeSelector:
    matchLabels:
      io.cilium.migration/cilium-default: "true"
  defaults:
    write-cni-conf-when-ready: /host/etc/cni/net.d/05-cilium.conflist
    custom-cni-conf: "false"
    cni-chaining-mode: "none"
    cni-exclusive: "true"
EOF

 

 

cilium으로 이전하기 

먼저 마이그레이션을 진행할 노드를 선택합니다.  처음 진행할 노드로 컨트롤 플레인은 부적합합니다. 워커노드 중에서 하나 고릅시다. 

선택한 노드에 cordon을 걸고 drain 하겠습니다.

kubectl cordon $NODE
kubectl drain --ignore-daemonsets $NODE

 

그리고 위에서 설정했던 cilium node 설정이 적용되도록 이 노드에 라벨을 붙이겠습니다.

kubectl label node $NODE --overwrite "io.cilium.migration/cilium-default=true"

 

이제 cilium을 재시작 시킵니다.

kubectl -n kube-system delete pod --field-selector spec.nodeName=$NODE -l k8s-app=cilium
kubectl -n kube-system rollout status ds/cilium -w

 

그리고 노드를 재시작 시킵니다.

 

이제 정상적으로 마이그레이션이 되었는지 확인하겠습니다. 

cilium status --wait
kubectl get -o wide node $NODE
kubectl -n kube-system run --attach --rm --restart=Never verify-network \
  --overrides='{"spec": {"nodeName": "'$NODE'", "tolerations": [{"operator": "Exists"}]}}' \
  --image ghcr.io/nicolaka/netshoot:v0.8 -- /bin/bash -c 'ip -br addr && curl -s -k https://$KUBERNETES_SERVICE_HOST/healthz && echo'

 

 

이상이 없다면 cordon을 해제하고 남은 노드들도 동일하게 진행해봅니다. 

 

완료되면 모든 파드들이 cilium에 의해 관리되게 됩니다. 

 

마이그레이션 마무리하기 

이제 마무리를 진행하기위해 다음과 같이 설정을 변경하겠습니다.

  • Cilium이 기본 CNI로 동작해야 합니다.
  • NetworkPolicy 적용을 활성화해야 합니다.
  • Operator가 Cilium이 관리하지 않는 파드도 재시작할 수 있도록 설정합니다.

 

위의 조건을 적용하기 위한 설정이 helm values에 잘 들어가도록 cilium 명령어를 사용하여 파일을 생성합니다.

cilium install --version 1.17.6 --values values-initial.yaml --dry-run-helm-values \
  --set operator.unmanagedPodWatcher.restart=true \
  --set cni.customConf=false \
  --set policyEnforcementMode=default \
  --set bpf.hostLegacyRouting=false > values-final.yaml

 

이제 이 설정을 cilium에 적용해보겠습니다. 

helm upgrade --namespace kube-system cilium cilium/cilium --values values-final.yaml
kubectl -n kube-system rollout restart daemonset cilium
cilium status --wait

 

마지막으로 마이그레이션에 사용한 cilium node는 삭제해줍니다. 

kubectl delete -n kube-system ciliumnodeconfig cilium-default

 

 

추가로 flannel 파드도 삭제하고

kubectl delete ns kube-flannel

 

노드에 붙였던 라벨도 제거합니다.

kubectl label node $NODE --overwrite "io.cilium.migration/cilium-default-"

 

문제 발생 - 노드 not ready

cilium의 상태는 정상이라고 하는데 2개의 노드가 계속 not ready로 변경된다.. 원인 파악 후 다시 작성 예정.. 

containerd 재시작 하니 정상화되긴했다..