Kubernetes 클러스터의 업그레이드를 단순히 "버전을 올리는 작업"으로 이해하기 쉽지만, 그 이면에는 꽤 정교한 내부 동작과 절차가 숨어 있습니다. 이 글에서는 kubeadm 설치 환경에서 Kubernetes 업그레이드가 실제로 어떻게 작동하는지, 살펴보며 정리해보겠습니다.

 

Kubernetes는 선언적(Declarative) 시스템입니다. kubeadm upgrade는 단순히 새 바이너리를 덮어씌우는 것이 아니라, 클러스터의 현재 상태를 읽고, 목표 상태로 점진적이고 안전하게 조정해 나갑니다.

 

주요 업그레이드 단계와 내부 로직


1. 현재 상태 평가 (upgrade plan)

  • kubeadm upgrade plan 실행 시, 다음을 수행합니다
    • kubeadm-config ConfigMap을 읽어 현재 버전과 구성 확인
    • kube-apiserver의 version API로 실제 버전 조회
    • 대상 버전과의 호환성 검사
    • CoreDNS, kube-proxy, CNI 등 애드온 호환성 체크

관련코드

- https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/cmd/upgrade/plan.go

 

kubernetes/cmd/kubeadm/app/cmd/upgrade/plan.go at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

github.com

실제로 업그레이드 실행은 하지 않고, 업그레이드가 가능한지 점검하고 계획(plan)을 출력하는 역할을 합니다.

kubeadm upgrade plan

이 명령어를 실행하면 아래의 함수가 실행되며 plan로직이 시작되게 됩니다.

 

func NewCmdPlan(...)

 

이 함수는 CLI 커맨드인 kubeadm upgrade plan을 정의합니다.

 

Run: func(cmd *cobra.Command, args []string) {
	err := runUpgradePlan(...)
	// ...
}

해당 커맨드가 실행되면 내부적으로 runUpgradePlan() 함수를 호출합니다

func runUpgradePlan(out io.Writer, flags *apply.PlanFlags) error

이 함수가 실제 plan 로직을 처리합니다. 주요 흐름은 아래와 같습니다

  • upgrade.GetAvailableUpgrades() 호출 → 업그레이드 가능한 버전 목록 조회
  • 현재 상태와 비교하여 업그레이드가 필요한 구성 요소 확인 (API Server, Controller Manager, Scheduler, CoreDNS, kube-proxy 등)
  • 업그레이드 시 어떤 작업이 수행될지 플랜 출력

실제로 업그레이드 가능 버전 계산하는 부분

plans, err := upgrade.GetAvailableUpgrades(...)
func GetAvailableUpgrades(...)

이 함수는

  • 현재 클러스터 상태 확인 (ConfigMap, kubelet, kube-apiserver 등)
  • 업그레이드 가능한 버전 목록을 kubeadm binary 기준으로 계산
  • CoreDNS, kube-proxy, etcd 등 업그레이드 대상 포함 여부 결정

 

실제 업그레이드를 수행하는 코드는?

kubeadm upgrade apply <version>

이 명령어를 실행하면 아래의 함수가 실행되며 apply로직이 시작되게 됩니다.

 

업그레이드는 다음 커맨드에서 수행됩니다

https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/cmd/upgrade/apply.go

 

kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

github.com

func NewCmdApply(...)

 

2. kube-apiserver → controller → scheduler 순으로 static pod 교체

업그레이드 실행 시, 다음과 같은 절차로 static pod를 교체합니다

  • /etc/kubernetes/manifests 경로에 있는 manifest 파일 교체
  • kubelet이 static pod 파일 감지 → 컨테이너 재생성
  • 교체된 프로세스가 readiness 상태로 돌아오면 다음 컴포넌트로 진행

관련코드

- https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/phases/upgrade/staticpods.go 

 

kubernetes/cmd/kubeadm/app/phases/upgrade/staticpods.go at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

github.com

func PerformStaticPodUpgrade(...)
  • /etc/kubernetes/manifests/ 경로에 존재하는 static pod manifest들을 새로운 버전으로 교체
  • kubelet이 이 변경을 감지하고 기존 pod 종료 + 새 pod 생성
  • 업그레이드가 정상적으로 완료되었는지 확인 (해당 컴포넌트의 health check 수행)

 

실제 업그레이드 수행 코드

PerformStaticPodUpgrade() 내부의 핵심은 이 부분입니다

err = upgrader.UpgradeComponent(component)

여기서 upgrader는 StaticPodPathManager 인터페이스를 구현한 객체이며, 각 control plane 컴포넌트(kube-apiserver, controller-manager, scheduler)를 업그레이드합니다.

 

