본문으로 건너뛰기

Karpenter 문제 해결

Karpenter 컨트롤러, KCNodeClass, NodePool 및 NodeClaim의 상태와 이벤트를 확인하여 노드가 생성되거나 삭제되지 않는 원인을 진단합니다.

기본 진단​

다음 명령으로 주요 리소스와 Warning 이벤트를 확인합니다.

Karpenter 기본 상태 확인
kubectl -n karpenter-kakaocloud get deployment,pod
kubectl get kcnodeclass,nodepool,nodeclaim
kubectl get events -A --field-selector type=Warning \
--sort-by=.lastTimestamp

컨트롤러 로그와 문제가 발생한 리소스의 상세 정보를 확인합니다.

로그 및 리소스 상세 정보 확인
kubectl -n karpenter-kakaocloud logs \
deployment/karpenter-provider-kakaocloud --tail=200

kubectl describe kcnodeclass <KCNODECLASS_NAME>
kubectl describe nodepool <NODEPOOL_NAME>
kubectl describe nodeclaim <NODECLAIM_NAME>

Kubernetes 버전 차이에 대한 일부 이벤트는 Normal 유형으로 기록되어 Warning 이벤트 조회 결과에는 표시되지 않을 수 있습니다. 관련 상태는 KCNodeClass의 조건에서 확인합니다.

증상별 확인 사항​

컨트롤러가 실행되지 않는 경우​

  • 파드가 Pending 또는 ContainerCreating 상태인 경우: 파드 이벤트와 이미지 레지스트리 접근을 확인합니다. 자격 증명 Secret에는 applicationCredentialId, applicationCredentialSecret, region, 서명 키 Secret에는 keyring.json이 있어야 합니다.
  • 파드가 CrashLoopBackOff 상태인 경우: 로그와 설치 값의 region, clusterName, projectID, IAM 권한을 확인합니다. region은 kr-central-2이며 서명 키는 32바이트여야 합니다.
  • RESTARTS가 증가하지만 명확한 오류가 없는 경우: 필수 CRD의 설치 여부를 확인하고, 누락되었다면 설치한 차트 버전의 CRD를 다시 적용합니다.

노드가 생성되지 않거나 준비되지 않는 경우​

  • KCNodeClass의 Ready=False: status.conditions의 reason과 메시지를 확인합니다. 서브넷, 워커 보안 그룹, 워커 이미지, 키 페어 및 IAM 조회 권한을 점검합니다.
  • KubernetesVersionReady=False: reason이 UnsupportedKubernetesVersion 또는 KubernetesVersionSkew인지 확인합니다. Kubernetes Engine에서 제공하는 버전 중 컨트롤 플레인과 같거나 한 단계 낮은 마이너 버전을 지정합니다.
  • KubernetesVersionDeprecated=True: WorkerVersionNotOffered는 현재 워커 버전의 신규 제공이 종료되었음을 뜻합니다. 기존 구성의 노드 생성은 계속되므로 지원 종료된 버전 안내에 따라 업데이트 일정을 수립합니다.
  • ImagesReady=True, reason ImagesRetained: 현재 버전의 이미지를 조회하지 못해 이전 이미지를 유지하는 상태입니다. 지원 버전으로 변경하거나 검증된 이미지 ID를 spec.imageID에 지정합니다.
  • 파드는 Pending이지만 NodeClaim이 없는 경우: NodePool과 KCNodeClass의 Ready, requirements, limits, 파드 이벤트를 확인합니다. 충돌하는 인스턴스·가용 영역 조건을 완화하고 리소스 상한을 조정합니다.
  • NodeClaim은 있지만 노드가 Ready가 되지 않는 경우: NodeClaim 이벤트, API 서버·DNS·메타데이터 서비스 통신, NAT와 egress, 워커 보안 그룹 및 CNI 규칙을 확인합니다. 메타데이터 서비스 주소는 169.254.169.254입니다.
  • Cilium 노드의 파드가 계속 Pending 상태인 경우: Cilium DaemonSet 상태와 node.cilium.io/agent-not-ready startup taint를 확인합니다. Calico 클러스터에는 이 taint를 사용하지 않습니다.
  • GPU 노드는 Ready지만 GPU가 0인 경우: GPU Operator와 device plugin, nvidia.com/gpu의 capacity·allocatable을 확인합니다. 자세한 내용은 GPU 런타임 확인을 참고하시기 바랍니다.
  • 예상하지 않은 노드 교체가 발생한 경우: NodeClaim 이벤트에서 통합·드리프트·만료 사유를 확인합니다. consolidateAfter, 중단 예산, expireAfter, KCNodeClass 변경 이력을 점검합니다.

