파드 디버깅하기

파드 디버깅하기

이 가이드는 쿠버네티스에 배포했는데 제대로 동작하지 않는 애플리케이션을 디버깅하려는 사용자를 돕기 위한 것이에요. 클러스터 자체를 디버깅하려는 사람을 위한 가이드는 아니며, 그런 경우 이 가이드를 확인하세요.

출처: 문서

본문

문제 진단하기

문제 해결의 첫 단계는 분류(triage)예요. 무엇이 문제일까요? 파드인지, 레플리케이션 컨트롤러인지, 아니면 서비스인지?

파드 디버깅하기

파드 디버깅의 첫 단계는 그것을 살펴보는 거예요. 다음 명령으로 파드의 현재 상태와 최근 이벤트를 확인해요:

kubectl describe pods ${POD_NAME}

파드 안 컨테이너의 상태를 살펴봐요. 모두 Running인가요? 최근 재시작이 있었나요?

파드 상태에 따라 디버깅을 계속해요.

내 파드가 계속 pending이에요

파드가 Pending에 멈춰 있다면 노드에 스케줄할 수 없다는 뜻이에요. 일반적으로 어떤 유형의 리소스가 부족해 스케줄링을 막고 있기 때문입니다. 위 kubectl describe ... 명령의 출력을 살펴봐요. 스케줄러가 파드를 스케줄할 수 없는 이유에 대한 메시지가 있어야 해요. 이유에는 다음이 포함됩니다:

  • 리소스가 부족하다: 클러스터의 CPU나 메모리 공급을 소진했을 수 있어요. 이 경우 파드를 삭제하거나, 리소스 request를 조정하거나, 클러스터에 새 노드를 추가해야 해요. 자세한 내용은 컴퓨트 리소스 문서를 참고하세요.

  • hostPort를 사용 중이다: 파드를 hostPort에 바인딩하면 파드를 스케줄할 수 있는 곳이 제한적이에요. 대부분의 경우 hostPort는 불필요하며, Service 오브젝트를 사용해 파드를 노출해보세요. hostPort가 정말 필요하다면 쿠버네티스 클러스터의 노드 수만큼만 파드를 스케줄할 수 있습니다.

내 파드가 계속 waiting이에요

파드가 Waiting 상태에 멈춰 있다면 워커 노드에 스케줄되었지만 그 머신에서 실행할 수 없다는 뜻이에요. 여기서도 kubectl describe ...의 정보가 도움이 됩니다. Waiting 파드의 가장 흔한 원인은 이미지 가져오기 실패예요. 확인할 것이 세 가지 있습니다:

  • 이미지 이름이 올바른지 확인한다.
  • 이미지를 레지스트리에 푸시했는가?
  • 이미지를 수동으로 가져와 가져올 수 있는지 확인한다. 예를 들어 PC에서 Docker를 사용한다면 docker pull <image>를 실행해보세요.

내 파드가 계속 terminating이에요

파드가 Terminating 상태에 멈춰 있다면 파드에 대한 삭제가 발행됐지만, 컨트롤 플레인이 파드 오브젝트를 삭제할 수 없다는 뜻이에요.

이런 일은 보통 파드에 finalizer가 있고, 컨트롤 플레인이 finalizer를 제거하지 못하게 하는 어드미션 웹훅이 클러스터에 설치된 경우 발생해요.

이 시나리오를 식별하려면 클러스터에 pods 리소스의 UPDATE 작업을 대상으로 하는 ValidatingWebhookConfiguration이나 MutatingWebhookConfiguration이 있는지 확인해요.

웹훅이 서드파티가 제공한 것이라면:

  • 최신 버전을 사용하고 있는지 확인한다.
  • UPDATE 작업에 대해 웹훅을 비활성화한다.
  • 해당 제공자에 이슈를 보고한다.

웹훅의 작성자라면:

  • 변경(mutating) 웹훅의 경우 UPDATE 작업에서 불변 필드를 절대 변경하지 않도록 한다. 예를 들어 컨테이너 변경은 보통 허용되지 않는다.
  • 검증(validating) 웹훅의 경우 검증 정책이 새 변경에만 적용되도록 한다. 즉 기존 위반이 있는 파드는 검증을 통과시키는 게 좋다. 이러면 검증 웹훅이 설치되기 전에 생성된 파드가 계속 실행될 수 있다.

내 파드가 크래시하거나 상태가 좋지 않아요

