이 글은 “Kubernetes가 소프트웨어 릴리스를 어떻게 관리하는가”와 “클러스터 업그레이드는 어떤 순서와 전략으로 하는가”를 한 번에 정리합니다.
강의 스크립트의 흐름을 그대로 살리면서, 우리가 대화에서 다뤘던 cordon/drain의 정확한 의미, 5분 오해(자동 drain 아님), Unschedulable/NotReady와 트래픽 관계, standalone 파드가 drain에서 어떻게 되는지까지 함께 포함했습니다.
1) Kubernetes 버전 번호는 무엇을 의미하나?
클러스터를 설치하면 특정 Kubernetes 버전을 설치하게 됩니다. 보통 아래처럼 확인하곤 합니다.
kubectl get nodes
여기서 보이는 버전은 “클러스터 전체 버전”이라기보다, 각 노드에 설치된 kubelet 버전이 대표로 표시되는 것에 가깝습니다. (뒤에서 다시 설명)
Kubernetes 버전은 일반적으로 다음 형태입니다.
- Major.Minor.Patch
예:1.28.3- Major: 큰 변화(현재 Kubernetes는 오랫동안 Major=1)
- Minor: 몇 달마다 나오는 기능 릴리스
- Patch: 버그/보안 수정 위주의 잦은 릴리스
2) 알파/베타/정식(Stable) 릴리스 흐름
Kubernetes는 많은 OSS 프로젝트와 유사하게 다음 릴리스 단계를 거칩니다.
- Alpha
- 기능이 실험적이며 기본적으로 비활성화인 경우가 많음
- 버그/호환성 이슈 가능성 높음
- Beta
- 기능이 충분히 테스트되며 기본 활성화되는 경우가 많음
- Stable(정식)
- 운영 사용을 전제로 안정화
운영 업그레이드 관점에서는 “새 기능이 왜 필요한지”보다 릴리스 노트/호환성이 핵심입니다.
3) “Kubernetes 컴포넌트는 모두 같은 버전이어야 하나?”
아니요. Kubernetes는 버전 스큐(version skew) 를 허용합니다.
다만 규칙이 있습니다. 핵심만 정리하면:
3.1 kube-apiserver가 기준점
- kube-apiserver가 가장 중심
- 다른 컴포넌트는 kube-apiserver보다 높은 버전이면 안 된다(원칙)
3.2 control plane 컴포넌트 스큐
- kube-controller-manager / kube-scheduler는 보통 apiserver보다 같거나 1 minor 낮게까지 허용되는 방향으로 운영됩니다.
3.3 노드 컴포넌트 스큐
- kubelet / kube-proxy는 apiserver보다 최대 2 minor 낮게까지 허용되는 방향으로 설계되어, “라이브 업그레이드(rolling upgrade)”가 가능해집니다.
3.4 kubectl은?
kubectl은 apiserver보다 같거나 약간 앞/뒤 minor 범위에서 동작하도록 설계되어 있습니다.
운영에서는 보통 “apiserver와 동일 minor”로 맞추는 게 안전합니다.
요점: Kubernetes는 업그레이드를 한 번에 다 올리는 게 아니라, 순차적으로 올려도 동작하도록 일부러 스큐를 허용합니다.
4) Kubernetes는 최신 Minor 3개까지만 지원 (개념 정리)
강의에서 말한 것처럼, Kubernetes는 보통 최신 마이너 포함 3개 마이너 라인만 공식 지원 대상이 됩니다.
그래서 운영에서는 “너무 오래된 버전”에서 한 번에 점프하는 업그레이드는 권장되지 않습니다.
업그레이드 원칙
- 한 번에 Minor 하나씩 올리는 것이 권장
예:1.27 → 1.28 → 1.29 1.27 → 1.29같은 “2단 점프”는 리스크가 커지고, 도구/정책 상 제약이 생길 수 있습니다.
5) 업그레이드 방식은 “클러스터를 어떻게 만들었는지”에 따라 다르다
5.1 Managed Kubernetes (GKE/EKS/AKS 등)
- 콘솔/CLI에서 업그레이드가 비교적 간단
- 단, 노드그룹(노드풀) 업그레이드 전략/서지(surge)/드레인 동작은 서비스마다 다름
5.2 kubeadm 기반 클러스터
kubeadm upgrade plan/apply로 control plane 업그레이드 흐름이 명확- 워커 노드 업그레이드는 “노드별 드레인 + kubelet 업그레이드 + 언코든” 형태로 진행
5.3 완전 수동 설치(바이너리 배포 등)
- 각 컴포넌트를 직접 교체/재시작해야 해서 난이도가 가장 높음
이 글에서는 강의 흐름대로 kubeadm 기준 절차를 중심으로 정리합니다.
6) 업그레이드의 큰 그림: Control Plane 먼저, Worker는 그 다음
강의에서 강조한 구조는 운영에서도 동일합니다.
- Control Plane 업그레이드
- Worker Node 업그레이드
6.1 Control Plane 업그레이드 중에도 “앱 트래픽은 계속 가능”
Control plane(apiserver/scheduler/controller-manager)이 잠시 내려가도,
- 워커 노드 위 파드들은 계속 실행 중이라
- 사용자 트래픽(데이터 플레인)은 계속 처리될 수 있습니다.
하지만:
- kubectl로 클러스터 조작 불가
- 새 배포/삭제/수정 불가
- 컨트롤러 매니저가 멈추면 파드 장애 시 자동 복구/스케일링 등이 멈춤
즉, “서비스는 돌아갈 수 있지만 관리 기능은 멈춘다”입니다.
7) kubeadm 업그레이드 절차(개념 + 커맨드 흐름)
7.1 업그레이드 계획 확인
kubeadm upgrade plan
이 출력에서 보통 확인하는 것:
- 현재 클러스터 버전
- 업그레이드 가능한 타겟 버전
- 주요 컴포넌트 버전 상태
- 주의사항(특히 kubelet은 kubeadm이 자동 업그레이드하지 않는다는 메시지)
포인트:
kubeadm자체도 버전이 있어 먼저 올려야 하는 경우가 많습니다.
7.2 Control Plane 업그레이드 적용
(예시 형태)
kubeadm upgrade apply v1.28.0
이 단계에서 control plane static pod/manifest 등이 업데이트되고 필요한 이미지가 당겨집니다.
7.3 “kubectl get nodes에 버전이 그대로인데요?”
강의에서 나오는 핵심 포인트:
kubectl get nodes에 보이는 버전은 apiserver 버전이 아니라, 노드의 kubelet 버전이 대표로 보이는 경우가 많습니다.- 그래서 control plane만 올렸다고 해서
kubectl get nodes출력이 즉시 바뀌지 않을 수 있습니다. - 다음 단계가 kubelet 업그레이드입니다.
7.4 kubelet 업그레이드(노드별)
배포판/패키지 매니저에 따라 다르지만 흐름은:
- kubelet 패키지 업그레이드
- 필요 시
kubeadm upgrade node같은 노드 구성 업데이트 - kubelet 재시작
예시(개념):
# (예) 패키지 업데이트 후
sudo systemctl restart kubelet
8) 워커 노드 업그레이드 전략 3가지
전략 A: 전체 노드 동시 업그레이드 (다운타임 가능)
- 가장 빠르지만
- 파드가 대거 내려가서 서비스 중단 가능성이 큼
전략 B: 노드 1대씩 순차 업그레이드 (Rolling)
- 운영에서 가장 흔함
- 각 노드에서 파드를 비우고(drain) 업그레이드 → 복귀 → 다음 노드 진행
전략 C: 새 버전 노드를 추가하고 기존 노드를 제거(교체)
- 클라우드 환경에서 특히 현실적
- 새 노드풀(신버전) 증설 → 워크로드 이동 → 구노드풀 축소/폐기
- 다운타임 최소화에 유리
9) 워커 노드 롤링 업그레이드에서 drain이 왜 중요한가
강의에서도 “첫 번째 워커 노드 업그레이드 전에 워크로드를 다른 노드로 옮긴다”는 흐름이 나오는데, 여기서 핵심 도구가 kubectl drain입니다.
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
9.1 drain의 정확한 의미
- drain은 “이동”이 아니라 기존 파드를 종료(evict)시키고 다른 노드에서 재생성되게 하는 것
- 동시에 노드를 Unschedulable(=cordon) 로 만듭니다.
9.2 “standalone 파드(ReplicaSet 없는 파드)”가 있으면?
우리가 대화에서 정리한 결론 그대로입니다.
- standalone 파드는 drain으로 지우면 끝(다른 노드에 자동 재생성되지 않음)
- 그래서 기본
drain은 standalone이 있으면 실패/거부되는 형태가 흔함 - 강제로 하려면
--force가 필요한데, 그건 “서비스가 사라질 수 있음”을 의미합니다.
kubectl drain <node-name> --ignore-daemonsets --force --delete-emptydir-data
운영 팁: “노드 유지보수/업그레이드가 반복될 환경”이면, 중요 워크로드는 standalone이 아니라 Deployment/StatefulSet 등 컨트롤러로 반드시 감싸는 것이 기본 전제입니다.
9.3 drain 후 uncordon 해도 파드가 돌아오지 않는 이유
uncordon은 단지 “스케줄 가능”으로 되돌리는 것이지,
- 다른 노드에서 이미 떠 있는 파드가 자동으로 원래 노드로 복귀하지는 않습니다.
kubectl uncordon <node-name>
10) 우리가 대화에서 정리한 오해 2개: “5분”과 “트래픽”
10.1 “5분 지나면 자동 drain 되나요?”
아닙니다.
- 노드가 NotReady가 오래 지속되면 장애 복구 흐름(eviction/recreate) 이 동작할 수 있는데,
- 이것은 사용자가 수행하는
kubectl drain과 비슷해 보일 수는 있어도 동일하지 않습니다.- drain: 유지보수 “사전 예방”
- NotReady 장기화 후 복구: 장애 “사후 대응”
그리고 둘 다 공통으로:
- standalone 파드는 자동 재생성이 안 됨
10.2 Unschedulable(cordon)면 트래픽이 안 가나요?
아닙니다.
cordon은 스케줄링만 막습니다.- 트래픽 라우팅은 Service의 Endpoint(Ready Pod) 기준입니다.
즉:
- 노드가 cordon 상태여도, 그 노드의 파드가 Ready면 트래픽은 계속 갈 수 있습니다.
- 노드가 NotReady면, 대개 파드가 Ready에서 빠지고 Endpoint에서 제외되면서 트래픽이 끊기는 방향으로 갑니다.
실제로 라우팅 백엔드는 EndpointSlice로 확인하는 게 정확합니다.
kubectl get endpointslice -n <ns> -l kubernetes.io/service-name=<svc>
11) kubeadm 기반 롤링 업그레이드 예시 시퀀스(워커 1대 기준)
아래는 “노드 1대 업그레이드”의 대표 흐름입니다.
- 노드 비우기(파드 재생성 유도)
kubectl drain <node-1> --ignore-daemonsets --delete-emptydir-data
- 노드에서 kubelet/kubectl 등 업그레이드 + 노드 구성 업데이트
# (예시) 패키지 업그레이드 후
sudo systemctl restart kubelet
# (환경에 따라)
kubeadm upgrade node
- 스케줄 가능 상태로 복귀
kubectl uncordon <node-1>
이 과정을 노드 2, 노드 3… 순서로 반복합니다.
12) 운영 체크리스트(업그레이드 전에 꼭 확인)
- 업그레이드 타겟 버전의 릴리스 노트/Breaking change
- etcd / CoreDNS 같은 외부/의존 컴포넌트 호환 버전
- 중요한 워크로드가 standalone이 아닌지
- PDB(PodDisruptionBudget)로 드레인 시 동시 중단을 제어할지
- 워커 노드 업그레이드 시 drain 옵션(daemonset, emptyDir) 대응
- 트래픽 관점은 cordon 여부가 아니라 Ready/EndpointSlice로 확인
'CKA' 카테고리의 다른 글
| Cluster Maintenance - 총 정리 (0) | 2025.12.31 |
|---|---|
| Cluster Maintenance - 백업 방법(yaml 및 etcd) (0) | 2025.12.31 |
| Cluster Maintenance - Cordon/Drain/Uncordon (1) | 2025.12.31 |
| Application Lifecycle Management - 총 정리 (0) | 2025.12.31 |
| Application Lifecycle Management - VPA (1) | 2025.12.30 |