KCNodeClass가 Ready=False라면 각 조건의 reason과 메시지를 확인합니다.

KCNodeClass 조건 확인
kubectl get kcnodeclass <KCNODECLASS_NAME> \
-o jsonpath='{range .status.conditions[*]}{.type}{"\t"}{.status}{"\t"}{.reason}{"\t"}{.message}{"\n"}{end}'

주요 조건은 다음과 같습니다.

조건확인 대상
KubernetesVersionReady클러스터 상태와 bootstrap.kubernetesVersion
KubernetesVersionDeprecated사용 중인 워커 Kubernetes 버전의 제공 여부
ImagesReadyKubernetes 버전에 맞는 워커 이미지
SubnetsReady서브넷 ID, 프로젝트 및 지원 가용 영역
SecurityGroupsReady보안 그룹 ID와 Kubernetes Engine 워커 보안 그룹 포함 여부
KeyPairReadykeyName에 지정한 키 페어
Ready위 조건의 종합 결과

업데이트 또는 삭제 중 문제가 발생한 경우​

  • 컨트롤 플레인 업데이트 API가 HTTP 400을 반환하는 경우: 코드가 InvalidRequest.BadRequest이고 메시지가 upgrade the karpenter nodes of cluster로 시작한다면, 모든 Karpenter 노드를 현재 컨트롤 플레인 버전으로 교체한 뒤 다시 요청합니다.
  • 컨트롤 플레인 업데이트 API가 HTTP 500을 반환하는 경우: 코드가 InternalError.InternalServerError라면 응답만으로 버전 불일치를 판단하지 않습니다. 잠시 후 다시 요청하고, 반복되면 헬프데스크로 문의합니다.
  • Kubernetes Engine 노드 삭제 API가 HTTP 404를 반환하는 경우: 코드가 ResourceNotAssociated.NotFound인지 확인합니다. Karpenter 노드는 Kubernetes Engine 노드 삭제 API가 아닌 NodeClaim을 삭제하여 회수합니다.
  • 노드 또는 NodeClaim이 삭제되지 않는 경우: PodDisruptionBudget, karpenter.sh/do-not-disrupt, 종료 중인 파드와 NodeClaim 이벤트를 확인합니다. 워크로드를 안전하게 중단할 수 있을 때 회수 정책을 조정하고 컨트롤러는 유지합니다.
  • 노드는 사라졌지만 인스턴스가 남은 경우: 콘솔의 인스턴스·볼륨과 서명 검증 로그를 확인합니다. 기존 서명 키로 컨트롤러 복구를 시도하고, 불가능하면 잔여 리소스 식별을 참고하시기 바랍니다.
  • 클러스터가 Deleting 상태에 머무르는 경우: 삭제 전에 기록한 인스턴스·볼륨을 콘솔과 대조합니다. 잔여 리소스 식별 후에도 상태가 계속되면 헬프데스크로 문의합니다.

GPU 런타임 확인​

GPU 노드에 nvidia.com/gpu 리소스가 등록되었는지 확인합니다.

GPU capacity 및 allocatable 확인
kubectl get nodes -l karpenter.sh/nodepool=karpenter-gpu \
-o custom-columns='NODE:.metadata.name,CAPACITY:.status.capacity.nvidia\.com/gpu,ALLOCATABLE:.status.allocatable.nvidia\.com/gpu'

GPU Operator의 파드가 모두 Running인데 값이 비어 있으면 containerd의 실제 적용 설정을 확인합니다. 다음 명령은 Pod Security 정책에 따라 제한될 수 있습니다.