UpgradeComponent() 내부에서 어떤 일이?

UpgradeComponent()는 다음과 같은 흐름으로 동작합니다:

  1. 현재 static pod manifest를 백업
  2. 새로운 버전에 맞는 manifest를 생성
  3. 해당 manifest 파일을 /etc/kubernetes/manifests/에 덮어쓰기
  4. kubelet이 감지하여 새 static pod를 실행
  5. 업그레이드 완료되었는지 확인 (health check 또는 readiness probe 등으로)

이 로직은 다음과 같은 함수들을 통해 구성됩니다

  • CreateStaticPodManifestFiles(...)
  • WaitForStaticPodControlPlaneHashChange(...)
  • StaticPodControlPlaneWaiter.WaitForStaticPodSingleHash(...)

 

예를 들어 kube-apiserver 업그레이드 시

  1. /etc/kubernetes/manifests/kube-apiserver.yaml의 내용을 새 버전 기준으로 덮어씀
  2. kubelet이 이를 감지하고 기존 apiserver pod를 종료
  3. 새로 생성된 manifest로 새로운 버전의 kube-apiserver pod 실행
  4. WaitForStaticPodControlPlaneHashChange()로 업그레이드된 Pod의 hash 값이 변경되었는지 확인하여 성공 여부 판단
  5. 이 과정을 kube-controller-manager, kube-scheduler 등 모든 control plane 구성요소에 대해 반복합니다.

 

static pod 교체의 핵심 원리

Kubernetes control plane의 핵심 컴포넌트(apiserver, controller-manager, scheduler)는 static pod로 동작합니다. 업그레이드 시에는 이 static pod의 manifest 파일이 새 버전으로 덮어쓰기되며, kubelet이 이를 감지하여 자동으로 재시작합니다.

/etc/kubernetes/manifests/kube-apiserver.yaml → 변경
└──> kubelet이 detect → 기존 컨테이너 종료 + 새로운 버전으로 시작

이 덕분에 systemd나 외부 툴 없이도 자체적으로 control plane을 self-managed하게 유지할 수 있습니다.

 

3. CoreDNS, kube-proxy 등의 애드온 리소스 업그레이드

  • CoreDNS: Deployment를 patch하거나 recreate
  • kube-proxy: DaemonSet을 rolling update 방식으로 갱신
  • ClusterConfiguration의 필드 비교 후, apply 방식으로 업데이트

관련코드

- https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/phases/addons/dns/dns.go

 

kubernetes/cmd/kubeadm/app/phases/addons/dns/dns.go at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

github.com

- https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/phases/addons/proxy/proxy.go

 

kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy.go at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

github.com

 

func EnsureDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface) error {
	// ...
	return coreDNS.EnsureDNSAddon(cfg, client)
}

 

func EnsureProxyAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface) error {
	// ...
	return proxyaddon.EnsureProxyAddon(cfg, client)
}

 

4. kubelet, kubectl은 별도 수동 업그레이드

  • 바이너리 교체 및 systemctl restart kubelet 필요
  • 노드별 kubeadm upgrade node 명령으로 kubelet 설정 업데이트
  • 업그레이드된 kubelet은 새 control plane과 통신하면서 정상 상태 유지

 

etcd는 언제 업그레이드될까?


  • etcd는 kubeadm-config에 명시된 버전에 따라 업그레이드됩니다.
  • 단독 실행 중이면 외부 관리 필요 (kOps, kubeadm 외)
  • embedded etcd일 경우 static pod로 관리되며 다른 컴포넌트와 동일 방식으로 교체

 

kubeadm 업그레이드 흐름


etcd snapshot
└──> 업그레이드 전 백업(선택사항)

kubeadm upgrade plan
└──> 현재 상태 + kubeadm-config + version API 분석

kubeadm upgrade apply v1.31.1
├── static pod 교체 (/etc/kubernetes/manifests)
├── CoreDNS, kube-proxy patch
└── kubeadm-config 업데이트

 

정리


Kubernetes의 업그레이드는 단순히 “버전 교체”가 아니라, 클러스터의 상태를 확인하고 각 구성요소를 안정적으로 교체하는 과정입니다. kubeadm은 이러한 과정을 단계적 절차를 거치는 메커니즘을 통해 안전하게 업그레이드를 수행하고 있다는 것을 알아보았습니다.

 

실제 운영환경에서는 주기적인 버전 업그레이드 작업이 필요하게 됩니다. 본 글을 통해 업그레이드 과정시에 조금이나마 도움이 되셨으면 좋겠습니다.

+ Recent posts