1. 개요
시리즈 마지막 편이다. 뭔가 안 될 때 처음에는 아무 명령이나 두드리게 된다. 순서를 정해 두면 훨씬 빠르다. 1편에서 쿠버네티스를 “원하는 상태와 현재 상태의 차이를 메우는 시스템” 이라고 했다. 진단도 같다. 원하는 상태는 무엇이고, 현재 상태는 무엇이고, 그 차이를 메우는 쪽이 무엇에 막혔는지 순서대로 묻는다.
2. 핵심 내용
2-1. 기본 순서
kubectl get pods -o wide # 1. 상태와 어느 노드인지
kubectl describe pod <이름> # 2. 상세와 이벤트
kubectl logs <이름> # 3. 앱 로그
kubectl logs <이름> --previous # 직전에 죽은 컨테이너의 로그
kubectl get events --sort-by=.lastTimestamp # 4. 네임스페이스 전체 이벤트get 은 어디가 이상한지, describe 는 왜 그런지 힌트를, logs 는 앱 자신의 말을 준다. 재시작을 반복하는 컨테이너는 현재 로그가 텅 비어 있는 일이 많아서 --previous 가 진짜 단서다. 컨테이너가 여럿이면 -c 컨테이너이름 을 붙인다.
2-2. 증상별로 볼 곳
| 증상 | 의미 | 먼저 볼 곳 |
|---|---|---|
| Pending | 노드에 배정이 안 됨 | describe 의 FailedScheduling. 리소스 부족, 셀렉터, taint(7편) 또는 PVC 미바인딩 |
| ImagePullBackOff | 이미지를 못 받음 | 이미지 이름·태그 오타, 레지스트리 인증(pull secret) |
| CrashLoopBackOff | 뜨자마자 죽고 재시작 반복 | logs --previous, 종료 코드, 프로브 설정(2편) |
| OOMKilled | 메모리 limit 초과 | describe 의 Last State, limit 와 실제 사용량 |
| Running 인데 Ready 0/1 | readiness 실패 | 프로브 경로, describe 의 Readiness probe failed |
| 연결이 안 됨 | 대상이 비었을 가능성 | Service 셀렉터와 EndpointSlice(4편) |
CrashLoopBackOff 는 원인이 아니라 “죽고 다시 뜨는 걸 반복하며 대기 시간이 늘어나는 상태” 의 이름이다. 원인은 로그와 종료 코드에 있다.
2-3. 이벤트는 과거의 기록이다
describe 하단의 Events 와 get events 는 그 시점에 일어난 일의 기록이다. 지금의 상태가 아니다. 예를 들어 어제 Warning Unhealthy: Readiness probe failed 가 남아 있어도 지금 Pod 는 정상일 수 있다. 이벤트는 일정 시간(보통 1시간) 뒤에 사라지기도 해서 없다고 문제가 없는 것도 아니다.
그래서 Warning 을 보고 “지금 이게 문제다” 라고 단정하지 않는다. 리소스에 직접 묻는다.
kubectl get pod <이름> -o yaml여기서 status 를 읽는다.
status.phase: 큰 단계.status.conditions: PodScheduled, Initialized, ContainersReady, Ready 의 현재 참·거짓과 이유.status.containerStatuses[*].state: 지금 Running, Waiting, Terminated 중 무엇인지.lastState.terminated: 직전 종료의reason(OOMKilled 등),exitCode.restartCount: 재시작 횟수. 늘고 있는지 다시 확인해 본다.
이벤트가 “무슨 일이 있었나” 라면 status 는 “지금 어떤가” 다. 둘을 함께 봐야 한다. 새 Pod 가 뜬 직후 몇 초간 연결이 거부되는 경우가 있다. 그때의 Warning 만 보고 앱 문제로 몰기 쉬운데, 네트워크 정책의 반영 지연일 수 있다는 사례는 NetworkPolicy default-deny 의 정확한 의미론에 적었다.
2-4. 어디서 실수하나
- 재시작한 컨테이너의 현재 로그만 보고 비어 있다며 넘어간다.
--previous를 쓴다. - 오래된 Warning 이벤트를 현재 장애의 원인으로 확정한다.
- 잘못된 네임스페이스를 보고 있다.
-n이나-A를 확인한다. - Pod 만 보고 Deployment 나 ReplicaSet 을 안 본다. 롤아웃이 왜 멈췄는지는
kubectl rollout status와describe deployment에 있다.
3. 마무리
요약
- 진단 순서는 get, describe, logs(—previous), events 이고, 증상별로 볼 곳이 다르다.
- CrashLoopBackOff 는 원인이 아니라 상태 이름이며, 원인은 이전 로그와 종료 코드에 있다.
- 이벤트는 과거의 기록이므로 Warning 만으로 현재 상태를 단정하지 않고
-o yaml의 status 에 직접 묻는다.- 결국 원하는 상태와 현재 상태의 차이를 찾고, 그 차이를 메우는 컨트롤러가 무엇에 막혔는지 묻는 일이다.
이것으로 쿠버네티스 기초 8편을 마친다. 선언과 조정 루프라는 한 문장에서 시작해 Pod, Deployment, Service, Gateway, 설정과 볼륨, 리소스, 진단까지 왔다. 이 뒤의 개념들도 대부분 같은 원리 위에 쌓여 있다.