Kubespray と Terraform でクラスターを構築する
1.35.8 から 1.36.4 へ — 同じノード、新しいバージョン
한국어 원문으로 표시합니다.
목표
kubespray v2.32.0 으로 쿠버네티스 1.35.8 클러스터를 세우고 워크로드를 올려 둔 뒤, 인벤토리의 판을 1.36.4 로 바꾸고
upgrade-cluster.yml 로 한 칸 올립니다. 올리기 전후를 사진으로 남겨 무엇이 바뀌고 무엇이 그대로인지 증거로 말합니다.
왜 중요한가
쿠버네티스는 대략 넉 달마다 마이너 판이 나오고, 지원 기간이 지나면 보안 패치가 끊깁니다. 그래서 업그레이드는 한 번 하는 일이 아니라 정기 작업입니다. kubespray 는 업그레이드를 설치와 같은 선언으로 다룹니다 — 인벤토리의 판을 바꾸고 플레이북을 돌립니다. 대신 순서가 있습니다. 마이너를 건너뛰지 않고, kubespray 태그를 건너뛰지 않고, 노드마다 cordon → drain → 올리기 → uncordon 을 합니다. 노드가 한 대면 드레인 동안 워크로드가 멈춘다는 것도 이 실습에서 직접 봅니다. 설치와 업그레이드를 합쳐 약 13분을 기다립니다. 여유가 모자라면 세션을 연장하세요.
단계
/opt/ks/kubespray에서ansible-playbook -i /root/ks/inventory/lab/inventory.ini cluster.yml을 돌려 출력 전체를/root/ks/logs/cluster-1.log에 남기세요(약 7분). 인벤토리의 kube_version 은 1.35.8 입니다. 끝나면 API 서버 판이 v1.35.8 이어야 합니다.- default 네임스페이스에 Deployment
web(이미지registry.k8s.io/e2e-test-images/agnhost:2.59, 인자netexec --http-port=8080, 레플리카 2)을 만들어 두 파드가 Ready 가 되게 하세요. 그다음/root/ks/upgrade/before.json에server_version,kubelet_version,etcd_version(etcd --version의 판),coredns_image(coredns Deployment 의 이미지),node_uid,web_pod_uids(web 파드 UID 정렬 배열)를 적으세요. /root/ks/inventory/lab/group_vars/k8s_cluster/k8s-cluster.yml의kube_version을 1.36.4 로 바꾸세요.-e로 넘기지 말고 파일을 고칩니다.ansible-inventory --host node1이 1.36.4 를 돌려줘야 합니다./opt/ks/kubespray에서ansible-playbook -i /root/ks/inventory/lab/inventory.ini upgrade-cluster.yml을 돌려 출력 전체를/root/ks/logs/upgrade.log에 남기세요(약 6분). PLAY RECAP 이failed=0이고, API 서버·kubelet 이 모두 v1.36.4,/etc/kubernetes/kubeadm-config.yaml의 kubernetesVersion 도 v1.36.4 여야 합니다.- 2단계와 같은 필드로
/root/ks/upgrade/after.json을 적으세요. 그리고/root/ks/upgrade/diff.json에same_node(노드 UID 가 그대로인가),web_pods_recreated(web 파드 UID 가 모두 바뀌었는가),etcd_changed(etcd 판이 바뀌었는가),coredns_changed(coredns 이미지가 바뀌었는가)를 불리언으로 적으세요. /root/ks/logs/upgrade.log에서 upgrade/pre-upgrade·post-upgrade 역할의 작업을 찾아/root/ks/upgrade/drain.json에cordon_changed,drain_changed,uncordon_changed(각각 "Cordon node"·"Drain node"·"Uncordon node" 작업이 changed 를 냈는가, 불리언),drain_sec("Drain node" 작업이 걸린 초, TASKS RECAP 의 값을 반올림한 정수, 목록에 없으면 0),node_schedulable_now(지금 노드의 spec.unschedulable 이 참이 아닌가, 불리언)를 적으세요./root/ks/upgrade/next.json에running(지금 API 서버 판),max_supported(이 kubespray 판이 설치할 수 있는 가장 높은 쿠버네티스 판, 체크섬 목록의 첫 키),needs_new_kubespray(다음 마이너로 올리려면 kubespray 를 다음 태그로 먼저 올려야 하는가, 불리언)를 적으세요.
참고
- kubespray v2.32.0 이
/opt/ks/kubespray에, 인벤토리가/root/ks/inventory/lab/inventory.ini(kube_version 1.35.8)에 준비돼 있습니다. - 흔한 실수:
-e kube_version=1.36.4로만 올리고 인벤토리를 그대로 두는 것. 다음 사람이 옛 판이 적힌 인벤토리로 cluster.yml 을 돌리게 됩니다. - 흔한 실수: 업그레이드가 도중에 실패한 뒤 노드가 cordon 된 채 남은 것을 모르는 것.
kubectl get node의 SchedulingDisabled 를 확인하세요. - 문서: Kubespray — Upgrading Kubernetes · Kubernetes — Version Skew Policy · Kubernetes — Upgrading kubeadm clusters
한 칸 아래(1.35.8)로 세운다
/opt/ks/kubespray 에서 ansible-playbook -i /root/ks/inventory/lab/inventory.ini cluster.yml 을 돌려 출력 전체를 /root/ks/logs/cluster-1.log 에 남기세요(약 7분). 인벤토리의 kube_version 은 1.35.8 입니다. 끝나면 API 서버 판이 v1.35.8 이어야 합니다.
업그레이드를 연습하려면 한 칸 아래 판이 먼저 있어야 합니다. 이 kubespray 판의 기본값은 1.36.4 이라, 인벤토리에 1.35.8 을 적어 두지 않으면 처음부터 1.36.4 이 설치됩니다.
올리기 전의 사진
default 네임스페이스에 Deployment web(이미지 registry.k8s.io/e2e-test-images/agnhost:2.59, 인자 netexec --http-port=8080, 레플리카 2)을 만들어 두 파드가 Ready 가 되게 하세요. 그다음 /root/ks/upgrade/before.json 에 server_version, kubelet_version, etcd_version(etcd --version 의 판), coredns_image(coredns Deployment 의 이미지), node_uid, web_pod_uids(web 파드 UID 정렬 배열)를 적으세요.
업그레이드 뒤에 무엇이 바뀌었고 무엇이 그대로인지 말하려면 올리기 전 값을 먼저 남겨야 합니다. etcd 는 파드가 아니라 호스트 서비스라 kubectl 이 아니라 바이너리로 판을 묻습니다. 채점기는 이 기록이 업그레이드보다 먼저 쓰였는지를 판 번호로 대조합니다.
판은 인벤토리에서 올린다
/root/ks/inventory/lab/group_vars/k8s_cluster/k8s-cluster.yml 의 kube_version 을 1.36.4 로 바꾸세요. -e 로 넘기지 말고 파일을 고칩니다. ansible-inventory --host node1 이 1.36.4 를 돌려줘야 합니다.
kubespray 업그레이드 문서는 인벤토리에 판을 적어 두었다면 upgrade-cluster.yml 을 돌리기 전에 그 값을 고치라고 합니다. -e 로만 올리면 인벤토리에는 옛 판이 남고, 다음에 누군가 그 인벤토리로 cluster.yml 을 돌리면 클러스터와 인벤토리가 어긋난 상태에서 시작합니다.
upgrade-cluster.yml
/opt/ks/kubespray 에서 ansible-playbook -i /root/ks/inventory/lab/inventory.ini upgrade-cluster.yml 을 돌려 출력 전체를 /root/ks/logs/upgrade.log 에 남기세요(약 6분). PLAY RECAP 이 failed=0 이고, API 서버·kubelet 이 모두 v1.36.4, /etc/kubernetes/kubeadm-config.yaml 의 kubernetesVersion 도 v1.36.4 여야 합니다.
upgrade-cluster.yml 은 이미 있는 클러스터에만 쓰는 플레이북이고, 노드마다 cordon → drain → 올리기 → uncordon 을 합니다. 노드가 한 대면 드레인하는 동안 파드가 갈 곳이 없어 잠시 Pending 이 됩니다 — 한 대짜리 클러스터의 업그레이드는 곧 중단 시간이라는 뜻입니다. 기다리는 동안 로그의 PLAY 머리들을 따라가 보세요.
올린 뒤의 사진
2단계와 같은 필드로 /root/ks/upgrade/after.json 을 적으세요. 그리고 /root/ks/upgrade/diff.json 에 same_node(노드 UID 가 그대로인가), web_pods_recreated(web 파드 UID 가 모두 바뀌었는가), etcd_changed(etcd 판이 바뀌었는가), coredns_changed(coredns 이미지가 바뀌었는가)를 불리언으로 적으세요.
쿠버네티스를 한 칸 올린다고 모든 구성요소가 따라 오르지는 않습니다. kubespray 는 etcd·CoreDNS 판을 쿠버네티스 마이너 판별 표(etcd_supported_versions, coredns_supported_versions)로 고릅니다. 두 판이 표에서 같은 값을 가리키면 그대로 남습니다.
로그로 읽는 드레인
/root/ks/logs/upgrade.log 에서 upgrade/pre-upgrade·post-upgrade 역할의 작업을 찾아 /root/ks/upgrade/drain.json 에 cordon_changed, drain_changed, uncordon_changed(각각 "Cordon node"·"Drain node"·"Uncordon node" 작업이 changed 를 냈는가, 불리언), drain_sec("Drain node" 작업이 걸린 초, TASKS RECAP 의 값을 반올림한 정수, 목록에 없으면 0), node_schedulable_now(지금 노드의 spec.unschedulable 이 참이 아닌가, 불리언)를 적으세요.
profile_tasks 의 TASKS RECAP 목록에는 오래 걸린 작업만 나옵니다. 드레인이 목록에 없다면 빨리 끝났다는 뜻입니다. 업그레이드가 도중에 실패하면 노드가 cordon 된 채 남을 수 있어서, 끝난 뒤 unschedulable 을 확인하는 습관이 필요합니다.
다음 칸은 어디서 오나
/root/ks/upgrade/next.json 에 running(지금 API 서버 판), max_supported(이 kubespray 판이 설치할 수 있는 가장 높은 쿠버네티스 판, 체크섬 목록의 첫 키), needs_new_kubespray(다음 마이너로 올리려면 kubespray 를 다음 태그로 먼저 올려야 하는가, 불리언)를 적으세요.
kubespray 는 태그마다 받아 줄 판을 체크섬으로 고정합니다. 지금 판이 목록의 맨 위라면 이 kubespray 로는 더 올라갈 수 없고, 문서의 '여러 번 업그레이드' 절대로 kubespray 태그를 한 칸씩 올린 뒤 upgrade-cluster.yml 을 돌려야 합니다. 태그를 건너뛰는 것은 지원하지 않습니다.