Podからセルフヒーリングまで
한국어 원문으로 표시합니다.
목표
파드 하나를 손으로 띄우는 것에서 시작해 Deployment·Job·CronJob·DaemonSet 을 각각 만들어 보고, 소유 관계(ownerReferences)를 따라가 본 뒤, 파드를 일부러 지워 셀프힐링이 실제로 도는 것을 삭제 전후 목록으로 증명합니다.
왜 중요한가
현장에서 파드를 직접 만드는 일은 거의 없습니다. 그런데도 파드를 이해해야 하는 이유는, 모든 워크로드 컨트롤러가 결국 파드 템플릿을 들고 있는 껍데기이기 때문입니다. Deployment 의 문제는 대부분 파드 템플릿의 문제입니다.
컨트롤러를 고르는 기준은 하나로 요약됩니다 — 이 프로세스는 스스로 끝나는가. 끝나지 않는 서비스에 Job 을 쓰면 영원히 완료되지 않고, 끝나는 배치에 Deployment 를 쓰면 종료할 때마다 재시작되어 CrashLoopBackOff 처럼 보입니다. 실제로 신입이 가장 자주 만드는 사고입니다.
마지막 단계가 이 실습의 핵심입니다. "파드를 지우면 다시 생긴다"는 말은 다들 알지만, 돌아온 파드가 같은 파드가 아니라는 것을 눈으로 본 사람은 적습니다. 이름이 달라진다는 사실 하나가 "파드 이름에 의존하지 마라", "상태를 파드 안에 두지 마라" 같은 원칙 전부의 근거입니다.
단계
- 네임스페이스
kcna-work를 만들고 그 안에 이미지nginx:1.27-alpine인 파드hello를 만들어 Running 까지 갑니다. - 같은 네임스페이스에 Deployment
web을 만듭니다. 이미지는nginx:1.27-alpine, replicas 는 3, 파드 템플릿 라벨은app=web입니다. web의 replicas 를 5 로 늘리고 5 개가 모두 Ready 가 될 때까지 기다립니다.web이 만든 ReplicaSet 의 이름을/root/kcna-work/rs-name.txt에 한 줄로 저장하고,web의 파드 하나를 골라 그 파드의metadata.ownerReferences[0].kind값을/root/kcna-work/owner.txt에 한 줄로 저장합니다.- 같은 네임스페이스에 Job
report를 만듭니다 — 이미지busybox:1.36,completions는 3. 그리고 CronJobnightly를 만듭니다 — schedule 은 매일 03:00 (0 3 * * *). - 같은 네임스페이스에 DaemonSet
node-agent를 만듭니다. 이미지는busybox:1.36이고, 컨테이너가 바로 종료되지 않도록 오래 도는 명령을 주세요. - 셀프힐링을 증명합니다. (a)
web의 파드 이름 5 개를/root/kcna-work/before.txt에 저장하고, (b) 그중 하나를 지운 뒤 지운 이름을/root/kcna-work/deleted.txt에 한 줄로 저장하고, (c) 새 파드가 Ready 가 된 다음 파드 이름 5 개를/root/kcna-work/after.txt에 저장합니다.
참고
- 파드 이름만 뽑을 때는
kubectl get pods -n kcna-work -l app=web -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'가 편합니다. kubectl get rs -n kcna-work로 레플리카셋 이름을 확인하고,kubectl get rs <이름> -n kcna-work -o yaml로 ownerReferences 를 볼 수 있습니다.- DaemonSet 은
kubectl create서브커맨드가 없으므로 YAML 을 직접 작성해 apply 해야 합니다.spec.selector.matchLabels와spec.template.metadata.labels가 같아야 합니다. - 흔한 실수 1: 5단계 Job 의
restartPolicy를 비워 두는 것. 기본값Always는 Job 에서 거부됩니다. - 흔한 실수 2: 7단계에서 파드를 지운 직후 바로
after.txt를 받는 것. 새 파드가 아직 목록에 없어 5줄이 되지 않습니다.
첫 파드 띄우기
네임스페이스 kcna-work 를 만들고 그 안에 이미지 nginx:1.27-alpine 인 파드 hello 를 만들어 Running 까지 갑니다.
네임스페이스를 먼저 만들고 그 안에 파드를 만듭니다. kubectl run 으로 빠르게 만들거나 YAML 을 써도 됩니다. 파드가 Running 이 될 때까지 몇 초 걸릴 수 있으니 상태를 확인하고 채점하세요.
Deployment 로 파드 관리 맡기기
같은 네임스페이스에 Deployment web 을 만듭니다. 이미지는 nginx:1.27-alpine, replicas 는 3, 파드 템플릿 라벨은 app=web 입니다.
kubectl create deployment 는 파드 템플릿의 라벨을 자동으로 붙여 줍니다. 어떤 라벨이 붙었는지 -o yaml 로 한 번 확인해 보세요. 준비된 레플리카 수는 status 쪽에서 볼 수 있습니다.
레플리카 수 바꾸기
web 의 replicas 를 5 로 늘리고 5 개가 모두 Ready 가 될 때까지 기다립니다.
kubectl scale 로 한 줄에 끝낼 수도 있고 매니페스트를 고쳐 다시 apply 해도 됩니다. 둘 중 무엇이 기록에 남는 방식인지 생각해 보세요. 채점은 spec 과 status 를 모두 봅니다.
소유 관계 따라가기
web 이 만든 ReplicaSet 의 이름을 /root/kcna-work/rs-name.txt 에 한 줄로 저장하고, web 의 파드 하나를 골라 그 파드의 metadata.ownerReferences[0].kind 값을 /root/kcna-work/owner.txt 에 한 줄로 저장합니다.
네임스페이스의 레플리카셋 목록을 보면 이름 뒤에 해시가 붙어 있습니다. 그 오브젝트의 metadata.ownerReferences 를 -o jsonpath 나 -o yaml 로 열어 보면 누가 만들었는지 나옵니다. 파드 쪽도 같은 필드를 갖고 있습니다.
끝나는 일: Job 과 CronJob
같은 네임스페이스에 Job report 를 만듭니다 — 이미지 busybox:1.36, completions 는 3. 그리고 CronJob nightly 를 만듭니다 — schedule 은 매일 03:00 (0 3 * * *).
Job 의 파드 템플릿은 restartPolicy 에 Always 를 쓸 수 없습니다. 왜 그런지 생각해 보면 값이 정해집니다. CronJob 의 schedule 은 표준 cron 표기 다섯 자리입니다.
노드마다 하나: DaemonSet
같은 네임스페이스에 DaemonSet node-agent 를 만듭니다. 이미지는 busybox:1.36 이고, 컨테이너가 바로 종료되지 않도록 오래 도는 명령을 주세요.
DaemonSet 매니페스트에는 replicas 필드가 없습니다. 개수를 정하는 주체가 사람이 아니기 때문입니다. kubectl create 로는 만들 수 없으니 YAML 을 직접 써야 하고, selector 와 template.metadata.labels 가 일치해야 합니다.
파드를 지워 셀프힐링 증명하기
셀프힐링을 증명합니다. (a) web 의 파드 이름 5 개를 /root/kcna-work/before.txt 에 저장하고, (b) 그중 하나를 지운 뒤 지운 이름을 /root/kcna-work/deleted.txt 에 한 줄로 저장하고, (c) 새 파드가 Ready 가 된 다음 파드 이름 5 개를 /root/kcna-work/after.txt 에 저장합니다.
삭제 전 목록, 지운 이름, 삭제 후 목록을 각각 파일로 남겨야 채점이 성립합니다. 삭제 후 목록은 컨트롤러가 새 파드를 만든 뒤에 받아야 5줄이 나옵니다. 돌아온 파드의 이름이 지운 것과 같은지 다른지 직접 확인해 보세요.