파드가 스케줄되면 실행 중인 파드 디버깅하기에 설명된 방법을 사용해 디버깅할 수 있어요.

내 파드가 실행 중인데 제가 시킨 일을 안 해요

파드가 예상대로 동작하지 않는다면 파드 설명(예: 로컬 머신의 mypod.yaml 파일)에 오류가 있고, 파드를 만들 때 그 오류가 조용히 무시됐을 수 있어요. 종종 파드 설명의 어떤 부분이 잘못 중첩되었거나 키 이름이 잘못 입력되어 키가 무시됩니다. 예를 들어 commandcommnd로 오타를 내면 파드는 생성되지만 의도한 명령줄을 사용하지 않게 돼요.

가장 먼저 할 일은 파드를 삭제하고 --validate 옵션으로 다시 만드는 거예요. 예를 들어 kubectl apply --validate -f mypod.yaml을 실행해보세요. commandcommnd로 오타를 냈다면 다음과 같은 오류가 납니다:

I0805 10:43:25.129850   46757 schema.go:126] unknown field: commnd
I0805 10:43:25.129973   46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842
pods/mypod

다음으로 확인할 것은 apiserver의 파드가 만들려고 한 파드(예: 로컬 머신의 yaml 파일)와 일치하는지예요. 예를 들어 kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml을 실행한 뒤 원래 파드 설명 mypod.yaml과 apiserver에서 받은 mypod-on-apiserver.yaml을 수동으로 비교해보세요. 보통 "apiserver" 버전에는 원본 버전에 없는 줄이 몇 줄 있어요. 이는 정상입니다. 하지만 원본에 있는 줄이 apiserver 버전에 없다면 파드 스펙에 문제가 있을 수 있음을 나타냅니다.

레플리케이션 컨트롤러 디버깅하기

레플리케이션 컨트롤러는 꽤 간단해요. 파드를 만들 수 있거나 만들 수 없거나 둘 중 하나입니다. 파드를 만들 수 없다면 위의 지침을 참고해 파드를 디버깅하세요.

kubectl describe rc ${CONTROLLER_NAME}을 사용해 레플리케이션 컨트롤러와 관련된 이벤트를 들여다볼 수도 있어요.

서비스 디버깅하기

서비스는 파드 집합에 걸쳐 로드 밸런싱을 제공해요. 서비스가 제대로 작동하지 않게 만드는 흔한 문제가 몇 가지 있습니다. 다음 지침이 서비스 문제를 디버깅하는 데 도움이 될 거예요.

먼저 서비스에 엔드포인트가 있는지 확인해요. 모든 Service 오브젝트에 대해 apiserver는 하나 이상의 EndpointSlice 리소스를 사용할 수 있게 만듭니다.

다음 명령으로 이 리소스들을 볼 수 있어요:

kubectl get endpointslices -l kubernetes.io/service-name=${SERVICE_NAME}

EndpointSlices의 엔드포인트가 서비스의 구성원이 될 것으로 예상하는 파드 수와 일치하는지 확인해요. 예를 들어 서비스가 3개의 레플리카를 가진 nginx 컨테이너를 위한 것이라면, 서비스의 엔드포인트 슬라이스에 세 개의 서로 다른 IP 주소가 보일 거예요.

내 서비스에 엔드포인트가 없어요

엔드포인트가 없다면 Service selector의 라벨로 파드를 나열해보세요. 예를 들어 다음 선택자를 가진 Service가 있다고 해요:

...
spec:
  selector:
    name: nginx
    type: frontend

다음 명령을 사용할 수 있어요:

kubectl get pods --selector=name=nginx,type=frontend

이 선택자와 일치하는 파드를 나열해보세요. 그 목록이 서비스를 제공할 것으로 예상되는 파드와 일치하는지 확인하고, 파드의 containerPort가 서비스의 targetPort와 일치하는지 확인해요.

네트워크 트래픽이 전달되지 않아요

자세한 내용은 서비스 디버깅하기를 참고하세요.

더 알아보기 (Learn more)

위의 어떤 방법으로도 문제가 해결되지 않으면 서비스 디버깅 문서의 지침을 따라 Service가 실행 중이고 Endpoints가 있으며 Pods가 실제로 서빙하는지 확인하고, DNS가 동작하고 iptables 규칙이 설치되어 있으며 kube-proxy가 오작동하지 않는지 확인하세요.

자세한 내용은 문제 해결 문서를 방문해도 좋아요.