Profile picture

[k8s] 쿠버네티스 클러스터 버전 업그레이드 방법 및 주의사항

JaehyoJJAng2025년 03월 20일

k8s 버전 정책 (Skew Policy)

쿠버네티스는 업스트림 마이너 버전을 평균 4개월에 한 번씩 Release 합니다.

그렇기에 새로운 마이너 버전이 Release 되는 시점이 바로 쿠버네티스 버전을 업그레이드하는 적절한 시기가 되는거죠.


Release 목록은 다음 링크에서 확인할 수 있습니다.
k8s.changelog


주의사항

쿠버네티스의 버전은 단계별로 진행해야해요!

  • 1. kubeadm 공식 문서에서 지원하는 "마이너 버전 업그레이드 경로"(v1.29 -> v1.30 등)를 확인하기!
  • 2. 메이저(1.x -> 2.x) 건너뛰기는 불가해요! 마이너 버전은 한 단계씩(v1.29 -> v1.30 -> v1.31 ...)만 가능하다는 걸 잊지마세요!

또한, 쿠버네티스 구성 요소 간에 지원되는 버전 차이는 다음과 같아요.
(버전 차이(Skew) 정책)


  • 구성 요소 중 kube-apiserver의 버전은 가장 최신 버전이어야 함.
  • controller-manager, kube-schedularkube-apiserver보다 한 버전 낮게 설정 가능
  • kubelet, kube-proxykube-apiserver보다 두 버전 낮게 설정 가능
  • kubectlkube-apiserver를 기준으로 한 버전 차이 내에서 지원함.

업그레이드 전 준비 사항

1. 현재 버전, 구성 확인하기

kubectl get nodes
# NAME       STATUS   ROLES    AGE   VERSION
# cp-node    Ready    control-plane  …  v1.29.11
# worker-1   Ready    <none>        …  v1.29.11
# worker-2   Ready    <none>        …  v1.29.11

kubeadm version
kubelet --version
kubectl version --client

2. 지원 가능한 업그레이드 경로 확인

  • kubeadm 공식 문서에서 지원하는 “마이너 버전 업그레이드 경로”(v1.29 → v1.30 등)를 확인
  • 메이저(1.x → 2.x) 건너뛰기는 불가, 마이너 버전은 한 단계씩(v1.29 → v1.30 → v1.31 …)만 가능

3. 백업

etcd 스냅샷 확보하기. (선택)

# control-plane 노드에서
ETCDCTL_API=3 etcdctl snapshot save ~/etcd-backup-$(date +%F).db \
  --endpoints=127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

애드온 매니페스트, Helm 릴리즈 값 덤프


4. 릴리즈 노트, Deprecated 체크

  • Cilium, nginx-ingress-controller, MetalLB 등 사용 중인 애드온의 새 버전 호환성 확인
  • Kubernetes API Deprecated 체크(kubectl deprecations 플러그인 등 활용)

버전 업그레이드

kubeadm으로 구성된 환경에서의 쿠버네티스 클러스터 버전을 업그레이드하는 순서입니다.

버전 업그레이드는 Control Plane -> Worker Node 순으로 작업을 진행할 예정입니다.

각 노드별로 업그레이드가 필요한 구성 요소는 다음과 같아요.

  • Control Plane: kube-apiserver, controller-manager, kube-schedular, kubelet, kube-proxy
  • Worker Node: kubelet, kube-proxy

저는 현재 v1.29.11 버전이기 때문에 v1.30으로 업그레이드를 해볼거에요!


Control Plane

Control Plane 업그레이드 작업 시, 주요 구성 요소의 일시적인 중단을 발생시켜요.

따라서 작업하는 동안 kubectl 명령 및 쿠버네티스 API 사용, 파드 생성/변경/삭제, 파드 생성 실패 시의 재생성 프로세스 등이 제한됩니다.


1. 쿠버네티스 패키지 레포지토리 변경하기 (관련 링크)


변경할 버전에 맞게 수정해주세요.

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 저장소 업데이트
sudo apt-get update -y

2. 버전 hold 해제 후 kubeadm 업그레이드

만약 kubeadm, kubelet, kubectlapt-mark hold가 걸려있지 않다면 해당 부분은 패스하고 업그레이드 부분만 참고해주세요.

sudo apt-mark unhold kubeadm && \
sudo apt-get update -y && sudo apt-get install -y kubeadm='1.30.x-*' && \
sudo apt-mark hold kubeadm
kubeadm version

kubeadm version: &version.Info{Major:"1", Minor:"30", GitVersion:"v1.30.11", GitCommit:"6a074997c960757de911780f250ecd9931917366", GitTreeState:"clean", BuildDate:"2025-03-11T19:56:25Z", GoVersion:"go1.23.6", Compiler:"gc", Platform:"linux/amd64"}

3. 업그레이드 플랜 확인

sudo kubeadm upgrade plan
# → 현재 Control Plane 버전, 가능한 Target 버전, etcd 버전 호환성 등 표시

4. Control Plane 업그레이드 실행

sudo kubeadm upgrade apply v1.30.x
  • 프롬프트에 따라 yes 입력
  • 성공 시 kube‑apiserver, kube‑controller‑manager, kube‑scheduler 매니페스트가 자동 업데이트

5. 버전 hold 해제 후 kubelet, kubectl 업그레이드

sudo apt-mark unhold kubelet kubectl && \
sudo apt-get update -y && sudo apt-get install -y kubelet='1.30.x-*' kubectl='1.30.x-*' && \
sudo apt-mark hold kubelet kubectl
# kubelet 재시작
sudo systemctl daemon-reload
sudo systemctl restart kubelet

6. Control Plane 상태 확인

kubectl get pods -n kube-system

