파드 디버깅하기
파드 디버깅하기
이 가이드는 쿠버네티스에 배포했는데 제대로 동작하지 않는 애플리케이션을 디버깅하려는 사용자를 돕기 위한 것이에요. 클러스터 자체를 디버깅하려는 사람을 위한 가이드는 아니며, 그런 경우 이 가이드를 확인하세요.
출처: 문서
본문
문제 진단하기
문제 해결의 첫 단계는 분류(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 파일)에 오류가 있고, 파드를 만들 때 그 오류가 조용히 무시됐을 수 있어요. 종종 파드 설명의 어떤 부분이 잘못 중첩되었거나 키 이름이 잘못 입력되어 키가 무시됩니다. 예를 들어 command를 commnd로 오타를 내면 파드는 생성되지만 의도한 명령줄을 사용하지 않게 돼요.
가장 먼저 할 일은 파드를 삭제하고 --validate 옵션으로 다시 만드는 거예요. 예를 들어 kubectl apply --validate -f mypod.yaml을 실행해보세요. command를 commnd로 오타를 냈다면 다음과 같은 오류가 납니다:
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가 오작동하지 않는지 확인하세요.
자세한 내용은 문제 해결 문서를 방문해도 좋아요.