문서 목차
Kubernetes 클러스터 업그레이드
운영 중인 컨트롤플레인 및 워커 노드를 무중단으로 안전하게 업그레이드 합니다. 한 번에 한 노드씩 순서대로(마스터 → 워커) 처리하며, 각 노드가 정상 복귀한 뒤에만 다음 노드로 진행합니다.
QUANTUM C&S
운영 중인 컨트롤플레인 및 워커 노드를 무중단으로 안전하게 업그레이드합니다. 한 번에 한 노드씩 순서대로(마스터 → 워커) 처리하며, 각 노드가 정상 복귀한 뒤에만 다음 노드로 진행합니다.
사전 준비
업그레이드 전 반드시 전체 클러스터 백업을 생성합니다(Velero 문서 참고):
kubectl apply -f - <<EOF
apiVersion: velero.io/v1
kind: Backup
metadata:
name: pre-k8s-upgrade
namespace: velero
spec: {}
EOF
kubectl get backup pre-k8s-upgrade -n velero -o jsonpath='{.status.phase}'
Completed가 나온 뒤에 업그레이드를 진행합니다.
설정값
ubuntu.yaml:
kube_version: "1.37.1"
목표 버전 사전 점검 (버전을 바꿀 때마다 필수)
아래 두 가지는 목표 마이너 버전이 바뀔 때마다 사람이 직접 확인해야 하는 항목입니다. 확인하지 않고 진행하면 업그레이드 도중 실패합니다.
호환성 매트릭스 항목 존재 확인
inventory/qks/group_vars/all/compatible-matrix.yaml에서 아래 7개 매트릭스 전부에 목표 버전(kube_version의 major.minor, 예:1.38) 키가 있는지 확인합니다:grep -A2 "^containerd_matrix:\|^runc_matrix:\|^matrix_etcd:\|^matrix_pause:\|^matrix_coredns:\|^cni_cilium_matrix:\|^csi_ceph_matrix:" \ inventory/qks/group_vars/all/compatible-matrix.yaml | grep "'<목표버전>'"7줄이 다 나와야 정상입니다. 하나라도 안 나오면 그 매트릭스에 항목을 추가해야 합니다.
matrix_etcd/matrix_pause/matrix_coredns는 kubeadm이 그 버전에서 실제로 쓰는 값을 그대로 가져와야 하므로, kubeadm 공식 소스코드에서 확인합니다:curl -s https://raw.githubusercontent.com/kubernetes/kubernetes/v<목표버전>.0/cmd/kubeadm/app/constants/constants.go \ | grep -E "DefaultEtcdVersion|PauseVersion|CoreDNSVersion ="출력된 값을 그대로 매트릭스에 추가합니다(기존 줄 바로 아래):
# matrix_etcd '1.38': "<DefaultEtcdVersion 값>" # matrix_pause '1.38': "<PauseVersion 값>" # matrix_coredns '1.38': "<CoreDNSVersion 값>"containerd_matrix/runc_matrix는 아래 2번 항목의 결정에 따라 채웁니다.cni_cilium_matrix/csi_ceph_matrix는 이번 절차의 검증 범위 밖이므로(CNI/CSI 자체 업그레이드는 별도 절차), 직전 버전과 같은 값을 그대로 넣어 우선 통과시킵니다.containerd 버전에 맞는 설정 템플릿 존재 확인
먼저 containerd 공식 지원표(https://github.com/containerd/containerd/blob/main/RELEASES.md)에서 LTS로 표시된 버전을 목표로 고릅니다(최신 버전이 항상 지원 기간이 더 긴 것은 아니므로, 지원 종료일(End of Life)이 가장 늦은 걸 우선 선택합니다).
그 버전용 설정 템플릿이 이미 있는지 확인합니다:
ls roles/qks-kubernetes/cri/containerd/templates/containerd-config-<major>.<minor>.x.toml.j2- 있으면:
containerd_matrix에 그 버전을 그대로 추가하고 끝. - 없으면: 가장 가까운 하위 버전의 템플릿을 새 파일로 복사합니다(대부분의 point release는 설정 스키마가 동일합니다):
복사한 뒤에는 두 파일을cp roles/qks-kubernetes/cri/containerd/templates/containerd-config-<가장가까운하위버전>.x.toml.j2 \ roles/qks-kubernetes/cri/containerd/templates/containerd-config-<목표버전>.x.toml.j2diff로 비교해서 실제로 설정 스키마 차이가 없는 버전 조합이었는지 재확인합니다(예: containerd 2.2.x→2.3.x는 diff 결과가 완전히 동일했음). 차이가 있다면 containerd 공식 릴리즈 노트에서 해당 변경 사항을 반영해야 합니다. 그다음containerd_matrix(및 필요 시runc_matrix)에 선택한 버전을 추가합니다.
- 있으면:
실행
./install.sh ubuntu plays/qks-k8s-upgrade.yaml
업그레이드 흐름
./install.sh ubuntu plays/qks-k8s-upgrade.yaml
├─ 1. 대상 K8s 마이너 버전의 패키지 저장소 등록
├─ 2. (마스터부터 워커까지 한 노드씩 순서대로)
│ ├─ 노드 drain (PodDisruptionBudget 위반 시 자동 재시도, Knative PDB는 자동 완화 후 원복)
│ ├─ kubeadm/kubelet/kubectl 패키지 업그레이드
│ ├─ 컨트롤플레인 첫 노드: kubeadm upgrade apply / 나머지: kubeadm upgrade node
│ ├─ 노드 uncordon
│ ├─ 이 노드가 Ready로 복귀할 때까지 대기
│ └─ containerd 버전 확인 및 필요 시 재구성
└─ 3. (선택) CoreDNS 패치
설치 확인
kubectl get nodes -o wide
NAME STATUS ROLES VERSION CONTAINER-RUNTIME
k8s-ubuntu24-m01 Ready control-plane v1.37.1 containerd://2.3.0
k8s-ubuntu24-m02 Ready control-plane v1.37.1 containerd://2.3.0
k8s-ubuntu24-m03 Ready control-plane v1.37.1 containerd://2.3.0
k8s-ubuntu24-w01 Ready worker v1.37.1 containerd://2.3.0
k8s-ubuntu24-w02 Ready worker v1.37.1 containerd://2.3.0
k8s-ubuntu24-w03 Ready worker v1.37.1 containerd://2.3.0
전체 노드가 Ready이고, VERSION과 CONTAINER-RUNTIME이 목표 버전으로 표시되어야 합니다.
kubectl version
Client Version/Server Version 모두 목표 버전이어야 합니다.
실제 동작 확인
클러스터 전체 파드 헬스 확인:
kubectl get pods -A | grep -vE "Running|Completed"
아무 것도 출력되지 않으면(헤더 줄만 있으면) 정상입니다.
테스트 워크로드로 스케줄링 · 네트워킹 · 스토리지 동작 확인: 업그레이드된 노드가 새 파드를 실제로 정상 수용하는지, PVC 마운트가 정상인지 확인합니다.
kubectl create namespace gs-8-2-test
kubectl apply -n gs-8-2-test -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gs-8-2-test-pvc
spec:
accessModes: [ReadWriteOnce]
storageClassName: qks-ceph-block
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: gs-8-2-test-pod
spec:
containers:
- name: writer
image: busybox
command: ["sh", "-c", "echo ok > /data/hello.txt && sleep 3600"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: gs-8-2-test-pvc
EOF
kubectl wait pod/gs-8-2-test-pod -n gs-8-2-test --for=condition=Ready --timeout=60s
kubectl exec -n gs-8-2-test gs-8-2-test-pod -- cat /data/hello.txt
파드가 Running이 되고 파일 내용(ok)이 정상적으로 읽히면, 업그레이드된 클러스터에서 스케줄링 · 네트워킹 · 스토리지가 모두 정상 동작하는 것입니다. 확인 후 정리합니다:
kubectl delete namespace gs-8-2-test