본문으로 건너뛰기

업그레이드와 수명주기 관리

11분 읽기
AI용 문서 안내

개요​

하이브리드 노드의 Kubernetes 버전 업그레이드는 managed node group과 달리 전 과정이 고객 책임입니다(공유 책임 모델). AWS는 업그레이드 도구(nodeadm upgrade)를 제공하지만, 워크로드 대피(drain)·순서 제어·검증은 운영자가 수행합니다. 본 문서는 업그레이드 전략 선택(in-place vs 노드 교체), nodeadm upgrade의 동작 원리, 사전 조건(드레인·nodeadm 버전), 폐쇄망 환경의 사설 미러 구성, 그리고 노드 단위 업그레이드 런북을 다룹니다.

업그레이드 전략: 노드 교체 vs In-Place​

전략방식적합 환경
노드 교체 (cutover, blue-green) — 공식 권장대상 버전으로 초기화한 새 노드를 조인시키고, 워크로드를 이전한 후 구버전 노드를 nodeadm uninstall·kubectl delete node로 제거여유 장비 또는 가상화 기반 노드 프로비저닝이 가능한 환경
In-place (nodeadm upgrade)기존 노드에서 kubelet 등 아티팩트를 대상 버전으로 교체 — 교체 중 노드 다운타임 발생여유 용량이 없어 같은 호스트에서 업그레이드해야 하는 환경

공식 가이드는 여유 용량이 있으면 노드 교체(cutover)를 권장하고, in-place는 여유 용량이 없는 환경의 대안으로 규정합니다. 두 전략 모두 전제 조건은 동일합니다. 컨트롤 플레인을 먼저 업그레이드한 후 노드를 따라가며, 노드 버전은 컨트롤 플레인과 같거나 낮아야 하고 Kubernetes 버전 skew 정책(kubelet은 API server보다 최대 3개 마이너 버전 하위) 범위 안에 있어야 합니다. In-place 업그레이드에서 자격 증명 공급자(SSM ↔ IAM RA)는 변경할 수 없으며 노드 이름은 업그레이드 후에도 유지됩니다.

nodeadm upgrade 동작 원리: 4단계 프로세스​

nodeadm upgrade는 노드 위에서 실행되는 in-place 교체 작업이며, 내부적으로 4단계로 진행됩니다.

글씨가 작으면 확대해서 확인할 수 있습니다.
다이어그램
  1. Shutdown: kubelet을 포함한 노드 구성 요소를 정지합니다. 이 시점부터 노드의 Pod는 새로 스케줄되지 않습니다.
  2. Uninstall: 기존 Kubernetes 버전의 아티팩트(kubelet, kubectl 바이너리 등)를 제거합니다.
  3. Install: 대상 버전의 아티팩트를 다운로드해 설치합니다. 폐쇄망에서는 이 단계가 사설 경로로 해석 가능해야 합니다.
  4. Restart: NodeConfig를 기반으로 노드를 재초기화하고 클러스터에 재조인합니다.
# 대상 버전과 NodeConfig를 지정해 실행
sudo nodeadm upgrade 1.34 --config-source file://nodeConfig.yaml

in-place 업그레이드는 노드에 다운타임을 유발합니다. nodeadm upgrade는 kubelet·kubectl 등 EKS 아티팩트뿐 아니라 OS 패키지 매니저를 통해 containerd도 함께 업그레이드하며(대상 Kubernetes 버전에 따라 containerd 메이저 버전 업그레이드가 포함될 수 있습니다), 이 과정에서 실행 중이던 컨테이너는 재시작될 수 있습니다. kubelet 중지·재시작 사이에 노드는 NotReady가 되어 헬스 체크·스케줄링 대상에서 제외되므로, 업그레이드 전 반드시 수동 drain으로 워크로드를 대피시켜야 합니다. 따라서 "실행 중인 컨테이너가 그대로 보존된다"고 가정하지 말고, 업그레이드를 중단 가능한(disruptive) 작업으로 계획합니다.

수동 드레인 의무: nodeadm은 Pod를 대피시키지 않습니다​

drain 생략 시 워크로드 유실 위험