# 모든 컨트롤 플레인 컴포넌트가 Ready 상태인지 확인
kubectl get cs

Worker Node

워커 노드는 한 번에 하나의 노드를 대상으로 업그레이드를 진행합니다.

그리고 목표한 버전에 도달할 때까지 마이너 업그레이드 작업을 노드마다 반복해 수행해야해요!


1. 노드 격리하기 (Control Plane에서 해당 명령어 실행)

kubectl cordon <worker-node>
kubectl drain <worker-node> --ignore-daemonsets --delete-local-data

2. 쿠버네티스 패키지 레포지토리 변경하기 (관련 링크)


변경할 버전에 맞게 수정해주세요.

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 저장소 업데이트
sudo apt-get update -y

3. 버전 hold 해제 후 kubeadm 업그레이드

만약 kubeadm, kubelet, kubectlapt-mark hold가 걸려있지 않다면 해당 부분은 패스하고 업그레이드 부분만 참고해주세요.

sudo apt-mark unhold kubeadm && \
sudo apt-get update -y && sudo apt-get install -y kubeadm='1.30.x-*' && \
sudo apt-mark hold kubeadm
kubeadm version

kubeadm version: &version.Info{Major:"1", Minor:"30", GitVersion:"v1.30.11", GitCommit:"6a074997c960757de911780f250ecd9931917366", GitTreeState:"clean", BuildDate:"2025-03-11T19:56:25Z", GoVersion:"go1.23.6", Compiler:"gc", Platform:"linux/amd64"}

4. kubelet config 업그레이드

sudo kubeadm upgrade node

5. 버전 hold 해제 후 kubelet, kubectl 업그레이드

sudo apt-mark unhold kubelet kubectl && \
sudo apt-get update -y && sudo apt-get install -y kubelet='1.30.x-*' kubectl='1.30.x-*' && \
sudo apt-mark hold kubelet kubectl

6. kubelet 재시작

sudo systemctl daemon-reload
sudo systemctl restart kubelet

7. 노드 격리 해제 (Control Plane에서 해당 명령어 실행)

kubectl uncordon <worker-node>

트러블슈팅

ERROR CreateJob

kubeadm upgrade plan 명령어 사용 시 cluster health check에서 실패하면서 중단되는 문제가 발생함.

[upgrade/health] FATAL: [preflight] Some fatal errors occurred:
    [ERROR CreateJob]: Job "upgrade-health-check-xxxxx" in the namespace "kube-system" did not complete in 15s: no condition of type Complete

이건 kubeadm이 클러스터 상태를 확인하기 위해 Job 리소스를 생성했지만, 그것이 15초 내에 성공적으로 완료되지 않아 실패로 간주했다는 로그임.


원인 분석 및 해결책

1. 노드 리소스 부족 OR Job 스케줄링 실패

  • Pod가 Pending 상태에 머물러 Job이 완료되지 못할 수 있음.

확인 방법

kubectl get jobs -n kube-system
kubectl describe job upgrade-health-check-xxxxx -n kube-system
kubectl get pods -n kube-system | grep upgrade-health-check
kubectl describe pod <해당-pod> -n kube-system

2. CNI 플러그인 문제로 인해 Pod 통신 불안정

  • health-check Job은 Pod간 통신이 가능한지를 체크하는데, CNI 문제로 실패할 가능성이 있음.

이 경우 다음 명령으로 CNI 상태 점검

kubectl get pods -n kube-system -o wide

CNI 관련 Pod(e.g., calico, flannel, cilium)가 CrashLoopBackOff나 Error 상태라면 먼저 해결해야 함.


3. Job 컨트롤러 문제

  • Job 자체가 작동을 못 하거나 API server가 문제가 있을 수도 있음.

kube-controller-manager, kube-scheduler, etcd 상태도 같이 확인

kubectl get pods -n kube-system

4. 임시 해결: preflight error 무시하고 강제 실행하기

개발/테스트 환경이라면 다음처럼 preflight error 에러를 무시해서 강제로 upgrade plan 하도록 하는 방법이 있음.

sudo kubeadm upgrade plan --ignore-preflight-errors=CreateJob

단, 실제 upgrade apply 단계에서도 같은 문제가 생길 수 있으므로 원인 파악하는 것이 더 안전함.


CNI 파드 동기화 실패

노드 버전 업그레이드 이후 CNI(cilium) 파드가 정상적으로 동기화되지 않는 문제가 발생함.(Pending 상태)


원인 분석 및 해결책

1. 정확한 원인 파악을 위해 다음 명령 실행

kubectl describe pod <cilium-operator-pod-name> -n kube-system
  • Events: 예: 0/2 nodes are available: 1 node(s) had taint {...}
  • NodeAffinity / Tolerations / Scheduling issues

2. 문제 1: 노드에 taint가 있어 스케줄이 안되는 경우

drain을 할 때 --delete-local-data--ignore-daemonsets 옵션 때문에 노드에 taint가 남는 경우가 있음.

kubectl describe node <worker-node>

이거에서 Taints: 항목이 NoSchedule 같은 걸로 돼 있으면, cilium-operator가 못 올라올 수 있다고 함.


kubectl taint nodes <worker-node> node-role.kubernetes.io/worker-

실제 taint key를 확인하고 맞게 제거해야 함.


3. 문제 2: Cilium 자체 충돌 또는 리소스 부족


Pending 상태지만 리소스가 부족해서 스케줄링이 안되는 경우도 있음.

kubectl get nodes -o wide
kubectl top node

해결: (강제 재배포하기)

kubectl rollout restart daemonset cilium -n kube-system
kubectl rollout restart deployment cilium-operator -n kube-system

또는 완전 삭제 후 재설치 (cilium CLI 필요 시)

cilium uninstall
cilium install

Loading script...