Part 17: Troubleshooting - 장애 해결
Part 17: Troubleshooting - 장애 해결
Part 17: Troubleshooting
Troubleshooting 접근법
체계적인 문제 해결 단계
- 증상 파악: 무엇이 작동하지 않는가?
- 범위 좁히기: Application, Control Plane, Worker Node, Network?
- 로그 확인: 에러 메시지 수집
- 설정 검증: YAML, 인증서, 권한 등
- 테스트: 변경 후 검증
- 문서화: 해결 과정 기록
핵심 디버깅 명령어
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 리소스 상태 확인
kubectl get <resource> -o wide
kubectl describe <resource> <name>
# 로그 확인
kubectl logs <pod-name>
kubectl logs <pod-name> -c <container-name>
kubectl logs <pod-name> --previous
# 이벤트 확인 (시간순 정렬)
kubectl get events --sort-by='.metadata.creationTimestamp'
kubectl get events -n <namespace> --sort-by='.lastTimestamp'
# 상세 출력
kubectl get <resource> -o yaml
kubectl get <resource> -o json
# 임시 디버그 Pod
kubectl run debug --image=busybox -it --rm --restart=Never -- sh
# Pod 내부 접속
kubectl exec -it <pod-name> -- /bin/bash
kubectl exec -it <pod-name> -c <container-name> -- /bin/sh
# Port Forward로 직접 접근
kubectl port-forward <pod-name> 8080:80
# 리소스 편집
kubectl edit <resource> <name>
Application Failure
Pod가 시작하지 않는 경우
시나리오 1: ImagePullBackOff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 증상
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# nginx-deployment-xxx 0/1 ImagePullBackOff 0 2m
# 진단
kubectl describe pod nginx-deployment-xxx
# 에러 메시지 예:
# Events:
# Type Reason Age From Message
# ---- ------ ---- ---- -------
# Normal Scheduled 2m default-scheduler Successfully assigned default/nginx-deployment-xxx to node01
# Normal Pulling 1m (x4 over 2m) kubelet Pulling image "nginx:typo"
# Warning Failed 1m (x4 over 2m) kubelet Failed to pull image "nginx:typo": rpc error: code = NotFound desc = failed to pull and unpack image "docker.io/library/nginx:typo": failed to resolve reference "docker.io/library/nginx:typo": docker.io/library/nginx:typo: not found
# Warning Failed 1m (x4 over 2m) kubelet Error: ErrImagePull
# Normal BackOff 1m (x6 over 2m) kubelet Back-off pulling image "nginx:typo"
# Warning Failed 1m (x6 over 2m) kubelet Error: ImagePullBackOff
# 해결
# 1. 이미지 이름 확인
# 2. 태그 확인
# 3. Private registry인 경우 imagePullSecrets 설정
kubectl edit deployment nginx-deployment
# image: nginx:typo → nginx:latest
# imagePullSecrets 생성 (Private Registry)
kubectl create secret docker-registry regcred \
--docker-server=myregistry.com \
--docker-username=user \
--docker-password=pass \
--docker-email=email@example.com
# Deployment에 추가
spec:
template:
spec:
imagePullSecrets:
- name: regcred
시나리오 2: CrashLoopBackOff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 증상
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# app-xxx 0/1 CrashLoopBackOff 5 (2m ago) 10m
# 진단
kubectl logs app-xxx
kubectl logs app-xxx --previous # 이전 컨테이너 로그
# 일반적인 원인:
# - 애플리케이션 코드 오류
# - 설정 오류 (ConfigMap, Secret)
# - 필요한 의존성 누락
# - 리소스 부족
# 추가 디버깅
kubectl describe pod app-xxx
# Events 확인:
# Warning BackOff 2m (x10 over 5m) kubelet Back-off restarting failed container
# 해결
# 1. 로그에서 에러 확인
# 2. ConfigMap/Secret 확인
kubectl get configmap
kubectl describe configmap app-config
# 3. 리소스 요구사항 확인
kubectl describe pod app-xxx | grep -A 5 "Limits:"
# 4. 라이브니스/리디니스 프로브 조정
kubectl edit deployment app
# livenessProbe:
# initialDelaySeconds: 30 # 증가
# periodSeconds: 10
시나리오 3: Pending
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 증상
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# app-xxx 0/1 Pending 0 5m
# 진단
kubectl describe pod app-xxx
# 원인 1: 리소스 부족
# Events:
# Warning FailedScheduling 2m default-scheduler 0/3 nodes are available: 3 Insufficient cpu.
# 해결: 리소스 요구사항 줄이기 또는 노드 추가
kubectl edit deployment app
# resources:
# requests:
# cpu: 100m # 1000m → 100m로 감소
# 원인 2: PVC Pending
kubectl get pvc
# NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
# data-pvc Pending standard 5m
kubectl describe pvc data-pvc
# 해결: StorageClass 확인 및 생성
kubectl get storageclass
kubectl describe storageclass standard
# 원인 3: Node Selector/Affinity 불일치
kubectl describe pod app-xxx
# Node-Selectors: disktype=ssd
# Events:
# Warning FailedScheduling 0/3 nodes are available: 3 node(s) didn't match node selector.
# 해결: 노드에 레이블 추가 또는 selector 제거
kubectl label node node01 disktype=ssd
시나리오 4: Init Container 실패
1
2
3
4
5
6
7
8
9
10
11
# 증상
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# app-xxx 0/1 Init:CrashLoopBackOff 3 5m
# 진단
kubectl describe pod app-xxx
kubectl logs app-xxx -c init-container-name
# 해결
# Init Container의 로그를 확인하고 문제 수정
Service 연결 문제
시나리오: Service로 접근 불가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 1. Service 확인
kubectl get svc
kubectl describe svc my-service
# 2. Endpoints 확인 (가장 중요)
kubectl get endpoints my-service
# 정상:
# NAME ENDPOINTS AGE
# my-service 10.244.1.5:80,10.244.2.6:80 5m
# 문제:
# NAME ENDPOINTS AGE
# my-service <none> 5m
# 원인: Selector가 Pod Label과 불일치
kubectl get pods --show-labels
# NAME READY STATUS LABELS
# app-xxx 1/1 Running app=myapp,version=v1
kubectl get svc my-service -o yaml | grep -A 5 selector
# selector:
# app: wrong-label # 불일치
# 해결
kubectl edit svc my-service
# selector:
# app: myapp # 수정
# 검증
kubectl get endpoints my-service
# ENDPOINTS가 생성되었는지 확인
# 3. Port 확인
kubectl describe svc my-service
# Port: 80/TCP
# TargetPort: 8080/TCP
# Pod의 실제 포트 확인
kubectl get pod app-xxx -o yaml | grep -A 3 "ports:"
# ports:
# - containerPort: 80 # TargetPort와 일치해야 함
# 4. 네트워크 연결 테스트
kubectl run test --image=busybox -it --rm --restart=Never -- wget -O- my-service
# 5. DNS 확인
kubectl run test --image=busybox -it --rm --restart=Never -- nslookup my-service
ConfigMap/Secret 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# ConfigMap이 Pod에 마운트되지 않음
kubectl get pods
kubectl describe pod app-xxx
# Events:
# Warning FailedMount 1m kubelet MountVolume.SetUp failed for volume "config" : configmap "app-config" not found
# 해결: ConfigMap 생성 확인
kubectl get configmap
kubectl create configmap app-config --from-file=config.yaml
# Secret 권한 문제
kubectl get secret
kubectl describe secret my-secret
# Secret을 환경변수로 사용 시
kubectl logs app-xxx
# Error: SECRET_KEY not found
# Secret YAML 확인
kubectl get secret my-secret -o yaml
# data:
# password: cGFzc3dvcmQ= # base64 인코딩 확인
# 디코딩 확인
echo "cGFzc3dvcmQ=" | base64 -d
Application Failure 실습 과제
- ImagePullBackOff 상황 만들고 해결하기
- CrashLoopBackOff로 인한 장애 디버깅
- Service Endpoints가 없는 문제 해결
- ConfigMap 마운트 실패 시나리오 해결
Control Plane Failure
kube-apiserver 장애
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 증상: kubectl 명령이 작동하지 않음
kubectl get nodes
# The connection to the server localhost:8080 was refused
# 진단
# 1. API Server Pod 확인
kubectl get pods -n kube-system
# 작동하지 않으면 직접 확인
# Control Plane 노드에서
docker ps | grep kube-apiserver
crictl ps | grep kube-apiserver
# 2. API Server 로그 확인
# Static Pod로 실행되는 경우
tail -f /var/log/pods/kube-system_kube-apiserver-*/*/*.log
# 또는
journalctl -u kubelet | grep apiserver
# 3. Static Pod Manifest 확인
cat /etc/kubernetes/manifests/kube-apiserver.yaml
# 일반적인 오류:
# - 잘못된 인증서 경로
# - etcd 연결 실패
# - 포트 충돌
# 해결 예시: 인증서 경로 수정
vim /etc/kubernetes/manifests/kube-apiserver.yaml
# --client-ca-file=/etc/kubernetes/pki/ca.crt # 올바른 경로 확인
# kubelet이 자동으로 재시작
# 또는 수동 재시작
systemctl restart kubelet
# 4. API Server 접근 테스트
curl -k https://localhost:6443/version
# 5. kubeconfig 확인
cat ~/.kube/config
# server: https://controlplane:6443 # 올바른 주소 확인
etcd 장애
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 증상: 클러스터 상태 변경 불가, API Server 응답 느림
# 진단
# 1. etcd Pod 확인
kubectl get pods -n kube-system | grep etcd
# 2. etcd 로그 확인
kubectl logs -n kube-system etcd-controlplane
# 또는
journalctl -u etcd
# 3. etcd 멤버 상태 확인
ETCDCTL_API=3 etcdctl member list \
--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
# 4. etcd 상태 확인
ETCDCTL_API=3 etcdctl endpoint health \
--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
# 출력:
# https://127.0.0.1:2379 is healthy: successfully committed proposal: took = 2.345ms
# 5. etcd Manifest 확인
cat /etc/kubernetes/manifests/etcd.yaml
# 일반적인 오류:
# - 데이터 디렉토리 손상
# - 인증서 만료
# - 디스크 공간 부족
# - 권한 문제
# 해결 예시: 데이터 디렉토리 권한
ls -ld /var/lib/etcd
# drwx------ 3 root root 4096 Dec 13 12:00 /var/lib/etcd
chown -R etcd:etcd /var/lib/etcd # 필요시
# 디스크 공간 확인
df -h /var/lib/etcd
# 6. etcd 복구 (백업에서)
# Part 16 Backup and Restore 참조
kube-scheduler 장애
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 증상: Pod가 Pending 상태로 유지
# 진단
# 1. Scheduler Pod 확인
kubectl get pods -n kube-system | grep scheduler
# 2. Scheduler 로그
kubectl logs -n kube-system kube-scheduler-controlplane
# 일반적인 에러:
# - kubeconfig 경로 오류
# - API Server 연결 실패
# - 권한 부족
# 3. Scheduler Manifest 확인
cat /etc/kubernetes/manifests/kube-scheduler.yaml
# 4. Scheduler가 작동하는지 확인
kubectl get events | grep -i scheduled
# 해결 예시: kubeconfig 경로 수정
vim /etc/kubernetes/manifests/kube-scheduler.yaml
# --kubeconfig=/etc/kubernetes/scheduler.conf # 올바른 경로
# Pod 재생성 확인
kubectl get pods -n kube-system -w
kube-controller-manager 장애
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 증상: ReplicaSet이 Pod를 생성하지 않음, Deployment 롤아웃 실패
# 진단
# 1. Controller Manager Pod 확인
kubectl get pods -n kube-system | grep controller-manager
# 2. 로그 확인
kubectl logs -n kube-system kube-controller-manager-controlplane
# 일반적인 에러:
# - Service Account 권한 부족
# - API Server 연결 실패
# - 인증서 문제
# 3. Manifest 확인
cat /etc/kubernetes/manifests/kube-controller-manager.yaml
# 4. Controller가 작동하는지 테스트
kubectl scale deployment nginx --replicas=3
kubectl get pods -w
# 해결: 설정 수정 후 자동 재시작 대기
Control Plane Failure 실습 과제
- kube-apiserver manifest를 고의로 손상시키고 복구
- etcd 장애 시뮬레이션 및 복구
- scheduler 장애로 인한 Pod Pending 해결
- controller-manager 장애 디버깅
Worker Node Failure
Node NotReady 상태
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# 증상
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# node01 NotReady <none> 10d v1.28.0
# 진단
# 1. Node 상세 정보
kubectl describe node node01
# Conditions:
# Ready False Wed, 13 Dec 2023 12:00:00 +0000 Wed, 13 Dec 2023 11:55:00 +0000 KubeletNotReady kubelet is not ready: runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
# 2. 문제 원인별 해결
# 원인 1: kubelet이 실행되지 않음
# Node에 SSH 접속
ssh node01
systemctl status kubelet
# ● kubelet.service - kubelet: The Kubernetes Node Agent
# Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
# Active: inactive (dead)
# kubelet 시작
systemctl start kubelet
systemctl enable kubelet
# 로그 확인
journalctl -u kubelet -f
# 원인 2: kubelet 설정 오류
cat /var/lib/kubelet/config.yaml
# 일반적인 오류:
# - API Server 주소 잘못됨
# - 인증서 경로 오류
# - CNI 설정 오류
# API Server 주소 확인
grep server /etc/kubernetes/kubelet.conf
# server: https://controlplane:6443
# 인증서 확인
ls -l /var/lib/kubelet/pki/
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -text -noout
# 원인 3: 디스크/메모리 부족
df -h
free -m
# Disk Pressure 해결
# 불필요한 이미지 삭제
crictl images
crictl rmi <image-id>
# 로그 정리
journalctl --vacuum-time=2d
# 원인 4: Container Runtime 문제
systemctl status containerd
# 또는
systemctl status docker
systemctl restart containerd
# CRI 소켓 확인
crictl info
# 원인 5: CNI 플러그인 문제
ls /etc/cni/net.d/
cat /etc/cni/net.d/10-calico.conflist
# CNI 바이너리 확인
ls /opt/cni/bin/
# Calico/Flannel 등 CNI Pod 확인
kubectl get pods -n kube-system | grep -E "calico|flannel|weave"
kubelet 인증서 만료
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 증상: Node가 NotReady, kubelet 로그에 인증서 에러
# 진단
journalctl -u kubelet | grep -i certificate
# 에러 예:
# certificate has expired or is not yet valid
# 인증서 확인
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -text -noout | grep -A 2 Validity
# Validity
# Not Before: Dec 13 11:00:00 2022 GMT
# Not After : Dec 13 11:00:00 2023 GMT # 만료됨
# 해결
# 1. 인증서 자동 갱신 설정 확인
cat /var/lib/kubelet/config.yaml | grep rotateCertificates
# rotateCertificates: true
# 2. kubelet 재시작하여 인증서 갱신 트리거
systemctl restart kubelet
# 3. 수동 갱신 (필요시)
kubeadm certs renew all
# 4. kubelet.conf 재생성
kubeadm init phase kubeconfig kubelet
# 5. 검증
kubectl get nodes
리소스 고갈
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# CPU/Memory 압박
kubectl describe node node01
# Conditions:
# MemoryPressure True
# DiskPressure False
# 메모리 사용량 확인
kubectl top node node01
kubectl top pods --all-namespaces --sort-by=memory
# 해결
# 1. 리소스를 많이 사용하는 Pod 찾기
kubectl top pods -A --sort-by=memory | head -20
# 2. 불필요한 Pod 삭제
kubectl delete pod <pod-name> -n <namespace>
# 3. Resource Limits 적용
kubectl edit deployment <deployment-name>
# resources:
# limits:
# memory: "512Mi"
# requests:
# memory: "256Mi"
Worker Node Failure 실습 과제
- kubelet 중지 후 Node NotReady 상태 해결
- CNI 플러그인 문제 디버깅 및 복구
- 디스크 압박 시뮬레이션 및 해결
- kubelet 인증서 갱신
Network Troubleshooting
Pod 간 통신 불가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 시나리오: Pod A에서 Pod B로 ping 실패
# 1. 기본 연결 테스트
kubectl exec -it pod-a -- ping <pod-b-ip>
# 2. CNI 플러그인 확인
kubectl get pods -n kube-system | grep -E "calico|flannel|weave|cilium"
# CNI Pod 로그 확인
kubectl logs -n kube-system <cni-pod-name>
# 3. NetworkPolicy 확인
kubectl get networkpolicy -A
# NetworkPolicy가 있다면
kubectl describe networkpolicy <policy-name> -n <namespace>
# 4. Pod IP 확인
kubectl get pods -o wide
# 5. 라우팅 테스트
kubectl exec -it pod-a -- traceroute <pod-b-ip>
# 6. iptables 규칙 확인 (Node에서)
ssh node01
iptables -L -n -v -t nat | grep <pod-ip>
# 해결 예시: NetworkPolicy 수정
kubectl edit networkpolicy deny-all
# 모든 Ingress 허용
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- {} # 모든 소스 허용
DNS 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# 증상: Service 이름으로 접근 불가
# 1. DNS 테스트
kubectl run test --image=busybox -it --rm --restart=Never -- nslookup kubernetes.default
# 정상:
# Server: 10.96.0.10
# Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
# Name: kubernetes.default
# Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local
# 에러:
# Server: 10.96.0.10
# Address 1: 10.96.0.10
# nslookup: can't resolve 'kubernetes.default'
# 2. CoreDNS Pod 확인
kubectl get pods -n kube-system -l k8s-app=kube-dns
# NAME READY STATUS RESTARTS AGE
# coredns-74ff55c5b-abc12 1/1 Running 0 10d
# coredns-74ff55c5b-def34 1/1 Running 0 10d
# 3. CoreDNS 로그
kubectl logs -n kube-system -l k8s-app=kube-dns
# 4. CoreDNS ConfigMap 확인
kubectl get configmap -n kube-system coredns -o yaml
# apiVersion: v1
# kind: ConfigMap
# metadata:
# name: coredns
# namespace: kube-system
# data:
# Corefile: |
# .:53 {
# errors
# health {
# lameduck 5s
# }
# ready
# kubernetes cluster.local in-addr.arpa ip6.arpa {
# pods insecure
# fallthrough in-addr.arpa ip6.arpa
# ttl 30
# }
# prometheus :9153
# forward . /etc/resolv.conf {
# max_concurrent 1000
# }
# cache 30
# loop
# reload
# loadbalance
# }
# 5. kube-dns Service 확인
kubectl get svc -n kube-system kube-dns
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 10d
# 6. Pod의 DNS 설정 확인
kubectl exec -it test-pod -- cat /etc/resolv.conf
# nameserver 10.96.0.10
# search default.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5
# 해결 예시: CoreDNS 재시작
kubectl rollout restart deployment coredns -n kube-system
# DNS 캐시 플러시 (Pod 재생성)
kubectl delete pod <pod-name>
Service 접근 불가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 1. Service 확인
kubectl get svc my-service
kubectl describe svc my-service
# 2. Endpoints 확인 (핵심)
kubectl get endpoints my-service
# 문제: Endpoints가 없음
# 원인: Selector가 Pod Label과 불일치
# 3. Selector 검증
kubectl get svc my-service -o yaml | grep -A 5 selector
# selector:
# app: myapp
kubectl get pods --show-labels | grep myapp
# 4. TargetPort 검증
kubectl get svc my-service -o yaml | grep targetPort
# targetPort: 8080
kubectl get pod <pod-name> -o yaml | grep containerPort
# containerPort: 80 # 불일치
# 해결
kubectl edit svc my-service
# targetPort: 80 # 수정
# 5. kube-proxy 확인
kubectl get pods -n kube-system | grep kube-proxy
kubectl logs -n kube-system <kube-proxy-pod>
# 6. iptables 규칙 확인
ssh node01
iptables-save | grep my-service
Ingress 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. Ingress Controller 확인
kubectl get pods -n ingress-nginx
# 2. Ingress 리소스 확인
kubectl get ingress
kubectl describe ingress my-ingress
# 3. Ingress Controller 로그
kubectl logs -n ingress-nginx <ingress-controller-pod>
# 4. Backend Service 확인
kubectl get svc my-service
kubectl get endpoints my-service
# 5. Host 헤더 테스트
curl -H "Host: myapp.example.com" http://<ingress-ip>/
# 6. TLS 인증서 확인
kubectl get secret my-tls-secret -o yaml
kubectl describe ingress my-ingress | grep -A 5 TLS
Network Troubleshooting 실습 과제
- NetworkPolicy로 Pod 간 통신 차단하고 해결
- CoreDNS 장애 시뮬레이션 및 복구
- Service Endpoints 불일치 문제 디버깅
- Ingress 라우팅 문제 해결
고급 디버깅 기법
JSON PATH 활용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 모든 Pod 이름 추출
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
# 특정 필드만 추출
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n'
# 조건부 필터 (Running 상태인 Pod만)
kubectl get pods -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}'
# 복합 출력 (이름과 IP)
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}'
# Node의 CPU/Memory 용량
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.capacity.cpu}{"\t"}{.status.capacity.memory}{"\n"}{end}'
# PVC의 StorageClass
kubectl get pvc -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.storageClassName}{"\n"}{end}'
# 정렬 (PV를 용량순으로)
kubectl get pv --sort-by=.spec.capacity.storage
# Custom Columns
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName,IP:.status.podIP
임시 디버그 컨테이너
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Ephemeral Container (Kubernetes 1.23+)
kubectl debug -it <pod-name> --image=busybox --target=<container-name>
# 새로운 디버그 Pod 생성
kubectl run debug --image=nicolaka/netshoot -it --rm --restart=Never -- /bin/bash
# 안에서 네트워크 도구 사용
# ping, curl, nslookup, traceroute, tcpdump 등
# 특정 Node에서 디버그
kubectl debug node/node01 -it --image=ubuntu
# Node의 파일시스템은 /host에 마운트됨
chroot /host
이벤트 분석
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 시간순 정렬
kubectl get events --sort-by='.lastTimestamp'
# 특정 네임스페이스
kubectl get events -n kube-system --sort-by='.lastTimestamp'
# Warning만 필터
kubectl get events --field-selector type=Warning
# 특정 리소스 관련 이벤트
kubectl get events --field-selector involvedObject.name=my-pod
# 실시간 모니터링
kubectl get events -w
# 이벤트를 시간대별로 그룹화
kubectl get events --sort-by='.lastTimestamp' -o custom-columns=TIME:.lastTimestamp,TYPE:.type,REASON:.reason,MESSAGE:.message
리소스 사용량 모니터링
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Metrics Server 설치 확인
kubectl get deployment metrics-server -n kube-system
# Node 리소스 사용량
kubectl top nodes
# Pod 리소스 사용량
kubectl top pods -A --sort-by=cpu
kubectl top pods -A --sort-by=memory
# 특정 Pod의 컨테이너별 리소스
kubectl top pod <pod-name> --containers
# 실시간 모니터링 (watch)
watch -n 1 kubectl top pods
로그 고급 활용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 이전 컨테이너 로그 (재시작된 경우)
kubectl logs <pod-name> --previous
# 여러 컨테이너 중 특정 컨테이너
kubectl logs <pod-name> -c <container-name>
# 마지막 N줄만
kubectl logs <pod-name> --tail=100
# 특정 시간 이후 로그
kubectl logs <pod-name> --since=1h
kubectl logs <pod-name> --since=2023-12-13T10:00:00Z
# 실시간 로그 스트리밍
kubectl logs <pod-name> -f
# 여러 Pod 로그 동시 보기 (Label Selector)
kubectl logs -l app=nginx --all-containers=true
# 타임스탬프 포함
kubectl logs <pod-name> --timestamps
# 로그 저장
kubectl logs <pod-name> > pod.log
Kubectl Plugins
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# kubectl-debug 플러그인 설치
kubectl krew install debug
# 사용
kubectl debug <pod-name>
# kubectl-tree (리소스 계층 구조)
kubectl krew install tree
kubectl tree deployment nginx
# kubectl-whoami (현재 인증 정보)
kubectl krew install whoami
kubectl whoami
# kubectl-stern (다중 Pod 로그)
kubectl stern <pod-query>
실전 Troubleshooting 시나리오
시나리오 1: 애플리케이션이 갑자기 응답하지 않음
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1단계: Pod 상태 확인
kubectl get pods -l app=myapp
# 2단계: 최근 이벤트
kubectl get events --sort-by='.lastTimestamp' | head -20
# 3단계: Pod 로그
kubectl logs -l app=myapp --tail=100
# 4단계: Service/Endpoints
kubectl get svc myapp-service
kubectl get endpoints myapp-service
# 5단계: 리소스 사용량
kubectl top pods -l app=myapp
# 6단계: 네트워크 테스트
kubectl run test --image=busybox -it --rm -- wget -O- myapp-service
# 해결 사례:
# - OOMKilled: Memory Limit 증가
# - CrashLoopBackOff: 애플리케이션 로그 확인
# - Endpoints 없음: Selector 수정
시나리오 2: 클러스터 전체 성능 저하
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1단계: Node 상태
kubectl get nodes
kubectl top nodes
# 2단계: Control Plane 컴포넌트
kubectl get pods -n kube-system
kubectl top pods -n kube-system --sort-by=cpu
# 3단계: etcd 성능
ETCDCTL_API=3 etcdctl endpoint status --cluster -w table
# 4단계: API Server 부하
kubectl get --raw /metrics | grep apiserver_request_total
# 5단계: 리소스 고갈 Pod
kubectl top pods -A --sort-by=memory | head -20
# 해결 사례:
# - etcd 디스크 느림: SSD로 이전
# - API Server 과부하: Rate Limiting 조정
# - Memory Leak: Pod 재시작 및 코드 수정
시나리오 3: 특정 Node의 Pod만 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 1단계: Node 상세 정보
kubectl describe node node01
# 2단계: Node의 모든 Pod
kubectl get pods -A -o wide --field-selector spec.nodeName=node01
# 3단계: Node에 SSH 접속
ssh node01
# kubelet 상태
systemctl status kubelet
journalctl -u kubelet -f
# Container Runtime
systemctl status containerd
# 디스크/메모리
df -h
free -m
# 4단계: CNI 문제
ls /etc/cni/net.d/
ls /opt/cni/bin/
# 해결 사례:
# - Disk Pressure: 로그/이미지 정리
# - CNI 손상: CNI 재설치
# - kubelet 설정 오류: config.yaml 수정
This post is licensed under CC BY 4.0 by the author.