nodeadm upgrade는 Pod 대피(drain)를 수행하지 않습니다. managed node group 업그레이드가 자동으로 수행하는 cordon → drain → 교체 흐름을 하이브리드 노드에서는 관리자가 직접 실행해야 합니다. drain 없이 업그레이드하면 kubelet 중지 시점에 실행 중이던 Pod가 정상 종료 절차(preStop hook, terminationGracePeriod) 없이 중단될 수 있습니다.

# 1. 신규 스케줄링 차단
kubectl cordon mi-0f1c2d3e4a5b6c7d8

# 2. 워크로드 대피 (PodDisruptionBudget 존중)
# 주의: --delete-emptydir-data 는 해당 노드 Pod의 emptyDir 볼륨 데이터를 삭제합니다.
# 버퍼·캐시·스크래치에 복구 불가 데이터가 없는지 먼저 확인하고,
# 필요한 데이터는 백업하거나 영구 볼륨으로 옮긴 뒤 실행합니다.
# 주의: --grace-period=300 은 각 Pod에 설정된 terminationGracePeriodSeconds 를
# 300초로 "덮어씁니다". 워크로드별 종료 시간을 모르면 이 플래그를 생략해
# Pod별 기본 grace period 를 사용하고, 필요한 워크로드만 값을 조정합니다.
kubectl drain mi-0f1c2d3e4a5b6c7d8 \
--ignore-daemonsets \
--delete-emptydir-data \
--grace-period=300 \
--timeout=15m
# drain 이 timeout 에 도달하면 성공으로 간주하지 말고, 왜 Pod가 축출되지 않는지
# (PDB 대기, 종료 지연 등) 조사한 뒤 다시 진행합니다.

# 3. 업그레이드 실행 (노드에서)
sudo nodeadm upgrade 1.34 --config-source file://nodeConfig.yaml

# 4. 노드 Ready·버전 확인 후 스케줄링 재개
kubectl get node mi-0f1c2d3e4a5b6c7d8 -o wide # VERSION 열 확인
kubectl uncordon mi-0f1c2d3e4a5b6c7d8
  • nodeadm upgrade는 기본 동작으로 노드가 cordon 상태인지(node-validation), DaemonSet·static Pod 외의 Pod가 남아 있지 않은지(pod-validation) 를 사전 검증하고, 충족되지 않으면 진행하지 않습니다. 이 검증은 안전장치일 뿐 drain을 대신 수행하지는 않습니다.
  • PodDisruptionBudget(PDB) 이 구성된 워크로드는 drain이 축출(eviction) API를 통해 PDB를 존중하므로, 축출로 인해 PDB가 위반되면 drain이 대기하거나 멈춥니다. 노드를 한 대씩 순차 진행하면 동시 중단 범위는 줄지만, 한 대만 축출해도 minAvailable이 현재 replica 수와 같거나 이미 가용 replica가 부족하면 그 한 건의 축출마저 거부됩니다. 따라서 순차 진행만으로 PDB stall이 방지되는 것은 아닙니다. drain 전에 각 워크로드의 가용 replica 수, 여유 용량(다른 노드로 재스케줄 가능 여부), PDB 설정을 사전 점검하고, drain이 막히면 replica 증설·PDB 조정 등 워크로드 차원의 조치를 취한 뒤 다시 진행합니다.
  • GPU 추론처럼 종료에 시간이 걸리는 워크로드는 --grace-period를 모델 언로드 시간에 맞게 조정합니다.
  • 노드가 다시 Ready가 된 후에도 CNI(Cilium) DaemonSet Pod가 정상 기동했는지 확인한 뒤 uncordon합니다.

SSM 서명 키 만료: nodeadm 1.0.19 이상 필수​

이전 버전 nodeadm 바이너리에 포함된 SSM 서명 키가 만료되어, SSM 자격 증명 공급자를 사용하는 환경에서 nodeadm install/upgrade가 다음 서명 검증 오류로 실패하는 이슈가 있습니다.

"msg":"Command failed","error":"failed to install ssm installer:
validating ssm-setup-cli signature: Signature Verification Error: No matching signature"

업그레이드 실행 전 nodeadm 자체를 1.0.19 이상으로 먼저 갱신하는 것을 업그레이드 런북의 0단계로 고정합니다.

