올바른 워크로드 리소스 선택하기

KubernetesBeginner
지금 연습하기

소개

CKAD 시험에서는 매니페스트를 작성하기 전에 올바른 Kubernetes 워크로드 리소스를 선택하는 능력을 자주 요구합니다. Pod 는 실행 가능한 가장 작은 단위이며, Deployment 는 장기 실행 애플리케이션의 복제본을 유지하고, Job 은 작업이 완료될 때까지 실행하며, CronJob 은 예약된 Job 템플릿을 저장합니다.

이번 실습에서는 정의를 단순히 암기하는 대신, 실제 동작을 관찰하며 이러한 리소스들을 비교해 봅니다. 독립형 Pod 는 삭제 후 다시 생성되지 않지만, Deployment 는 Pod 를 자동으로 복구하고, Job 은 작업을 완료한 뒤 성공 여부를 기록하며, CronJob 은 반복 작업을 위한 예약 정보를 저장한다는 점을 직접 확인하게 됩니다.

워크로드 비교를 위한 네임스페이스 준비

이 단계에서는 워크로드 리소스를 비교하기 위한 깨끗한 네임스페이스를 준비합니다.

/home/labex/project 디렉토리에서 시작합니다. 워크로드 동작을 비교하면서 이 디렉토리에 작은 매니페스트 파일들을 생성할 것입니다.

mkdir -p /home/labex/project
cd /home/labex/project

Kubernetes API 서버에 접근 가능한지 확인합니다. VM 이 막 시작되어 노드가 아직 준비되지 않았다면, 몇 초 기다린 후 명령어를 다시 실행하세요.

kubectl get nodes --request-timeout=5s

예상 출력:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

워크로드는 Pod 를 생성하므로, 클러스터 네트워킹 Pod 가 준비될 때까지 기다립니다.

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

예상 출력:

pod/calico-node-... condition met

ckad-prep-workloads라는 이름의 네임스페이스를 생성합니다.

kubectl create namespace ckad-prep-workloads

이 네임스페이스를 현재 컨텍스트의 기본 네임스페이스로 설정합니다.

kubectl config set-context --current --namespace=ckad-prep-workloads

현재 네임스페이스를 확인합니다.

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

예상 출력:

ckad-prep-workloads

Pod 와 Deployment 비교

이 단계에서는 독립형 Pod 와 Deployment 를 각각 삭제해 보고, Kubernetes 가 어떻게 반응하는지 관찰하며 두 리소스를 비교합니다.

독립형 Pod 는 아주 작은 작업이나 검사를 위해 직접 관리되는 런타임 단위가 필요할 때 유용합니다. Deployment 는 ReplicaSet 을 소유하고 요청된 수만큼의 Pod 를 항상 실행 상태로 유지하므로 장기 실행 애플리케이션에 더 적합합니다.

독립형 Pod 매니페스트를 생성합니다. 컨테이너가 대기 상태를 유지하여 Pod 가 충분히 오래 실행되도록 합니다. terminationGracePeriodSeconds: 0 설정은 나중에 Pod 를 삭제할 때 실습을 빠르게 진행하기 위함입니다.

cat > standalone-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: standalone-task
  labels:
    app: standalone-task
    workload.labex.io/intent: direct-pod
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: sleeper
    image: busybox:1.36
    command: ["/bin/sh", "-c", "sleep 3600"]
EOF

Deployment 매니페스트를 생성합니다. 이 Deployment 는 Kubernetes 에 managed-worker Pod 하나를 계속 실행하도록 요청하며, Pod 템플릿에도 동일한 빠른 종료 설정을 적용합니다.

cat > managed-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: managed-worker
  labels:
    workload.labex.io/intent: long-running
spec:
  replicas: 1
  selector:
    matchLabels:
      app: managed-worker
  template:
    metadata:
      labels:
        app: managed-worker
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: sleeper
        image: busybox:1.36
        command: ["/bin/sh", "-c", "sleep 3600"]
EOF

두 매니페스트를 적용합니다.

kubectl apply -f standalone-pod.yaml
kubectl apply -f managed-deployment.yaml

예상 출력:

pod/standalone-task created
deployment.apps/managed-worker created

두 워크로드가 모두 준비될 때까지 기다립니다.

kubectl wait --for=condition=Ready pod/standalone-task --timeout=120s
kubectl wait --for=condition=Available deployment/managed-worker --timeout=120s

예상 출력:

pod/standalone-task condition met
deployment.apps/managed-worker condition met

현재 Deployment 의 Pod 이름을 가져온 뒤, 독립형 Pod 와 Deployment 가 관리하는 Pod 를 모두 삭제합니다.

managed_pod="$(kubectl get pods -l app=managed-worker -o 'jsonpath={.items[0].metadata.name}')"
kubectl delete pod standalone-task "$managed_pod"

예상 출력:

pod "standalone-task" deleted
pod "managed-worker-..." deleted

Deployment 가 다시 사용 가능해질 때까지 기다립니다.

kubectl wait --for=condition=Available deployment/managed-worker --timeout=120s

예상 출력:

deployment.apps/managed-worker condition met

Pod 목록을 확인합니다. 독립형 Pod 는 사라졌지만, 새로운 managed-worker Pod 가 생성되어 있을 것입니다.

kubectl get pods

예상 출력에는 managed-worker Pod 는 포함되지만 standalone-task는 포함되지 않습니다.

NAME                              READY   STATUS    RESTARTS   AGE
managed-worker-...                1/1     Running   0          ...

작업 완료를 위한 Job 선택

이 단계에서는 계속 실행되는 것이 아니라 성공적으로 완료되어야 하는 작업을 위해 Job 을 선택하는 방법을 알아봅니다.

Deployment 는 "애플리케이션을 계속 실행 상태로 유지"하는 것이 목표일 때 적합합니다. 반면 Job 은 "작업이 완료될 때까지 실행"하는 것이 목표일 때 더 적합합니다. 이것이 바로 마이그레이션, 배치 처리, 일회성 유지보수 명령어가 보통 Job 으로 구현되는 이유입니다.

schema-migration이라는 이름의 Job 을 생성합니다.

kubectl create job schema-migration --image=busybox:1.36 -- /bin/sh -c 'echo migration-start; echo migration-complete'

예상 출력:

job.batch/schema-migration created

Job 이 Complete 상태에 도달할 때까지 기다립니다.

kubectl wait --for=condition=Complete job/schema-migration --timeout=120s

예상 출력:

job.batch/schema-migration condition met

Job 요약을 확인합니다. COMPLETIONS가 1/1로 표시되어야 하며, 이는 작업이 한 번 성공적으로 수행되었음을 의미합니다.

kubectl get job schema-migration

예상 출력:

NAME               STATUS     COMPLETIONS   DURATION   AGE
schema-migration   Complete   1/1           ...        ...

Job 로그를 확인합니다.

kubectl logs job/schema-migration

예상 출력:

migration-start
migration-complete

반복 작업을 위한 CronJob 선택

이 단계에서는 일정에 따라 실행되어야 하는 작업을 위해 CronJob 을 선택하는 방법을 알아봅니다.

CronJob 은 예약된 Job 템플릿입니다. 작업이 한 번 완료되는 것이 아니라 나중에 반복되어야 할 때 올바른 선택입니다. 이 실습에서는 예측 가능한 결과를 위해 CronJob 을 일시 중단 (suspend) 상태로 생성합니다. 이렇게 하면 시간 경계를 기다리지 않고도 일정과 템플릿을 검사할 수 있습니다.

cleanup-cronjob.yaml 파일을 생성합니다.

cat > cleanup-cronjob.yaml <<'EOF'
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cleanup-schedule
  labels:
    workload.labex.io/intent: recurring-task
spec:
  schedule: "*/5 * * * *"
  suspend: true
  successfulJobsHistoryLimit: 1
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: cleanup
            image: busybox:1.36
            command:
            - /bin/sh
            - -c
            - 'echo cleanup-ready'
EOF

매니페스트를 적용합니다.

kubectl apply -f cleanup-cronjob.yaml

예상 출력:

cronjob.batch/cleanup-schedule created

CronJob 요약을 확인합니다. 실습을 위해 예약된 Job 을 기다리지 않고 리소스 선택 방법을 배우기 위해 SUSPEND가 True로 설정되어 있습니다.

kubectl get cronjob cleanup-schedule

예상 출력:

NAME               SCHEDULE      TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cleanup-schedule   */5 * * * *   <none>     True      0        <none>          ...

오브젝트에서 직접 일정과 템플릿 이미지를 읽어옵니다.

kubectl get cronjob cleanup-schedule -o 'jsonpath={.spec.schedule}{" "}{.spec.suspend}{" "}{.spec.jobTemplate.spec.template.spec.containers[0].image}{"\n"}'

예상 출력:

*/5 * * * * true busybox:1.36

이번 실습에서 생성한 워크로드 리소스들을 나열합니다. 이 목록은 리소스 유형과 의도된 동작을 연결해 줍니다: 장기 실행 복제본을 위한 Deployment, 완료를 위한 Job, 반복을 위한 CronJob 입니다.

kubectl get deployment,job,cronjob

예상 출력:

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/managed-worker   1/1     1            1           ...

NAME                         STATUS     COMPLETIONS   DURATION   AGE
job.batch/schema-migration   Complete   1/1           ...        ...

NAME                               SCHEDULE      TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/cleanup-schedule     */5 * * * *   <none>     True      0        <none>          ...

요약

동작 방식을 통해 Kubernetes 워크로드 리소스들을 비교해 보았습니다. 독립형 Pod 는 삭제 후 다시 생성되지 않았고, Deployment 는 복제본을 유지하기 위해 Pod 를 자동으로 복구했으며, Job 은 작업을 성공적으로 완료했고, CronJob 은 반복적인 Job 템플릿을 저장했습니다. 이러한 관찰 결과는 CKAD 스타일의 매니페스트를 작성하기 전에 올바른 리소스를 선택하는 데 큰 도움이 될 것입니다.