증상으로 부품 좁히기
| 증상 | 의심 |
|---|---|
kubectl 전부 connection refused | kube-apiserver(또는 그 아래 etcd) |
| 새 파드가 Events 없이 Pending | kube-scheduler |
| 레플리카가 안 맞음, 디플로이먼트를 만들어도 RS·파드가 안 생김, 노드 상태가 안 바뀜 | kube-controller-manager |
특정 노드 NotReady | 그 노드의 kubelet(또는 런타임, CNI) |
| 서비스로 접속 안 됨(엔드포인트는 정상) | kube-proxy, CNI, NetworkPolicy |
| 이름 해석 안 됨 | CoreDNS(DNS 강의) |
컨트롤 플레인 고치기
kubectl get pods -n kube-system # 살아 있다면 여기서 상태 확인
kubectl logs -n kube-system kube-scheduler-controlplane
kubectl describe pod -n kube-system kube-scheduler-controlplane
API 서버가 죽어 kubectl 이 안 되면 노드에서 런타임에 직접:
crictl ps -a | grep -E "apiserver|etcd|scheduler|controller" # Exited 인 것, ATTEMPT 가 큰 것
crictl logs <컨테이너ID> # 왜 죽었는지
ls /var/log/pods/ # 파드별 로그 파일도 있다
원인은 거의 항상 /etc/kubernetes/manifests/*.yaml 의 한 줄입니다.
| 로그 단서 | 흔한 원인 |
|---|---|
no such file or directory | 인증서·kubeconfig 경로 오타(scheduler.conff) |
unknown flag: --… | 플래그 이름 오타 |
connection refused …:2380 | etcd 주소·포트 오류(클라이언트 포트는 2379) |
executable file not found | command 첫 줄(바이너리 이름) 오타 |
| 컨테이너 자체가 없음 | YAML 문법 오류 → kubelet 이 파일을 못 읽음(journalctl -u kubelet 에 나옴) |
고치고 저장하면 kubelet 이 알아서 다시 띄웁니다. 1분쯤 기다렸다가 kubectl get pods -n kube-system 으로 확인합니다.
매니페스트를 백업하고 고치세요.
cp kube-apiserver.yaml /root/kube-apiserver.yaml.bak— 단, 백업을 같은 폴더에 두면 안 됩니다. kubelet 이 그것도 static pod 로 띄우려 합니다.
NotReady 노드
kubectl get nodes
kubectl describe node node01 | grep -A8 Conditions # "Kubelet stopped posting node status"
ssh node01
systemctl status kubelet # inactive? failed? activating(auto-restart)?
journalctl -u kubelet -n 30 --no-pager
| 발견 | 해결 |
|---|---|
inactive (dead) | systemctl enable --now kubelet (enable 까지 — 재부팅 대비) |
status=203/EXEC | 드롭인의 ExecStart 경로 오타 → 고치고 daemon-reload → restart |
unable to load client CA file … | /var/lib/kubelet/config.yaml 의 인증서 경로 오류 |
failed to load kubelet config file | config.yaml 문법 오류 |
container runtime is down | systemctl status containerd |
swap 관련 | swapoff -a |
kubelet 관련 파일 위치:
/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf ← 서비스 설정(ExecStart, 환경변수)
/var/lib/kubelet/config.yaml ← kubelet 설정(staticPodPath, clusterDNS …)
/var/lib/kubelet/kubeadm-flags.env ← kubeadm 이 넣은 추가 플래그
/etc/kubernetes/kubelet.conf ← API 서버 접속용 kubeconfig
드롭인 경로는 배포판·설치 방식에 따라
/etc/systemd/system/kubelet.service.d/일 수도 있습니다.systemctl status kubelet의 Drop-In: 줄이 실제 위치를 알려 줍니다.
노드 유지보수: cordon · drain · uncordon
kubectl cordon node02 # 새 파드만 금지
kubectl drain node02 --ignore-daemonsets # 금지 + 기존 파드 내보내기
kubectl uncordon node02 # 복구
drain 이 거부하는 경우와 옵션:
| 메시지 | 옵션 | 뜻 |
|---|---|---|
cannot delete DaemonSet-managed Pods | --ignore-daemonsets | DS 파드는 남겨 둔다(어차피 노드마다 있어야 함) |
cannot delete Pods that declare no controller | --force | 컨트롤러 없는 파드는 영영 사라진다 |
cannot delete Pods with local storage | --delete-emptydir-data | emptyDir 데이터가 지워진다 |
Cannot evict pod as it would violate the pod's disruption budget | (기다리거나 PDB 조정) | PodDisruptionBudget 이 막음 |
static pod(mirror pod)는 drain 대상이 아닙니다.