본문 바로가기
문서 목차
ORKESTRIX설치

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"

목표 버전 사전 점검 (버전을 바꿀 때마다 필수)

아래 두 가지는 목표 마이너 버전이 바뀔 때마다 사람이 직접 확인해야 하는 항목입니다. 확인하지 않고 진행하면 업그레이드 도중 실패합니다.

  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 자체 업그레이드는 별도 절차), 직전 버전과 같은 값을 그대로 넣어 우선 통과시킵니다.

  2. 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.j2
      
      복사한 뒤에는 두 파일을 diff로 비교해서 실제로 설정 스키마 차이가 없는 버전 조합이었는지 재확인합니다(예: 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

다음 단계