kubectl debug --target, 이거 모르는 분 꽤 많더라
오늘 알게 된 것도 아니고, 알고는 있는데 막상 새벽에 장애 터지면 까먹는 옵션 하나를 정리해두려고 한다. kubectl debug --target. 같이 일하는 주니어한테 알려주니까 "어 이게 되네요?" 하길래.
흔한 상황
운영 중인 Pod에서 네트워크가 이상하다. DNS는 되는데 특정 외부 IP로만 connect timeout. 컨테이너는 distroless라서 kubectl exec로 들어가도 쉘이 없다. 사이드카로 디버깅 컨테이너 박아서 재배포? 새벽 두 시에 그건 좀 그렇다.
이럴 때 쓰는 게 ephemeral container, 그리고 kubectl debug다. K8s 1.25에서 GA된 후로 죽 안정적이다. 근데 의외로 --target 옵션을 안 쓰고 그냥 띄워서 "어 왜 안 보이지" 하는 경우가 많다.
핵심은 --target
kubectl debug -it pod/my-app-abc123 \
--image=nicolaka/netshoot \
--target=my-app
--target=<container-name>. 이게 빠지면 process namespace 공유가 안 된다. 같은 Pod 안이라 네트워크 namespace는 공유되니까 curl이나 dig는 되는데, ps로 앱 프로세스를 보거나 /proc/<pid>/net/tcp를 까보거나 strace를 붙이는 건 안 된다.
--target을 주면 그 컨테이너랑 PID namespace까지 같이 묶여서, netshoot 컨테이너에서 ps -ef 치면 앱 프로세스가 그대로 보인다. 이게 결정적인 차이다. 한 번은 conntrack 테이블이 꽉 차서 SYN_SENT가 쌓이는 걸 추적해야 했는데, --target 없이는 앱 입장에서 본 소켓 상태를 못 보니까 한참 헤맸다.
추가로 알아두면 좋은 것:
- ephemeral container는 한 번 붙이면 못 뗀다. Pod 삭제될 때까지 따라다닌다. 운영 Pod에 너무 자주 붙이면 spec이 지저분해진다.
--profile=sysadmin을 같이 주면 capability를 다 풀어준다.tcpdump떠야 할 때 필수.- 노드 자체를 디버깅하려면
kubectl debug node/<node-name> -it --image=...가 따로 있다. 호스트의/를/host에 마운트해줘서, hostPath로 chroot 들어갈 일이 줄었다.
자주 쓰는 한 줄
팀 위키에 박아둔 거. 그냥 alias로 들고 다닌다.
alias kdebug='kubectl debug -it --image=nicolaka/netshoot --profile=sysadmin --target'
# 사용: kdebug pod/foo -- bash ... 까먹지 말고 컨테이너 이름은 별도 인자
뭐, 진짜 한 줄로 만들기는 어려운데 옵션 조합 외우기 귀찮아서 그냥 함수로 만들어 놓는 사람도 봤다. 어쨌든 --target은 까먹지 말자.
혹시 다른 디버깅 패턴 잘 쓰시는 거 있으면 댓글 남겨주세요. 특히 distroless 환경에서 어떻게 해결하시는지 궁금하다.