Static Pods

wu·2026년 5월 15일

CKA

목록 보기
3/8
post-thumbnail

CKA 스케줄링 섹션 중 Static Pod를 kind 환경에서 직접 실습했다. 개념을 잡고, docker exec로 컨트롤 플레인 컨테이너 안에 들어가서 manifest를 생성하고 수정하는 것까지 다뤘다. 실습하면서 CrashLoopBackOff, ImagePullBackOff 오류를 직접 마주치고 원인을 파악해서 해결했다.

Static Pod란?

일반 파드는 API 서버 → 스케줄러 → kubelet 순서로 실행된다. 반면 Static Pod는 kubelet이 특정 디렉토리를 직접 감시하다가 yaml 파일이 생기면 API 서버 없이 바로 실행하는 파드다.

/etc/kubernetes/manifests/   ← kubelet이 감시하는 경로
├── kube-apiserver.yaml
├── etcd.yaml
├── kube-scheduler.yaml
└── kube-controller-manager.yaml

존재 이유는 부트스트랩 문제 때문이다. kube-apiserver 자체를 파드로 띄우려면 API 서버가 필요한데, 아직 API 서버가 없다. 이 닭-달걀 문제를 Static Pod로 해결한다. 클러스터 초기화 시 manifests 디렉토리에 yaml이 복사되면 kubelet이
감지해서 컨트롤 플레인을 띄운다.

kubelet은 파드가 아니라 systemd가 관리하는 OS 레벨 프로세스다. 쿠버네티스 컴포넌트 중 유일하게 쿠버네티스 바깥에 있고, 컨트롤 플레인 포함 모든 노드에 설치된다.

클러스터 확인

kubectl get nodes
NAME                 STATUS   ROLES           AGE     VERSION
kind-control-plane   Ready    control-plane   2m42s   v1.35.0
kind-worker          Ready    <none>          2m28s   v1.35.0
kind-worker2         Ready    <none>          2m28s   v1.35.0

kind 환경에서 컨트롤 플레인 접속

kind는 노드가 Docker 컨테이너로 실행된다. 처음에 SSH로 접속하려다 실패했다.

ssh 172.18.0.3
# ^C (안됨)

kind 노드는 SSH가 아니라 docker exec로 접속해야 한다.

docker ps
# kind-control-plane, kind-worker, kind-worker2 컨테이너 확인

docker exec -it kind-control-plane bash

staticPodPath 확인

컨테이너 안에서 kubelet 설정을 확인한다.

cat /var/lib/kubelet/config.yaml | grep staticPodPath
# staticPodPath: /etc/kubernetes/manifests

ls /etc/kubernetes/manifests
# etcd.yaml  kube-apiserver.yaml  kube-controller-manager.yaml  kube-scheduler.yaml

컨트롤 플레인 컴포넌트 4개가 전부 Static Pod로 떠있는 걸 확인할 수 있다.

Static Pod 생성 — 첫 번째 실수

처음에 로컬 터미널에서 경로를 그대로 입력했다.

# 로컬에서 실행 → 실패
kubectl run web-static --image=nginx:1.27 --dry-run=client -o yaml \
  > /etc/kubernetes/manifests/web-static.yaml
# zsh: no such file or directory: /etc/kubernetes/manifests/web-static.yaml

로컬 macOS에는 /etc/kubernetes/manifests/가 없다. 컨테이너 안에서 실행해야 한다.

docker exec -it kind-control-plane bash

# 컨테이너 안에서
kubectl run web-static --image=nginx:1.27 --dry-run=client -o yaml \
  > /etc/kubernetes/manifests/web-static.yaml

참고로 컨테이너 안에는 k alias가 없다.

k get pods
# bash: k: command not found
# kubectl을 풀네임으로 써야 함

파일을 넣으면 kubelet이 자동 감지해서 바로 파드가 뜬다.

kubectl get pods -w
# NAME                            READY   STATUS              RESTARTS   AGE
# web-static-kind-control-plane   0/1     ContainerCreating   0          34s
# web-static-kind-control-plane   1/1     Running             0          42s

busybox Static Pod — CrashLoopBackOff

kubectl run log-agent --image=busybox --dry-run=client -o yaml \
  > /etc/kubernetes/manifests/log-agent.yaml