# 현재 nodeadm 버전 확인
nodeadm version

# 최신 nodeadm으로 교체 (x86_64)
curl -OL 'https://hybrid-assets.eks.amazonaws.com/releases/latest/bin/linux/amd64/nodeadm'
chmod +x nodeadm && sudo mv nodeadm /usr/local/bin/nodeadm

특정 버전 고정이 필요한 폐쇄망 배포 체계에서는 releases/latest 대신 버전 경로를 사용하고, 내부 아티팩트 저장소에 바이너리와 함께 체크섬을 미러링합니다.

폐쇄망 업그레이드: 사설 미러 구성​

nodeadm upgrade는 EKS 아티팩트(kubelet 등)를 받아오지만, containerd·ca-certificates·커널 모듈 같은 OS 계층 의존성은 OS 패키지 매니저(yum/dnf, apt)가 담당합니다. 인터넷이 차단된 환경에서 업그레이드가 중간에 실패하지 않으려면 두 경로 모두 내부망에서 해석되어야 합니다.

다운로드 대상기본 출처폐쇄망 대응
EKS 노드 아티팩트 (kubelet 등)hybrid-assets.eks.amazonaws.com내부 아티팩트 저장소 미러 또는 해당 도메인 한정 프록시 허용
OS 패키지 (containerd, ca-certificates, runc 등)OS 공식 저장소 (yum/apt)사설 미러 서버로 저장소 소스 경로 교체
컨테이너 이미지 (CNI·애드온)ECR·public.ecr.awsECR PrivateLink 또는 Harbor 미러 (레지스트리 통합)

OS·버전·아키텍처별로 미러를 분리하고(RHEL과 AL2023 패키지를 한 저장소에 섞지 않음), 필요한 모든 저장소와 GPG 서명 키를 포함시킵니다. 기존 공개 소스는 백업한 뒤 명시적으로 교체 또는 비활성화하고, 작업 후 활성화된 소스 목록을 검증합니다. 아래는 배포판별 접근 방식의 예시이며, 실제 미러 경로·릴리스 버전·키는 환경에 맞게 바꿉니다.

# RHEL 9 — 공개 BaseOS/AppStream 을 내부 미러로 교체 (RHEL 전용)
sudo cp /etc/yum.repos.d/redhat.repo /etc/yum.repos.d/redhat.repo.bak 2>/dev/null || true
sudo tee /etc/yum.repos.d/internal-mirror.repo << 'EOF'
[internal-rhel9-baseos]
name=Internal Mirror - RHEL9 BaseOS
baseurl=https://mirror.company.local/rhel9/baseos/
enabled=1
gpgcheck=1
gpgkey=https://mirror.company.local/keys/RPM-GPG-KEY-redhat-release
[internal-rhel9-appstream]
name=Internal Mirror - RHEL9 AppStream
baseurl=https://mirror.company.local/rhel9/appstream/
enabled=1
gpgcheck=1
gpgkey=https://mirror.company.local/keys/RPM-GPG-KEY-redhat-release
EOF
sudo dnf clean all && sudo dnf repolist # 활성화된 소스 검증

# AL2023 — Amazon Linux 는 버전 고정 저장소를 쓰므로 RHEL 저장소를 재사용하지 않습니다.
# /etc/dnf/vars/releasever 로 릴리스 버전을 고정하고, mirrorlist 를 내부 미러로 교체합니다.
sudo cp /etc/yum.repos.d/amazonlinux.repo /etc/yum.repos.d/amazonlinux.repo.bak
echo "2023.5.20240708" | sudo tee /etc/dnf/vars/releasever # 조직이 검증한 버전으로 고정
sudo sed -i 's#^mirrorlist=.*#baseurl=https://mirror.company.local/al2023/$releasever/$basearch/#' \
/etc/yum.repos.d/amazonlinux.repo
sudo dnf clean all && sudo dnf repolist # amazonlinux 저장소가 내부 미러를 가리키는지 확인

