285. Troubleshooting - Section Introduction
Kubernetes 트러블슈팅의 기본 원칙
“문제 층위를 위에서 아래로 좁혀 내려간다”
Kubernetes는 여러 층이 겹친 구조이기 때문에, 증상만 보면 어디가 원인인지 헷갈림.
[사용자 요청] → [Ingress] → [Service] → [Pod] → [Container] → [Application]
↓
[Node (kubelet)]
↓
[Control Plane (API Server)]
원칙:
- 증상 확인 (뭐가 안 되나?) → Pod 안 뜸? Service 응답 없음? API Server 다운?
- 위에서 아래로 내려가며 확인 —
describe→logs→ 시스템 로그 Events섹션을 먼저 본다 (kubectl describe의 핵심)- 이벤트는 시간 순 정렬 (
--sort-by=.lastTimestamp)
분류:
- 애플리케이션 장애 (Application Failure)
- 컨트롤 플레인 장애 (Control Plane Failure)
- 워커 노드 장애 (Worker Node Failure)
- 네트워크 트러블슈팅
286-288. Application Failure
공식문서: Debug Pods / Debug Services
트러블슈팅 접근 순서
- 사용자 접근 불가
- Service 확인 — Endpoints 연결됐는지
- Pod 상태 확인 — Running? Restarts?
- Pod 로그 확인 —
kubectl logs - Pod 상세 확인 —
kubectl describe pod - Deployment 확인 — 레플리카, 이미지, 셀렉터
Service → Pod 연결 확인
# Service 확인
kubectl get svc
kubectl describe svc web-service
# Endpoints 항목이 있어야 함 → 없으면 selector 불일치
# Pod 라벨 vs Service selector 비교
kubectl get pod --show-labels
kubectl get svc web-service -o yaml | grep selector -A5
# Service에서 직접 curl 테스트
kubectl run tmp --image=busybox --rm -it -- wget -qO- http://web-service:80Pod 상태별 트러블슈팅
| 상태 | 원인 | 확인 방법 |
|---|---|---|
Pending | 스케줄링 실패 (리소스 부족, NodeSelector 불일치) | kubectl describe pod → Events |
CrashLoopBackOff | 컨테이너 반복 재시작 | kubectl logs --previous |
ImagePullBackOff | 이미지 없음 / 인증 실패 | 이미지 이름/태그 확인, imagePullSecrets |
OOMKilled | 메모리 초과 | resources.limits 확인/조정 |
Error | 컨테이너 실행 오류 | kubectl logs 확인 |
# Pod 로그 확인
kubectl logs <pod-name>
kubectl logs <pod-name> -c <container-name> # 멀티 컨테이너
kubectl logs <pod-name> --previous # 재시작 전 로그
# Pod 상세 확인 (Events 섹션이 핵심)
kubectl describe pod <pod-name>
# Pod 내부 접속
kubectl exec -it <pod-name> -- /bin/sh
# 환경 변수 확인
kubectl exec <pod-name> -- env
# ConfigMap / Secret 마운트 확인
kubectl exec <pod-name> -- cat /etc/config/my-key일반적인 실수 패턴
# 1. Service selector와 Pod label 불일치
# Service: selector: app=web
# Pod: labels: app=webapp ← 다름!
# 2. 잘못된 Service 포트 매핑
# Service: port: 80, targetPort: 8080
# 컨테이너: containerPort: 80 ← targetPort가 틀림
# 3. 잘못된 ConfigMap/Secret 참조
kubectl get configmap
kubectl describe configmap <name>289-291. Control Plane Failure
컨트롤 플레인 컴포넌트 확인
# 노드 상태 확인
kubectl get nodes
# 컨트롤 플레인 파드 상태 (kubeadm 환경)
kubectl get pods -n kube-system
# Static Pod 매니페스트 확인
ls /etc/kubernetes/manifests/
cat /etc/kubernetes/manifests/kube-apiserver.yaml
cat /etc/kubernetes/manifests/kube-controller-manager.yaml
cat /etc/kubernetes/manifests/kube-scheduler.yaml
cat /etc/kubernetes/manifests/etcd.yaml컴포넌트별 로그 확인
# kubeadm 환경 (파드로 실행)
kubectl logs kube-apiserver-master -n kube-system
kubectl logs kube-controller-manager-master -n kube-system
kubectl logs kube-scheduler-master -n kube-system
kubectl logs etcd-master -n kube-system
# 바이너리로 실행되는 환경 (서비스로 실행)
sudo journalctl -u kube-apiserver -f
sudo journalctl -u kube-controller-manager -f
sudo journalctl -u kube-scheduler -f
# 컨테이너 런타임으로 직접 확인
sudo crictl ps | grep -E "apiserver|controller|scheduler|etcd"
sudo crictl logs <container-id>kube-apiserver 장애 시
# API Server가 죽으면 kubectl 자체가 안 됨
# → 마스터 노드에 직접 SSH 접속하여 확인
# Static Pod 매니페스트 문제 확인
sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml
# 인증서 만료 확인
sudo openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout | grep "Not After"
# etcd 연결 확인 (--etcd-servers 옵션)
sudo grep etcd /etc/kubernetes/manifests/kube-apiserver.yamletcd 상태 확인
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
endpoint health
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member list292-294. Worker Node Failure
공식문서: Troubleshooting Nodes
워커 노드 상태 확인
# 노드 상태 확인
kubectl get nodes
kubectl describe node <node-name>
# → Conditions 섹션 확인 (Ready / MemoryPressure / DiskPressure / PIDPressure)Node Conditions
| Condition | True 의미 | 원인 |
|---|---|---|
Ready | 노드 정상 | - |
MemoryPressure | 메모리 부족 | 메모리 확보 필요 |
DiskPressure | 디스크 부족 | 디스크 정리 필요 |
PIDPressure | 프로세스 과다 | 프로세스 정리 필요 |
Unknown | 마스터와 통신 끊김 | kubelet/네트워크 확인 |
워커 노드 SSH 접속 후 확인
# kubelet 상태 확인 (가장 중요!)
sudo systemctl status kubelet
sudo journalctl -u kubelet -f
sudo journalctl -u kubelet --since "10 minutes ago"
# kubelet 재시작
sudo systemctl restart kubelet
sudo systemctl enable kubelet
# kubelet 설정 파일 확인
cat /var/lib/kubelet/config.yaml
sudo cat /etc/kubernetes/kubelet.conf # kubeconfig
# 인증서 만료 확인
sudo openssl x509 -in /var/lib/kubelet/pki/kubelet.crt -text -noout | grep "Not After"
# 컨테이너 런타임 상태
sudo systemctl status containerd
sudo crictl ps
sudo crictl info
# 시스템 리소스 확인
free -h # 메모리
df -h # 디스크
top # CPU/프로세스노드 강제 복구
# 노드 드레인 (워크로드 이동)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
# 노드 유지보수 모드 해제
kubectl uncordon <node-name>
# 노드를 스케줄링 불가로 표시 (drain 없이)
kubectl cordon <node-name>295-296. Network Troubleshooting
CNI 플러그인 확인
# CNI 설정 파일 확인
ls /etc/cni/net.d/
cat /etc/cni/net.d/10-flannel.conflist # Flannel 예시
# CNI 바이너리 확인
ls /opt/cni/bin/
# CNI 플러그인 파드 상태 (DaemonSet)
kubectl get pods -n kube-system | grep -E "weave|calico|flannel|cilium"
kubectl logs -n kube-system <cni-pod-name>kube-proxy 확인
# kube-proxy 파드 상태
kubectl get pods -n kube-system | grep kube-proxy
kubectl logs -n kube-system <kube-proxy-pod>
# kube-proxy ConfigMap 확인
kubectl get configmap kube-proxy -n kube-system -o yaml
# iptables 규칙 확인
sudo iptables -t nat -L KUBE-SERVICES -n | head -20
sudo iptables -t nat -L | grep <service-ip>CoreDNS 확인
# CoreDNS 파드 상태
kubectl get pods -n kube-system | grep coredns
kubectl logs -n kube-system -l k8s-app=kube-dns
# CoreDNS ConfigMap 확인
kubectl get configmap coredns -n kube-system -o yaml
# DNS 해석 테스트
kubectl run dns-test --image=busybox --rm -it -- nslookup kubernetes
kubectl run dns-test --image=busybox --rm -it -- nslookup <service-name>.<namespace>Pod 간 통신 테스트
# Pod IP 확인
kubectl get pods -o wide
# Pod에서 직접 curl
kubectl exec <pod-a> -- curl http://<pod-b-ip>:8080
kubectl exec <pod-a> -- wget -qO- http://<service-name>:<port>
# 네트워크 정책 확인
kubectl get networkpolicy
kubectl describe networkpolicy <name>
# 특정 포트 연결 확인
kubectl exec <pod-name> -- nc -zv <target-ip> <port>트러블슈팅 종합 체크리스트
- 문제 발생 →
kubectl이 동작하는가?- No → API Server 확인:
/etc/kubernetes/manifests/,journalctl -u kube-apiserver - Yes → 다음 단계
- No → API Server 확인:
- 노드 상태? (
kubectl get nodes)- NotReady → kubelet 확인:
systemctl status kubelet,journalctl -u kubelet - Ready → 다음 단계
- NotReady → kubelet 확인:
- Pod 상태? (
kubectl get pods)- CrashLoop / Error →
kubectl logs,kubectl describe pod - Running → 다음 단계
- CrashLoop / Error →
- 서비스 접근 불가?
- Service / Endpoint 확인 → kube-proxy / CNI 확인 → DNS 확인