kubectl get pods
# NAME                           READY   STATUS             RESTARTS
# log-agent-kind-control-plane   0/1     CrashLoopBackOff   1 (5s ago)

describe로 원인을 확인한다.

kubectl describe pods log-agent-kind-control-plane
# State:     Terminated
#   Reason:  Completed
#   Exit Code: 0
# Events:
#   Warning  BackOff  kubelet  Back-off restarting failed container log-agent

Exit Code가 0이고 즉시 종료됐다. busybox는 명령어를 지정하지 않으면 기본으로 sh를 실행하는데, 입력받을 터미널이 없으니 바로 종료된다. 파드가 종료되면 kubelet이 재시작하고, 또 종료되는 걸 반복하다가 재시작 간격을 점점 늘리는 게 CrashLoopBackOff다.

sleep을 추가해서 프로세스가 살아있게 한다.

kubectl run log-agent --image=busybox --dry-run=client -o yaml \
  -- sleep 3600 > /etc/kubernetes/manifests/log-agent.yaml

kubectl get pods -w
# log-agent-kind-control-plane   0/1   Pending   0   1s
# log-agent-kind-control-plane   1/1   Running   0   3s

Static Pod 이미지 수정 — 에디터가 없다

manifest 파일의 이미지를 busybox:1.36으로 바꾸려고 에디터를 시도했는데 전부 없었다.

vim /etc/kubernetes/manifests/log-agent.yaml
# bash: vim: command not found
vi /etc/kubernetes/manifests/log-agent.yaml
# bash: vi: command not found
nano /etc/kubernetes/manifests/log-agent.yaml
# bash: nano: command not found

sed로 파일을 직접 수정한다.

sed -i 's/image: busybox/image: busybox:1.36/' \
  /etc/kubernetes/manifests/log-agent.yaml

파일만 수정하면 kubelet이 자동 감지해서 파드를 재시작한다. kubectl apply 없이도 된다.

ImagePullBackOff 트러블슈팅

잘못된 이미지명으로 Static Pod를 만들어서 트러블슈팅을 연습했다.

kubectl run web-static --image=nginxxx --dry-run=client -o yaml \
  > /etc/kubernetes/manifests/web-static.yaml

kubectl get pods -w
# web-static-kind-control-plane   0/1   ImagePullBackOff   0   30s
# web-static-kind-control-plane   0/1   ErrImagePull       0   31s

describe로 원인을 확인한다.

kubectl describe pods web-static-kind-control-plane
# Events:
#   Warning  Failed  kubelet  Failed to pull image "nginxxx":
#             failed to resolve reference "docker.io/library/nginxxx:latest":
#             pull access denied, repository does not exist

존재하지 않는 이미지라는 걸 확인하고 sed로 수정한다.

sed -i 's/image: nginxxx/image: nginx/' \
  /etc/kubernetes/manifests/web-static.yaml

kubectl get pods -w
# web-static-kind-control-plane   0/1   Terminating        0   2m36s
# web-static-kind-control-plane   0/1   ContainerCreating  0   5s
# web-static-kind-control-plane   1/1   Running            0   57s

구분일반 파드Static Pod
관리 주체API 서버 + kubeletkubelet 단독
설정 방법kubectl applymanifest 파일 복사
수정 방법kubectl edit / apply파일 직접 수정 (sed 등)
삭제 방법kubectl delete파일 삭제
주 용도일반 워크로드컨트롤 플레인 부트스트랩

Practice Questions

Q1. nginx:1.27 이미지로 web-static Static Pod를 controlplane 노드에 생성하라.
→ staticPodPath 확인 후 --dry-run=client -o yaml로 manifest 생성, manifests 디렉토리에 저장

Q2. log-agent Static Pod의 이미지를 busybox에서 busybox:1.36으로 변경하라.
→ 에디터 없는 환경에서는 sed -i 's/old/new/' manifest.yaml 활용

Q3. CrashLoopBackOff 상태의 Static Pod를 트러블슈팅하여 Running 상태로 만들어라.
kubectl describe의 Events 섹션에서 원인 파악 (잘못된 이미지 or 즉시 종료되는 이미지)


참조

0개의 댓글