# Ubuntu — 기본 소스는 ubuntu.sources 에 있으므로, 추가 파일만 두면 공개 저장소가 함께 사용됩니다.
# 폐쇄망이면 기본 소스를 백업·비활성화한 뒤 내부 미러로 대체합니다.
sudo cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak 2>/dev/null || true
sudo tee /etc/apt/sources.list.d/internal-mirror.list << 'EOF'
deb https://mirror.company.local/ubuntu noble main universe
deb https://mirror.company.local/ubuntu noble-updates main universe
deb https://mirror.company.local/ubuntu noble-security main universe
EOF
# 공개 소스를 함께 쓰지 않으려면 기본 소스를 비활성화합니다(예: ubuntu.sources 를 .bak 로 이동).
sudo apt-get update # 활성화된 소스가 모두 내부 미러로 해석되는지 확인

사설 미러는 업그레이드 시점에만 필요한 것이 아니라 OS 보안 패치의 상시 공급 경로입니다. 미러 동기화 주기·GPG 키 관리·미러 자체의 가용성을 업그레이드 계획 이전에 운영 체계로 정착시킵니다.

업그레이드 런북 (노드 단위)​

단계작업검증
0nodeadm 1.0.19+ 확인·갱신, 사설 미러 도달성 점검nodeadm version, yum repolist/apt-get update 성공
1컨트롤 플레인 업그레이드 완료 확인aws eks describe-cluster --name <cluster-name> --region <region> --query cluster.version(필요 시 --profile <profile>)
1bCNI/애드온이 대상 Kubernetes 버전을 지원하는지 사전 확인하고, 지원하지 않으면 노드 업그레이드 전에 CNI를 먼저 업그레이드애드온 버전 매트릭스 확인, CNI가 대상 버전 지원
2Cluster Insights에서 업그레이드 차단 이슈 확인구성 검증
3kubectl cordon + kubectl drain (한 대씩)Pod 재배치 완료, PDB 위반 없음
4sudo nodeadm upgrade <version> --config-source file://nodeConfig.yaml종료 코드 0
5노드 Ready·버전·CNI Pod 기동 확인kubectl get node -o wide, kubectl get pods -n kube-system -o wide --field-selector spec.nodeName=<node>
6kubectl uncordon 후 다음 노드로 진행워크로드 정상 배치
7전체 완료 후 애드온(CoreDNS·kube-proxy·Cilium)이 대상 버전과 정렬되었는지 최종 검증 (호환성 선행 점검은 1b 단계에서 이미 수행)애드온 버전 매트릭스와 실제 배포 버전 일치
  • 업그레이드 실패 시 nodeadm은 같은 명령의 재실행으로 재시도할 수 있습니다. 반복 실패 시 nodeadm debug로 네트워킹·자격 증명 요건을 재검증하고, journalctl -u kubelet과 /var/log/ 하위 nodeadm 로그를 수집합니다.
  • Cilium 등 CNI 버전은 Kubernetes 버전 호환 매트릭스를 따릅니다. 공식 전제 조건상 CNI는 대상 Kubernetes 버전을 지원해야 하며, 지원하지 않으면 하이브리드 노드 업그레이드 이전에 CNI를 먼저 업그레이드해야 합니다. 따라서 CNI 호환성 점검·업그레이드는 노드 업그레이드의 선행 조건(런북 1b 단계)이고, 전체 완료 후의 애드온 정렬은 최종 검증 단계입니다.

권장 사항 요약​

  • 업그레이드 순서는 컨트롤 플레인 → 노드이며, 노드는 한 대씩 cordon → drain → upgrade → 검증 → uncordon으로 순차 진행합니다.
  • nodeadm은 drain을 수행하지 않습니다 — drain 생략은 워크로드 유실로 직결되므로 런북에 필수 단계로 고정합니다.
  • SSM 환경은 업그레이드 전 nodeadm 1.0.19 이상 갱신을 0단계로 수행합니다.
  • 폐쇄망은 EKS 아티팩트·OS 패키지·컨테이너 이미지 세 경로의 사설 미러/PrivateLink를 사전 구성합니다.
  • PDB·grace period를 워크로드 특성(GPU 모델 언로드 등)에 맞게 조정하고, 업그레이드 창을 비피크 시간대로 계획합니다.

참고 자료​

공식 문서​

관련 문서 (내부)​