containerd NVIDIA 런타임 확인
kubectl debug node/<GPU_NODE_NAME> -it --image=busybox:1.36 -- \
chroot /host sh -c \
"containerd config dump | grep -E 'runtimes.nvidia'"

runtimes.nvidia 항목이 없으면 NVIDIA Container Toolkit 적용 상태를 확인합니다. /etc/containerd/config.toml 파일을 직접 수정하지 말고 GPU Operator가 런타임 구성을 다시 적용하도록 조치합니다.

삭제 지연 및 잔여 리소스 처리​

NodeClaim 삭제가 지연되면 연결된 노드의 파드와 중단 정책을 확인합니다.

노드의 파드 및 중단 정책 확인
kubectl get pods -A --field-selector spec.nodeName=<NODE_NAME>
kubectl get pdb -A
kubectl describe nodeclaim <NODECLAIM_NAME>

finalizer를 강제로 제거하면 Karpenter가 인스턴스와 볼륨을 정리하지 못할 수 있습니다. 일반적인 복구 절차로 finalizer를 삭제하지 말고, 기존 서명 키와 설정으로 컨트롤러를 복구하여 삭제를 다시 시도합니다.

노드 또는 Virtual Machine의 이름이나 설명이 변경되면 자동 회수 대상에서 제외될 수 있습니다. 이 경우 NodeClaim이 삭제된 후에도 인스턴스와 요금이 남을 수 있습니다.

잔여 리소스 식별​

클러스터 삭제가 완료된 뒤에도 인스턴스나 볼륨이 남아 있다면 다음 정보를 대조합니다.

  • 삭제 전에 기록한 NodeClaim의 provider ID와 인스턴스·볼륨 ID
  • 인스턴스 이름 karpenter-<클러스터 UID 앞 8자>-<NodeClaim 이름>
  • v=1;m=karpenter;로 시작하는 인스턴스 설명

클러스터 UID는 kubeconfig의 API 서버 엔드포인트에 포함된 값으로, 콘솔의 클러스터 ID와 다릅니다.

해당 클러스터에서 생성한 인스턴스임이 확인되고 같은 프로젝트에 다른 Karpenter 클러스터가 없다면, Virtual Machine > 인스턴스에서 남은 인스턴스를 삭제할 수 있습니다.

볼륨은 삭제 전에 기록한 ID와 생성 일시를 대조합니다. 연결된 인스턴스가 없는 경우에만 삭제합니다. 다른 클러스터의 리소스와 구분하기 어렵다면 직접 삭제하지 말고 헬프데스크 > 기술 문의로 문의하시기 바랍니다.

CRD 및 서명 키 정리​

서명 키는 남은 인스턴스의 소유권 확인에 필요합니다. 인스턴스가 모두 삭제된 것을 확인하기 전에는 서명 키 Secret과 백업을 삭제하지 않습니다.

Karpenter를 다시 설치할 계획이 없고 다른 구성이 같은 CRD를 사용하지 않는다면, Helm 릴리스 삭제 후 CRD를 삭제할 수 있습니다.

Karpenter CRD 삭제
kubectl delete crd \
kcnodeclasses.karpenter.kakaocloud.com \
nodeclaims.karpenter.sh \
nodepools.karpenter.sh \
nodeoverlays.karpenter.sh \
capacitybuffers.autoscaling.x-k8s.io

남은 인스턴스가 없는 것을 확인한 뒤 보관 중인 keyring.json 백업을 정리합니다.

컨트롤러 복구가 어렵거나 인스턴스 회수 여부를 확인할 수 없으면 헬프데스크 > 기술 문의로 문의하시기 바랍니다. 문의할 때 다음 정보를 함께 전달합니다.

  • 클러스터 이름과 ID
  • Karpenter Provider 차트 버전과 컨트롤러 이미지
  • KCNodeClass, NodePool 및 NodeClaim의 YAML
  • Warning 이벤트와 컨트롤러 로그
  • 관련 노드 이름과 Virtual Machine 인스턴스 ID
  • 문제 발생 시각과 수행한 변경 사항