하나의 IP 풀에서 다른 IP 풀로 마이그레이션하기
실행 중인 클러스터에서 기존 파드 연결을 끊지 않고 한 Calico Open Source IPPool에서 다른 IPPool로 워크로드를 마이그레이션하는 방법을 안내해요.
출처: 문서
본문
큰 그림
네트워크 중단 없이 실행 중인 클러스터에서 파드를 한 IP 풀에서 다른 IP 풀로 마이그레이션해요.
가치
파드는 Calico에서 구성한 IP 풀에서 IP 주소를 할당받아요. 파드 수가 늘어나면 파드가 사용할 수 있는 주소 수를 늘려야 할 수 있어요. 또는 실수로 사용한 CIDR에서 파드를 옮겨야 할 수도 있고요. Calico는 네트워크 중단 없이 실행 중인 클러스터에서 한 IP 풀에서 다른 IP 풀로 마이그레이션할 수 있게 해줘요.
개념
IP 풀과 클러스터 CIDR
Calico는 클러스터 내에서 여러 개의 서로 겹치지 않는(disjoint) IP 풀 CIDR을 지원해요. 하지만 Kubernetes는 모든 파드가 같은 클러스터 CIDR 안의 주소를 갖는다고 기대해요. 즉 기술적으로는 클러스터 CIDR 밖에 IP 풀을 만드는 것이 가능하더라도 권하지 않아요. Kubernetes 클러스터 CIDR 밖의 주소를 할당받은 파드는 네트워크 연결을 잃어요.
시작하기 전에...
Calico IPAM을 사용 중인지 확인하세요.
어떤 IPAM을 사용하는지 확실하지 않다면 확인 방법은 설치 방식에 따라 달라요.
Tab: Operator
기본 Installation 리소스에서 IPAM 플러그인을 조회할 수 있어요.
kubectl get installation default -o go-template --template {{.spec.cni.ipam.type}}
클러스터가 Calico IPAM을 사용한다면 위 명령은 Calico를 반환해요.
Tab: Manifest
Kubernetes 노드 중 하나에 SSH로 접속해 CNI 구성을 살펴봐요.
cat /etc/cni/net.d/10-calico.conflist
다음 항목을 찾아요:
"ipam": {
"type": "calico-ipam"
},
이 항목이 있으면 Calico IPAM을 사용 중이에요. IPAM이 Calico가 아니거나 10-calico.conflist 파일이 없다면 클러스터에서 이 기능을 사용할 수 없어요.
오케스트레이터가 pod network CIDR 변경을 지원하는지 확인하세요.
Kubernetes는 pod network CIDR 변경을 지원하지만 모든 오케스트레이터가 그런 것은 아니에요. 오케스트레이터 문서를 확인해 검증하세요.
방법
하나의 IP 풀에서 다른 IP 풀로 마이그레이션하기
다음 단계를 따라 파드를 한 IP 풀에서 다른 풀로 마이그레이션해요.
SECONDARY: 이 단계를 따르면 기존 파드 연결은 영향을 받지 않아요. (새 풀을 만들고 검증하기 전에 기존 IP 풀을 삭제하면 기존 파드가 영향을 받아요.) 파드가 삭제되면 애플리케이션 종류에 따라 일시적으로 사용할 수 없게 될 수 있으니 미리 계획하세요.
-
새 IP 풀을 추가해요.
SECONDARY: Calico IP 풀은 Kubernetes 클러스터 CIDR 안에 두는 것을 강력히 권장해요. 파드 IP가 Kubernetes 클러스터 CIDR 밖에서 할당되면 일부 트래픽 흐름에 불필요한 NAT가 적용되어 예상치 못한 동작이 발생할 수 있어요.
kube-proxy에 클러스터 CIDR을 구성했다면 원치 않는 NAT를 막기 위해 새 IP 풀 CIDR이 그 안에 포함되도록 확인해야 해요.
-
기존 IP 풀을 비활성화해요.
SECONDARY: IP 풀을 비활성화하면 새 IP 주소 할당만 막을 뿐, 기존 파드의 네트워킹에는 영향을 주지 않아요.
-
기존 IP 풀의 파드를 삭제해요. 여기에는 풀을 비활성화하기 전에 기존 IP 풀로 만들어졌을 수 있는 새 파드도 포함돼요.
-
새 파드가 새 IP 풀에서 주소를 받는지 확인해요.
-
기존 IP 풀을 삭제해요.
튜토리얼
다음 예시에서는 kubeadm으로 Kubernetes 클러스터를 만들었어요. 하지만 구성한 IP 풀 CIDR(192.168.0.0/16)이 Kubernetes 클러스터 CIDR과 일치하지 않아요. 이 예시에서는 클러스터 CIDR에 속하는 10.0.0.0/16으로 바꿔 볼게요.
Tab: Operator
kubectl get ippools를 실행해 IP 풀 default-ipv4-ippool을 확인해요.
NAME CREATED AT
default-ipv4-ippool 2024-03-28T16:14:28Z
1단계: 새 IP 풀 추가하기
CIDR 범위 10.0.0.0/16을 갖는 새 IPPool 리소스를 추가해요.
default installation에 기존 IP 풀 아래에 다음을 추가해요.
kubectl edit installation default
- name: new-ipv4-pool
cidr: 10.0.0.0/16
encapsulation: IPIP
새 IP 풀을 확인해요.
kubectl get ippools
NAME CREATED AT
default-ipv4-ippool 2024-03-28T16:14:28Z
test-pool 2024-03-28T18:30:15Z
2단계: 기존 IP 풀 비활성화하기
default installation을 편집해 default-ipv4-ippool이 어떤 노드도 선택하지 않도록 수정해요. 이렇게 하면 풀에서 IP 할당이 막혀요.
kubectl edit installation default
- name: 192.168.0.0-16
allowedUses:
- Workload
- Tunnel
blockSize: 26
cidr: 192.168.0.0/16
disableBGPExport: false
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
- nodeSelector: all()
+ nodeSelector: "!all()"
변경 사항을 적용해요.
기억하세요: 풀을 비활성화하면 새 IP 할당에만 영향을 주고 기존 파드의 네트워킹은 영향을 받지 않아요.
3단계: 기존 IP 풀의 파드 삭제하기
다음으로 기존 IP 풀의 기존 파드를 모두 삭제해요. (이 예시에서는 coredns가 유일한 파드예요. 파드가 여러 개라면 클러스터의 모든 파드에 삭제를 트리거하면 돼요.)
kubectl delete pod -n kube-system coredns-6f4fd4bdf-8q7zp
4단계: 새 파드가 새 IP 풀에서 주소를 받는지 확인하기
-
테스트 네임스페이스와 nginx 파드를 만들어요.
kubectl create ns ippool-test -
nginx 파드를 만들어요.
kubectl -n ippool-test create deployment nginx --image nginx -
새 파드가 새 범위에서 IP 주소를 받는지 확인해요.
kubectl -n ippool-test get pods -l app=nginx -o wide -
ippool-test네임스페이스를 정리해요.kubectl delete ns ippool-test
5단계: 기존 IP 풀 삭제하기
파드가 새 범위에서 IP를 받는 것을 확인했다면 기존 풀을 안전하게 삭제할 수 있어요. 이를 위해 default installation에서 기존 풀을 제거해 새로 만든 IP 풀만 남겨요.
Tab: Manifest
calicoctl get ippool -o wide를 실행해 IP 풀 default-ipv4-ippool을 확인해요.
NAME CIDR NAT IPIPMODE VXLANMODE DISABLED
default-ipv4-ippool 192.168.0.0/16 true Always Never false
calicoctl get wep --all-namespaces를 실행하면 기본 범위(192.168.52.130/32)를 사용하는 파드가 만들어진 것을 볼 수 있어요.
NAMESPACE WORKLOAD NODE NETWORKS INTERFACE
kube-system coredns-6f4fd4bdf-8q7zp vagrant 192.168.52.130/32 cali800a63073ed
이 파드를 새 IP 풀(10.0.0.0/16)로 바꾸는 작업을 시작해 볼게요.
1단계: 새 IP 풀 추가하기
CIDR 범위 10.0.0.0/16을 갖는 새 IPPool을 추가해요.
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: new-pool
spec:
cidr: 10.0.0.0/16
ipipMode: Always
natOutgoing: true
새 IP 풀을 확인해요.
calicoctl get ippool -o wide
NAME CIDR NAT IPIPMODE DISABLED
default-ipv4-ippool 192.168.0.0/16 true Always false
new-pool 10.0.0.0/16 true Always false
2단계: 기존 IP 풀 비활성화하기
기존 IP 풀 정의를 나열해요.
calicoctl get ippool -o yaml > pools.yaml
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 192.0.0.0/16
ipipMode: Always
natOutgoing: true
- apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: new-pool
spec:
cidr: 10.0.0.0/16
ipipMode: Always
natOutgoing: true
pools.yaml을 편집해요.
disabled: true로 설정해 이 IP 풀을 비활성화해요.
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 192.0.0.0/16
ipipMode: Always
natOutgoing: true
disabled: true
변경 사항을 적용해요.
기억하세요: 풀을 비활성화하면 새 IP 할당에만 영향을 주고 기존 파드의 네트워킹은 영향을 받지 않아요.
calicoctl apply -f pools.yaml
변경 사항을 확인해요.
calicoctl get ippool -o wide
NAME CIDR NAT IPIPMODE DISABLED
default-ipv4-ippool 192.168.0.0/16 true Always true
new-pool 10.0.0.0/16 true Always false
3단계: 기존 IP 풀의 파드 삭제하기
다음으로 기존 IP 풀의 기존 파드를 모두 삭제해요. (이 예시에서는 coredns가 유일한 파드예요. 파드가 여러 개라면 클러스터의 모든 파드에 삭제를 트리거하면 돼요.)
kubectl delete pod -n kube-system coredns-6f4fd4bdf-8q7zp
4단계: 새 파드가 새 IP 풀에서 주소를 받는지 확인하기
-
테스트 네임스페이스와 nginx 파드를 만들어요.
kubectl create ns ippool-test -
nginx 파드를 만들어요.
kubectl -n ippool-test create deployment nginx --image nginx -
새 파드가 새 범위에서 IP 주소를 받는지 확인해요.
kubectl -n ippool-test get pods -l app=nginx -o wide -
ippool-test네임스페이스를 정리해요.kubectl delete ns ippool-test
5단계: 기존 IP 풀 삭제하기
파드가 새 범위에서 IP를 받는 것을 확인했다면 기존 풀을 안전하게 삭제할 수 있어요.
calicoctl delete pool default-ipv4-ippool
추가 리소스
더 알아보기 (Learn more)
핵심 순서는 "새 풀 추가 → 기존 풀 비활성화 → 기존 풀 파드 삭제 → 새 풀 할당 확인 → 기존 풀 삭제"예요. 비활성화는 새 할당만 막고 기존 파드 네트워킹은 그대로 둔다는 점이 중단 없는 마이그레이션의 열쇠예요.