distroless 파드 디버깅, kubectl debug로 5초

상황
운영 중인 파드가 한 개 있다. 베이스 이미지는 gcr.io/distroless/static:nonroot. 셸은커녕 ls도 없다. 그런데 갑자기 이 파드만 외부 API 호출이 실패하기 시작한다. DNS 문제인지, 라우팅 문제인지, 인증서 문제인지 확인하고 싶다. 파드를 재시작하면 증상이 사라질 수도 있으니 살아있는 상태에서 보고 싶다. 자, 어떻게 할까?
이거 모르는 분 꽤 많더라. 어제 후배가 "프로덕션 파드에 들어가서 curl 좀 찍어보고 싶은데 distroless라서 kubectl exec가 안 먹힌다"라고 슬랙에 글 올린 거 보고 깜짝 놀랐다. kubectl debug가 GA 된 게 1.25 (2022년 후반) 인데, 2026년 지금까지도 의외로 안 쓰는 사람이 많은 것 같아서 짧게 정리한다.
한 줄로 끝난다
kubectl debug -it <pod-name> \
--image=nicolaka/netshoot \
--target=<container-name> \
--share-processes
--target을 주면 대상 컨테이너와 프로세스 네임스페이스를 공유한다. 그래서 디버그 컨테이너에서 ps -ef 치면 원래 앱 프로세스가 보인다. /proc/<pid>/root로 들어가면 distroless 컨테이너의 파일시스템도 그대로 볼 수 있다. 인증서 파일이 제대로 있는지, env가 어떻게 들어갔는지 다 보인다.
nicolaka/netshoot 이미지 안에는 curl, dig, nslookup, tcpdump, iperf, mtr 다 들어있다. 진짜 디버깅용 풀세트.
알아둘 점
운영에서 쓸 때 몇 가지 주의할 점이 있다.
한 번 추가한 ephemeral container는 파드를 지우기 전까지 제거할 수 없다. 그래서 디버깅 끝나면 파드 자체를 롤링으로 교체해 주는 게 깔끔하다. 그리고 kubectl debug 호출은 API 서버 audit log에 남는다. 누가 언제 어떤 파드에 디버그 컨테이너 붙였는지 추적된다는 뜻이다. 운영 시간에 거리낌 없이 쓰자.
RBAC도 챙겨야 한다. pods/ephemeralcontainers 서브리소스에 patch 권한이 별도로 필요하다. SRE 그룹에만 줘두면 무난하다.
- apiGroups: [""]
resources: ["pods/ephemeralcontainers"]
verbs: ["patch"]
노드 단위로도 된다
파드가 아니라 노드를 들여다보고 싶을 때도 같은 명령으로 된다.
kubectl debug node/<node-name> -it --image=ubuntu
호스트 파일시스템이 /host로 마운트돼서 들어간다. kubelet 로그를 직접 보거나 journalctl 칠 때 유용하다. SSH 안 열려있는 클러스터에서 한 번씩 쓰게 된다.
마무리
다른 방법 쓰시는 분도 많을 거다. nsenter로 직접 들어가는 사람도 봤고, sidecar로 디버그 컨테이너 미리 박아두는 팀도 있다. 다만 distroless 비중이 점점 늘어나는 분위기에서 kubectl debug 한 줄로 끝나는 건 알아두면 손해는 없다. 혹시 사내에서 쓰기 애매한 이유 있으신 분 있으면 댓글로 알려주세요. 저도 궁금합니다.