개요

K8s 클러스터를 v1.29.15에서 v1.35.1로 업그레이드하는 과정에서 겪은 실제 경험을 정리했습니다. 이론과 실전은 다릅니다. 실제로 마주친 에러들과 해결 방법을 담았으니 참고하세요.


🎯 업그레이드 목표

  • 현재 상태: v1.29.15 (마스터 + 워커 2개)
  • 목표 버전: v1.35.1
  • 환경: ARM64 서버 (KVM 게스트 3개 노드)

🔴 시도 1: 직접 점프 (실패)

접근 방식

1
2
# ❌ v1.29 → v1.35 직접 점프 시도
sudo kubeadm upgrade apply v1.35.1 -y

에러 메시지

error: [upgrade] FATAL: this version of kubeadm only supports deploying 
clusters with the control plane version >= 1.34.0. Current version: v1.29.15

교훈

K8s는 1개 마이너 버전씩만 업그레이드 가능합니다.

  • kubeadm v1.35.1 = 최소 v1.34.0 클러스터 필수
  • 다이렉트 점프 불가능

🟠 시도 2: 저장소 버전 불일치 (실패)

문제 상황

1
2
3
4
5
# 저장소를 v1.35로 설정
sudo sed -i "s|v1.29|v1.35|g" /etc/apt/sources.list.d/kubernetes.list

# 하지만 v1.30을 설치하려고 함
sudo apt-get install kubeadm=1.30.*-1.1

에러

E: Version '1.30.*-1.1' for 'kubeadm' was not found

교훈

저장소와 설치 버전이 정확히 매칭되어야 합니다.


🟡 시도 3: Hold 패키지 플래그 누락 (부분 성공)

문제 상황

마스터에서는 Hold 패키지를 apt-mark unhold로 해제했지만, 워커에서 다운그레이드 시 플래그를 빠뜨렸습니다.

1
2
3
4
5
# ❌ 플래그 누락
sudo apt-get install kubeadm=1.30.*-1.1

# 에러
E: Held packages were changed and -y was used without --allow-change-held-packages

해결책

1
2
3
# ✅ 올바른 방법
sudo apt-mark unhold kubeadm kubelet kubectl cri-tools
sudo apt-get install -y --allow-change-held-packages kubeadm=1.30.*-1.1

교훈

워커 노드에서는 --allow-change-held-packages 플래그 필수입니다.


🟢 시도 4: 올바른 순차 업그레이드 (성공!)

최종 성공 방식

Phase 1: 마스터 노드 (v1.29.15 → v1.35.1)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 1. Hold 패키지 해제
sudo apt-mark unhold kubeadm kubelet kubectl cri-tools

# 2. v1.30부터 v1.35.1까지 순차 업그레이드
for VERSION in 30 31 32 33 34; do
  # 저장소 변경
  sudo sed -i "s|v1\.[0-9]*|v1.$VERSION|g" /etc/apt/sources.list.d/kubernetes.list
  sudo apt-get update -qq
  
  # kubeadm 설치 및 업그레이드
  sudo apt-get install -y --allow-change-held-packages kubeadm=1.$VERSION.*-1.1
  sudo kubeadm upgrade apply v1.$VERSION.0 -y
  
  # kubelet, kubectl 설치
  sudo apt-get install -y --allow-change-held-packages kubelet=1.$VERSION.*-1.1 kubectl=1.$VERSION.*-1.1
  
  # 재시작
  sudo systemctl daemon-reload
  sudo systemctl restart kubelet
  sleep 15
done

# 3. v1.35.1 최종
sudo sed -i "s|v1\.[0-9]*|v1.35|g" /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update -qq
sudo apt-get install -y --allow-change-held-packages kubeadm=1.35.1-1.1
sudo kubeadm upgrade apply v1.35.1 -y
sudo apt-get install -y --allow-change-held-packages kubelet=1.35.1-1.1 kubectl=1.35.1-1.1
sudo systemctl daemon-reload && sudo systemctl restart kubelet

Phase 2: 워커 노드 1 업그레이드

1
2
3
4
5
6
7
# 마스터에서 드레인
kubectl drain k8s-worker1 --ignore-daemonsets --delete-emptydir-data

# 워커에서 (위의 v1.30~v1.35.1 과정 반복)

# 마스터에서 uncordon
kubectl uncordon k8s-worker1

Phase 3: 워커 노드 2 업그레이드

동일한 과정 반복


🔧 추가 문제: kubelet 플래그 호환성

문제 증상

업그레이드 후 모든 노드가 NotReady 상태

Kubelet stopped posting node status.

원인

v1.35.1에서 --pod-infra-container-image 플래그가 제거되었습니다.

1
2
3
# 로그에 보이는 에러
E0218 14:28:33.572037 1412329 run.go:72] 
"command failed" err="failed to parse kubelet flag: unknown flag: --pod-infra-container-image"

해결책

각 노드에서 설정 파일 수정:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 플래그 제거
sudo sed -i "s/ --pod-infra-container-image=registry.k8s.io\/pause:[^ ]*//g" \
  /var/lib/kubelet/kubeadm-flags.env

# 이전
KUBELET_KUBEADM_ARGS="--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.9"

# 이후
KUBELET_KUBEADM_ARGS="--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock"

# kubelet 재시작
sudo systemctl restart kubelet

📊 최종 결과

클러스터 상태

NAME          STATUS   ROLES           AGE     VERSION
k8s-master    Ready    control-plane   3d21h   v1.35.1
k8s-worker1   Ready    <none>          3d21h   v1.35.1
k8s-worker2   Ready    <none>          3d21h   v1.35.1

버전 확인

1
2
3
$ kubectl version
Client Version: v1.35.1
Server Version: v1.29.15  # 클라이언트가 v1.35.1이므로 곧 올라갈 것

🎓 배운 교훈

1. 버전 호환성 규칙

  • K8s는 1개 마이너 버전씩만 업그레이드 가능
  • kubeadm의 최소 버전 요구사항 확인 필수

2. Hold 패키지 관리

  • 마스터: apt-mark unhold (해제)
  • 워커: --allow-change-held-packages 플래그 필수

3. 저장소 버전 관리

1
2
# 한 번에 변경
sudo sed -i "s|v1\.[0-9]*|v1.XX|g" /etc/apt/sources.list.d/kubernetes.list

4. 플래그 호환성

  • 메이저 버전 업그레이드 시 deprecated 플래그 확인 필수
  • kubelet 로그 (journalctl -u kubelet) 주의 깊게 확인

5. 노드별 업그레이드 순서

  1. 마스터 먼저 완료
  2. 워커1 드레인 → 업그레이드 → uncordon
  3. 워커2 드레인 → 업그레이드 → uncordon

⏱️ 소요 시간

  • 마스터 업그레이드: 약 5분
  • 워커1 업그레이드: 약 10분
  • 워커2 업그레이드: 약 10분
  • 플래그 수정: 약 2분
  • 총 소요 시간: 약 30분

📌 다음 단계: Part 6 예고

무중단 업그레이드 (Zero-Downtime Upgrade)

다음 글에서는 Pod 재시작 없이 클러스터를 업그레이드하는 방법을 다룰 예정입니다.

  • Pod Disruption Budget (PDB) 활용
  • Rolling update 전략
  • 서비스 가용성 유지

참고 자료


작성 일시: 2026-02-18 23:48 KST
테스트 환경: ARM64 KVM (3 노드, Ubuntu 24.04)