Skip to content
Published on

Kubernetes CKAD 자격증 실전 연습 문제 (55문제 + 실기 시뮬레이션 10개)

Authors

CKAD 자격증 개요

CKAD(Certified Kubernetes Application Developer)는 CNCF에서 주관하는 Kubernetes 애플리케이션 개발자를 위한 실기 중심 자격증입니다.

항목내용
시험 시간120분
문제 수15-20문제 (실기형)
합격 기준66% 이상
시험 방식온라인 원격 감독
유효 기간3년
Kubernetes 버전최신 안정 버전

도메인별 출제 비율

도메인비율
Application Design & Build20%
Application Deployment20%
Application Observability & Maintenance15%
Application Environment, Configuration & Security25%
Services & Networking20%

개발자 관점 kubectl 치트시트

# ConfigMap 생성
kubectl create configmap app-config --from-literal=key=value
kubectl create configmap app-config --from-file=config.properties
kubectl create configmap app-config --from-env-file=.env

# Secret 생성
kubectl create secret generic db-secret --from-literal=password=mypassword
kubectl create secret docker-registry regcred \
  --docker-server=REGISTRY \
  --docker-username=USER \
  --docker-password=PASS

# 롤아웃 관리
kubectl rollout status deployment myapp
kubectl rollout history deployment myapp
kubectl rollout undo deployment myapp
kubectl rollout pause deployment myapp
kubectl rollout resume deployment myapp

# 리소스 제한
kubectl set resources deployment myapp --limits=cpu=200m,memory=512Mi
kubectl set resources deployment myapp --requests=cpu=100m,memory=256Mi

# 환경 변수 설정
kubectl set env deployment myapp ENV=production
kubectl set env deployment myapp --from=configmap/app-config

# 라벨 관리
kubectl label pod mypod env=production
kubectl label pod mypod env-   # 라벨 제거

# 임시 컨테이너 (디버깅)
kubectl debug -it POD_NAME --image=busybox --target=CONTAINER_NAME

# Helm 기본 명령어
helm repo add stable https://charts.helm.sh/stable
helm install myrelease stable/nginx
helm upgrade myrelease stable/nginx --set image.tag=latest
helm rollback myrelease 1
helm uninstall myrelease
helm list

# dry-run으로 YAML 생성
kubectl create deployment myapp --image=nginx --dry-run=client -o yaml > deploy.yaml
kubectl run mypod --image=nginx --dry-run=client -o yaml > pod.yaml

개념 이해 문제 (Q1 ~ Q55)

도메인 1: Application Design & Build

Q1. Sidecar 패턴과 Ambassador 패턴의 차이는?

A) Sidecar는 메인 컨테이너를 대체하고, Ambassador는 보조 기능을 제공한다 B) Sidecar는 메인 컨테이너의 기능을 확장(로깅, 모니터링)하고, Ambassador는 외부 서비스와의 통신을 프록시한다 C) 두 패턴은 동일하다 D) Ambassador는 Kubernetes 1.25에서 제거되었다

정답: B

설명: Sidecar 패턴은 메인 컨테이너와 함께 로그 수집, 모니터링, 보안 기능을 추가합니다. Ambassador 패턴은 메인 컨테이너가 외부 서비스와 통신할 때 중간 프록시 역할을 합니다. Adapter 패턴은 메인 컨테이너의 출력 형식을 변환합니다.

Q2. Init Container의 특징으로 올바른 것은?

A) 메인 컨테이너와 동시에 실행된다 B) 메인 컨테이너가 시작되기 전에 순서대로 실행되고, 완료 후 메인 컨테이너가 시작된다 C) 실패하면 Pod가 Running 상태를 유지한다 D) 무한정 실행된다

정답: B

설명: Init Container는 메인 컨테이너가 시작되기 전에 순서대로 실행됩니다. 모든 Init Container가 성공적으로 완료된 후에만 메인 컨테이너가 시작됩니다. Init Container가 실패하면 Pod의 restartPolicy에 따라 재시작됩니다. DB 마이그레이션, 설정 파일 준비 등에 활용됩니다.

Q3. Job에서 backoffLimit 필드의 역할은?

A) Job의 최대 실행 시간을 지정한다 B) Job 실패 시 재시도 횟수를 지정한다 C) 동시 실행 Pod 수를 제한한다 D) 완료된 Job을 자동으로 삭제한다

정답: B

설명: backoffLimit은 Job 실패 시 재시도하는 최대 횟수입니다. 기본값은 6입니다. 재시도 간격은 지수적으로 증가합니다(10초, 20초, 40초...). activeDeadlineSeconds는 Job의 최대 실행 시간을 제한합니다.

Q4. Dockerfile에서 멀티 스테이지 빌드의 장점은?

A) 빌드 속도를 높인다 B) 최종 이미지 크기를 줄이고 불필요한 빌드 도구를 제외할 수 있다 C) 캐싱을 비활성화한다 D) 여러 OS에서 동시에 빌드할 수 있다

정답: B

설명: 멀티 스테이지 빌드는 빌드 환경(컴파일러, 빌드 도구)과 실행 환경을 분리합니다. 첫 번째 스테이지에서 빌드 아티팩트를 생성하고, 두 번째 스테이지(경량 베이스 이미지)에서 아티팩트만 복사합니다. 이를 통해 이미지 크기를 대폭 줄일 수 있습니다.

Q5. CronJob의 concurrencyPolicy 옵션 중 Forbid의 동작은?

A) 이전 Job이 완료되지 않은 경우 새 Job을 동시에 실행한다 B) 이전 Job이 아직 실행 중이면 새 Job을 건너뛴다 C) 이전 Job을 강제 종료하고 새 Job을 시작한다 D) 모든 Job을 큐에 저장한다

정답: B

설명: concurrencyPolicy: Forbid는 이전 Job이 아직 실행 중일 때 새 Job 생성을 건너뜁니다. Allow(기본값)는 동시 실행을 허용합니다. Replace는 이전 실행 중인 Job을 종료하고 새 Job을 시작합니다.

Q6. 컨테이너 이미지의 레이어 캐싱을 최적화하기 위한 Dockerfile 작성 방법은?

A) 모든 RUN 명령을 하나로 합친다 B) 자주 변경되는 명령(COPY 소스 코드)을 Dockerfile 아래에 배치한다 C) FROM 명령을 여러 번 사용한다 D) LABEL 명령을 많이 사용한다

정답: B

설명: Docker 레이어 캐싱 최적화를 위해 자주 변경되지 않는 명령(패키지 설치 등)을 위에 배치하고, 자주 변경되는 명령(소스 코드 복사)을 아래에 배치합니다. 이렇게 하면 소스 코드 변경 시 패키지 레이어 캐시를 재사용할 수 있습니다.

Q7. Pod의 restartPolicy 옵션과 Job에서 사용해야 하는 값은?

A) Always - Job에서 권장 B) OnFailure 또는 Never - Job과 CronJob에서 사용 C) OnSuccess - Job에서만 사용 가능 D) Never - 모든 경우에 권장

정답: B

설명: Job과 CronJob의 Pod에는 OnFailure(실패 시 재시작) 또는 Never(재시작 없음)를 사용해야 합니다. Always는 Deployment, DaemonSet 등 장기 실행 워크로드에 사용합니다. Job Pod에 Always를 사용하면 Job이 완료되어도 Pod가 계속 재시작됩니다.

Q8. StatefulSet과 Deployment의 핵심 차이점은?

A) StatefulSet은 더 많은 레플리카를 지원한다 B) StatefulSet은 순서가 있는 Pod 이름, 안정적인 네트워크 ID, 개별 PVC를 제공한다 C) Deployment는 상태 저장 앱에 더 적합하다 D) StatefulSet은 롤링 업데이트를 지원하지 않는다

정답: B

설명: StatefulSet은 상태 저장 애플리케이션을 위해 설계되었습니다: 1) 예측 가능한 Pod 이름(app-0, app-1), 2) 안정적인 네트워크 ID(헤드리스 서비스 통해), 3) 각 Pod별 독립적인 PVC(volumeClaimTemplates), 4) 순서 있는 배포/업데이트/삭제. 데이터베이스, Kafka, ZooKeeper 등에 적합합니다.

도메인 2: Application Deployment

Q9. Deployment의 Recreate 전략과 RollingUpdate 전략의 차이는?

A) Recreate는 더 많은 리소스를 사용한다 B) Recreate는 기존 Pod를 모두 삭제 후 새 Pod를 생성하여 다운타임이 있고, RollingUpdate는 점진적으로 교체하여 다운타임이 없다 C) RollingUpdate는 대규모 클러스터에서만 가능하다 D) 둘 다 동일한 방식으로 동작한다

정답: B

설명: Recreate는 기존 ReplicaSet의 Pod를 모두 삭제한 후 새 Pod를 생성합니다. 다운타임이 발생하지만 이전/새 버전이 동시에 실행되지 않습니다. RollingUpdate는 점진적으로 Pod를 교체하여 서비스 중단 없이 배포합니다. maxSurge와 maxUnavailable로 속도를 조절합니다.

Q10. kubectl rollout pausekubectl rollout resume의 사용 목적은?

A) Pod를 일시 중지/재개한다 B) 롤아웃을 일시 중단하여 일부 Pod만 새 버전으로 실행한 후 검증하고, 문제없으면 재개하는 카나리 배포 방식 C) Deployment를 완전히 중지한다 D) 자동 스케일링을 일시 중지한다

정답: B

설명: kubectl rollout pause deployment는 진행 중인 롤아웃을 일시 중단합니다. 이를 통해 일부 Pod만 새 버전으로 교체된 상태에서 카나리 테스트를 수행할 수 있습니다. 문제없으면 kubectl rollout resume으로 나머지를 계속 업데이트합니다.

Q11. Helm chart의 values.yaml 파일의 역할은?

A) Helm 차트의 필수 구성 요소 목록 B) 차트 배포 시 사용되는 기본 설정값을 정의한다 C) Kubernetes 매니페스트 파일 D) Helm 저장소 인증 정보

정답: B

설명: values.yaml은 Helm 차트의 기본 설정값을 정의합니다. helm install이나 helm upgrade--set 또는 -f custom-values.yaml로 재정의할 수 있습니다. 템플릿 파일에서 {{ .Values.image.tag }}와 같이 참조합니다.

Q12. Kustomize에서 overlay와 base의 관계는?

A) overlay는 base와 동일한 파일이다 B) base는 공통 설정을, overlay는 환경별(dev/staging/prod) 변경사항을 정의한다 C) overlay는 base를 완전히 대체한다 D) Kustomize는 overlay를 지원하지 않는다

정답: B

설명: Kustomize에서 base는 공통 Kubernetes 리소스 정의를 포함합니다. overlay는 base를 참조하고 환경별(개발, 스테이징, 운영) 패치와 변경사항을 추가합니다. kubectl apply -k overlays/production/처럼 사용합니다. Helm 차트 없이도 멀티 환경 배포가 가능합니다.

Q13. kubectl set image 명령어로 특정 컨테이너 이미지만 업데이트하는 방법은?

A) kubectl set image deployment/myapp *=nginx:1.26 B) kubectl set image deployment/myapp nginx=nginx:1.26 C) kubectl update image deployment/myapp nginx:1.26 D) kubectl patch image deployment/myapp nginx=nginx:1.26

정답: B

설명: kubectl set image deployment/DEPLOY_NAME CONTAINER_NAME=IMAGE:TAG 형식으로 특정 컨테이너만 업데이트합니다. 예: kubectl set image deployment/myapp nginx=nginx:1.26. 여러 컨테이너를 동시에 업데이트하려면 공백으로 구분하여 나열합니다.

Q14. Deployment의 revisionHistoryLimit 필드의 기능은?

A) 보관할 롤아웃 히스토리(이전 ReplicaSet)의 수를 지정한다 B) 최대 Pod 수를 제한한다 C) 자동 롤백 횟수를 제한한다 D) 이전 버전 유지 기간을 시간으로 지정한다

정답: A

설명: revisionHistoryLimit은 Deployment가 보관할 이전 ReplicaSet의 수를 지정합니다. 기본값은 10입니다. 롤백에 사용 가능한 이전 버전 수와 직접 연관됩니다. 0으로 설정하면 이전 ReplicaSet을 바로 삭제합니다.

Q15. Helm 릴리스를 이전 버전으로 롤백하는 명령어는?

A) helm undo myrelease B) helm rollback myrelease REVISION C) helm revert myrelease D) helm restore myrelease

정답: B

설명: helm rollback myrelease REVISION_NUMBER로 특정 리비전으로 롤백합니다. helm history myrelease로 릴리스 히스토리와 리비전 번호를 확인할 수 있습니다. 리비전을 지정하지 않으면 가장 최근의 이전 버전으로 롤백됩니다.

Q16. Blue/Green 배포를 Kubernetes에서 구현하는 방법은?

A) Deployment의 Recreate 전략 사용 B) 두 개의 Deployment(blue/green)를 운영하고 Service의 selector를 전환하여 트래픽 전환 C) StatefulSet으로 구현 D) DaemonSet으로 구현

정답: B

설명: Blue/Green 배포: 1) blue Deployment(현재 운영)와 green Deployment(새 버전)를 함께 운영, 2) green Deployment 테스트 완료 후, Service의 selector를 blue에서 green으로 변경하여 즉시 트래픽 전환, 3) 문제없으면 blue 제거. 즉각적인 전환이 가능하고 롤백도 빠릅니다.

도메인 3: Application Observability & Maintenance

Q17. Liveness Probe 실패 시 Kubernetes의 동작은?

A) Pod를 삭제하고 재생성한다 B) 컨테이너를 재시작한다 C) Pod를 다른 노드로 이동한다 D) 알림을 보낸다

정답: B

설명: Liveness Probe가 실패하면 Kubernetes는 해당 컨테이너를 재시작합니다(Pod 전체가 아닌 컨테이너). 재시작 정책(restartPolicy)이 적용됩니다. failureThreshold번 연속 실패하면 재시작이 시작됩니다. 애플리케이션 데드락이나 무한 루프 감지에 사용됩니다.

Q18. Readiness Probe가 실패하면 어떻게 되는가?

A) 컨테이너가 재시작된다 B) Pod가 서비스의 엔드포인트에서 제거된다 C) Pod가 삭제된다 D) 새로운 Pod가 생성된다

정답: B

설명: Readiness Probe가 실패하면 해당 Pod가 Service의 엔드포인트에서 제거되어 트래픽을 받지 않게 됩니다. 컨테이너는 재시작되지 않습니다. Probe가 다시 통과하면 엔드포인트에 다시 추가됩니다. 배포 중 준비되지 않은 Pod에 트래픽이 가는 것을 방지합니다.

Q19. Startup Probe의 주요 용도는?

A) 컨테이너 초기화 시간이 오래 걸리는 레거시 앱에서 Liveness Probe 시작 전 애플리케이션이 준비될 때까지 대기 B) 컨테이너 시작 전 환경 변수 초기화 C) 컨테이너 종료 후 정리 작업 수행 D) 외부 의존성 상태 확인

정답: A

설명: Startup Probe는 시작 시간이 긴 애플리케이션에서 Liveness Probe가 너무 이르게 실패하는 것을 방지합니다. Startup Probe가 성공할 때까지 Liveness와 Readiness Probe가 활성화되지 않습니다. 기존 모놀리식 앱을 컨테이너화할 때 특히 유용합니다.

Q20. kubectl logs --since=1h의 의미는?

A) 최근 1시간 내의 로그만 표시한다 B) 1시간 전부터 현재까지의 로그를 표시한다 C) 로그 파일의 처음 1시간 분량을 표시한다 D) 로그를 1시간 동안 스트리밍한다

정답: B

설명: kubectl logs POD_NAME --since=1h는 지난 1시간 내의 로그만 표시합니다. --since-time=2024-01-01T00:00:00Z로 특정 시간 이후의 로그를 가져올 수도 있습니다. --tail=100은 마지막 100줄만 표시합니다.

Q21. kubectl top pod 명령어가 작동하기 위한 전제 조건은?

A) Prometheus가 설치되어 있어야 한다 B) Metrics Server가 클러스터에 설치되어 있어야 한다 C) Grafana가 설정되어 있어야 한다 D) kube-proxy가 IPVS 모드여야 한다

정답: B

설명: kubectl top podkubectl top node는 Kubernetes Metrics Server를 통해 CPU와 메모리 사용량을 가져옵니다. Metrics Server는 별도로 설치해야 합니다. Prometheus나 다른 모니터링 도구는 kubectl top 명령어에 영향을 주지 않습니다.

Q22. Ephemeral Container를 사용하는 목적은?

A) 임시 Pod를 생성한다 B) 이미 실행 중인 Pod에 디버깅 도구가 없을 때 임시 컨테이너를 추가하여 디버깅한다 C) Pod를 일시 중지한다 D) 리소스 사용량을 줄인다

정답: B

설명: Ephemeral Container는 distroless나 slim 이미지처럼 셸이나 디버깅 도구가 없는 컨테이너를 디버깅할 때 사용합니다. kubectl debug -it POD_NAME --image=busybox --target=CONTAINER로 실행 중인 Pod에 임시 컨테이너를 추가합니다. Kubernetes 1.23+에서 GA입니다.

Q23. 컨테이너의 Liveness Probe를 HTTP로 설정하는 방법은?

A) livenessProbe.tcpSocket 사용 B) livenessProbe.httpGet 사용 C) livenessProbe.exec 사용 D) livenessProbe.http 사용

정답: B

설명: HTTP Liveness Probe는 httpGet을 사용합니다. pathport를 지정하고, 응답 코드가 200-399이면 성공으로 간주합니다. tcpSocket은 TCP 연결 확인, exec는 명령어 실행 후 종료 코드 0 여부로 확인합니다.

도메인 4: Application Environment, Configuration & Security

Q24. ConfigMap을 환경 변수로 Pod에 주입하는 방법은?

A) spec.containers.env.valueFrom.configMapKeyRef 사용 B) spec.containers.configmap 사용 C) spec.volumes.configmap 사용 D) spec.env.configmap 사용

정답: A

설명: ConfigMap을 환경 변수로 주입하는 두 가지 방법: 1) 특정 키만 주입: env[].valueFrom.configMapKeyRef로 특정 키-값 참조, 2) 전체 ConfigMap 주입: envFrom[].configMapRef로 모든 키를 환경 변수로 주입. 볼륨 마운트는 파일로 사용할 때 적합합니다.

Q25. Kubernetes Secret이 etcd에 저장되는 방식은?

A) AES-256으로 암호화되어 저장된다 B) 기본적으로 base64 인코딩만 되어 저장되며, etcd 암호화 설정을 별도로 해야 암호화된다 C) SHA-256 해시로 저장된다 D) 완전히 암호화되어 저장된다

정답: B

설명: Kubernetes Secret은 기본적으로 base64 인코딩만 되어 etcd에 저장됩니다(암호화 아님). etcd 저장 시 암호화를 위해 kube-apiserver에 --encryption-provider-config를 설정해야 합니다. Secret을 RBAC로 접근 제어하고, etcd 암호화를 활성화하는 것이 보안 모범 사례입니다.

Q26. SecurityContext의 runAsNonRoot 설정의 효과는?

A) 컨테이너를 root 사용자로 실행한다 B) 컨테이너가 root(UID 0)로 실행되려고 하면 시작을 거부한다 C) 컨테이너의 모든 파일을 읽기 전용으로 만든다 D) 네트워크 권한을 제거한다

정답: B

설명: securityContext.runAsNonRoot: true는 컨테이너가 root(UID 0)로 실행되려고 할 경우 컨테이너 시작을 거부합니다. runAsUser: 1000과 함께 사용하면 특정 UID로 실행을 강제할 수 있습니다. 컨테이너 탈출 공격 시 피해를 최소화하는 보안 Best Practice입니다.

Q27. PodSecurityContext와 컨테이너 수준 SecurityContext의 차이는?

A) PodSecurityContext는 특정 컨테이너에만 적용된다 B) spec.securityContext는 Pod 내 모든 컨테이너에 적용되고, 컨테이너 수준 설정은 해당 컨테이너에만 적용되며 Pod 설정을 재정의한다 C) 두 설정은 동일하다 D) 컨테이너 수준 SecurityContext는 Kubernetes 1.24에서 제거되었다

정답: B

설명: spec.securityContext (Pod 수준)는 Pod의 모든 컨테이너에 적용됩니다(runAsUser, fsGroup, supplementalGroups 등). spec.containers[].securityContext (컨테이너 수준)는 해당 컨테이너에만 적용되며 Pod 수준 설정을 재정의합니다(capabilities, readOnlyRootFilesystem 등).

Q28. capabilities.drop: ["ALL"]의 효과는?

A) 컨테이너에 모든 Linux capabilities를 추가한다 B) 컨테이너에서 모든 Linux capabilities를 제거하여 최소 권한으로 실행한다 C) 컨테이너를 privileged 모드로 실행한다 D) 네트워크 접근을 차단한다

정답: B

설명: capabilities.drop: ["ALL"]은 컨테이너에서 모든 Linux capabilities를 제거합니다. 필요한 capabilities만 capabilities.add로 다시 추가하는 방식으로 최소 권한 원칙을 적용합니다. 예를 들어 웹 서버는 NET_BIND_SERVICE만 필요할 수 있습니다.

Q29. LimitRange의 역할은?

A) 클러스터 전체 리소스 사용량을 제한한다 B) 네임스페이스 내 개별 Pod/Container의 기본 및 최대 리소스 요청/제한을 설정한다 C) PVC 크기를 제한한다 D) 사용자당 Pod 수를 제한한다

정답: B

설명: LimitRange는 네임스페이스 내에서 개별 리소스(Pod, Container, PVC)의 기본값(default), 최솟값(min), 최댓값(max)을 설정합니다. requests/limits를 명시하지 않은 컨테이너에 자동으로 기본값이 적용됩니다. ResourceQuota는 네임스페이스 전체 합산을 제한합니다.

Q30. ResourceQuota를 사용하는 목적은?

A) 개별 Pod의 최대 CPU/메모리를 제한한다 B) 네임스페이스 전체에서 사용 가능한 리소스 합계를 제한한다 C) 노드의 리소스 사용량을 제한한다 D) 컨테이너의 네트워크 대역폭을 제한한다

정답: B

설명: ResourceQuota는 네임스페이스 전체에서 생성할 수 있는 리소스의 총량을 제한합니다. CPU, 메모리, Pod 수, PVC 수, LoadBalancer 서비스 수 등을 제한할 수 있습니다. 여러 팀이 클러스터를 공유할 때 특정 팀이 리소스를 독점하는 것을 방지합니다.

Q31. imagePullPolicy: IfNotPresent와 Always의 차이는?

A) IfNotPresent는 항상 이미지를 새로 받고, Always는 캐시를 사용한다 B) IfNotPresent는 로컬에 이미지가 없을 때만 받고, Always는 항상 레지스트리에서 최신 이미지를 받는다 C) 두 옵션은 동일하다 D) IfNotPresent는 latest 태그에서만 동작한다

정답: B

설명: IfNotPresent: 노드에 이미지가 없을 때만 레지스트리에서 가져옵니다. 이미지가 있으면 기존 것을 사용합니다. Always: 매번 레지스트리에서 최신 이미지를 확인하고 가져옵니다. latest 태그나 다이제스트 없이 태그를 사용하는 경우 Always를 권장합니다.

Q32. Pod에서 Secret을 환경 변수로 안전하게 사용하는 방법은?

A) spec.containers.env.value에 직접 값 입력 B) spec.containers.env.valueFrom.secretKeyRef 사용 C) spec.containers.args에 비밀 값 포함 D) ConfigMap에 Secret 값 포함

정답: B

설명: env[].valueFrom.secretKeyRef를 사용하여 Secret의 특정 키를 환경 변수로 주입합니다. envFrom[].secretRef로 Secret의 모든 키를 한 번에 주입할 수도 있습니다. Secret 값을 YAML에 직접 입력하거나 ConfigMap에 저장하는 것은 보안상 위험합니다.

Q33. ServiceAccount 토큰이 자동으로 마운트되는 경로는?

A) /etc/kubernetes/ B) /var/run/secrets/kubernetes.io/serviceaccount/ C) /home/app/.kube/ D) /tmp/secrets/

정답: B

설명: ServiceAccount 토큰은 기본적으로 /var/run/secrets/kubernetes.io/serviceaccount/ 경로에 자동 마운트됩니다. 이 경로에 token, ca.crt, namespace 파일이 있습니다. 자동 마운트가 필요없으면 automountServiceAccountToken: false로 비활성화합니다.

도메인 5: Services & Networking

Q34. Service의 selector와 Pod label이 일치하지 않으면 어떻게 되는가?

A) Service가 오류를 반환한다 B) Service의 엔드포인트가 비어 있어 트래픽이 전달되지 않는다 C) 모든 Pod에 트래픽이 전달된다 D) Service가 자동으로 삭제된다

정답: B

설명: Service selector가 Pod label과 일치하지 않으면 Service에 엔드포인트가 없게 됩니다. kubectl get endpoints SERVICE_NAME으로 확인 시 "none"이 표시됩니다. kubectl describe service의 Endpoints 필드가 빈 것으로 확인할 수 있습니다.

Q35. Ingress에서 path-based routing과 host-based routing의 차이는?

A) path-based는 IP 주소 기반, host-based는 도메인 기반 B) path-based는 URL 경로(/api, /web)로 라우팅하고, host-based는 호스트 이름(api.example.com, web.example.com)으로 라우팅한다 C) 두 방식은 동일하다 D) host-based는 TLS를 지원하지 않는다

정답: B

설명: path-based routing은 동일한 도메인에서 경로별로 다른 서비스로 라우팅합니다(example.com/api → api-service, example.com/web → web-service). host-based routing은 다른 호스트명으로 다른 서비스로 라우팅합니다(api.example.com → api-service).

Q36. Ingress에서 TLS를 설정하는 방법은?

A) spec.ssl 필드 사용 B) spec.tls 필드에 secretName(TLS인증서를 포함하는 Secret)과 hosts를 지정 C) spec.annotations에 TLS 정보 포함 D) Ingress Controller 설정으로만 가능

정답: B

설명: Ingress TLS 설정: spec.tlshosts(TLS를 적용할 호스트 목록)와 secretName(TLS 인증서가 담긴 kubernetes.io/tls 타입의 Secret)을 지정합니다. Secret에는 tls.crttls.key 키가 있어야 합니다.

Q37. NetworkPolicy에서 egress 규칙을 설정하는 이유는?

A) 들어오는 트래픽을 제어한다 B) Pod에서 나가는 트래픽을 제어하여 의도하지 않은 외부 연결을 방지한다 C) 노드 간 통신을 제어한다 D) DNS 쿼리를 차단한다

정답: B

설명: egress 규칙은 Pod에서 나가는(outbound) 트래픽을 제어합니다. 예를 들어 데이터베이스 Pod가 인터넷에 연결되는 것을 방지하거나, 특정 포트(예: 5432 Postgres)로만 나가도록 제한할 수 있습니다. DNS 통신(포트 53)은 명시적으로 허용해야 합니다.

Q38. Service를 외부 DNS 이름에 매핑하는 Service 타입은?

A) ClusterIP B) NodePort C) LoadBalancer D) ExternalName

정답: D

설명: ExternalName 서비스는 클러스터 내부에서 외부 DNS 이름을 내부 서비스 이름처럼 사용할 수 있게 합니다. 예를 들어 my-database.default.svc.cluster.localmysql.external.com으로 CNAME 매핑합니다. 클러스터 외부 서비스를 내부에서 접근할 때 유용합니다.

Q39. Pod 간 통신에서 NetworkPolicy 기본 동작은?

A) 모든 트래픽이 기본적으로 차단된다 B) NetworkPolicy가 없으면 모든 Pod 간 통신이 허용된다 C) 같은 네임스페이스의 Pod만 통신 가능하다 D) Service를 통해서만 통신 가능하다

정답: B

설명: Kubernetes의 기본 네트워크 모델에서는 NetworkPolicy가 없으면 모든 Pod 간 통신이 허용됩니다. 특정 Pod에 NetworkPolicy가 적용되면 정책에 명시된 트래픽만 허용됩니다. 네임스페이스에 default-deny NetworkPolicy를 적용하고 필요한 통신만 허용하는 것이 보안 Best Practice입니다.

Q40. Ingress pathType: Prefix와 Exact의 차이는?

A) Prefix는 경로의 앞부분만 확인하고, Exact는 전체 경로가 정확히 일치해야 한다 B) Prefix는 정규식을 사용하고, Exact는 문자열을 비교한다 C) 두 타입은 동일하다 D) Exact는 대소문자를 구분하지 않는다

정답: A

설명: Prefix는 지정된 경로로 시작하는 모든 URL을 매칭합니다(/api는 /api/users, /api/posts도 매칭). Exact는 지정된 경로와 정확히 일치하는 URL만 매칭합니다(/api는 /api만 매칭, /api/users는 불일치). ImplementationSpecific은 Ingress Controller에 따라 동작이 다릅니다.

Q41. Service에서 sessionAffinity: ClientIP를 설정하면 어떻게 되는가?

A) 같은 클라이언트 IP에서 오는 요청이 항상 같은 Pod로 라우팅된다 B) 세션이 만료된다 C) 모든 요청이 하나의 Pod로 집중된다 D) Load Balancer가 비활성화된다

정답: A

설명: sessionAffinity: ClientIP를 설정하면 동일한 클라이언트 IP에서 오는 요청이 항상 동일한 Pod로 라우팅됩니다(sticky session). sessionAffinityConfig.clientIP.timeoutSeconds로 세션 유지 시간을 설정할 수 있습니다. 기본값은 None(랜덤 라우팅)입니다.

Q42. 같은 네임스페이스 내에서 다른 서비스로 요청하는 올바른 DNS 이름은?

A) service-name.cluster.local B) service-name (또는 service-name.namespace.svc.cluster.local) C) namespace.service-name D) http://service-name:port

정답: B

설명: 같은 네임스페이스 내에서는 서비스 이름만으로 접근 가능합니다(service-name). 다른 네임스페이스에서 접근 시 service-name.namespace 또는 전체 FQDN인 service-name.namespace.svc.cluster.local을 사용합니다.

Q43. 다음 중 Pod를 외부에서 직접 접근 가능하게 하는 Service 타입은?

A) ClusterIP B) NodePort와 LoadBalancer C) headless service D) ExternalName

정답: B

설명: NodePort는 모든 노드의 특정 포트(30000-32767)로 외부 접근을 허용합니다. LoadBalancer는 클라우드 프로바이더의 로드 밸런서를 자동으로 생성하여 외부 IP를 제공합니다. ClusterIP는 클러스터 내부에서만 접근 가능합니다.

Q44. kubectl port-forward 명령어의 용도는?

A) Service의 포트를 영구적으로 변경한다 B) 로컬 포트를 Pod의 포트에 임시로 포워딩하여 클러스터 내부 서비스에 로컬에서 접근한다 C) 노드의 포트를 Pod에 매핑한다 D) Ingress 설정을 테스트한다

정답: B

설명: kubectl port-forward pod/POD_NAME LOCAL_PORT:POD_PORT는 로컬 머신의 포트를 Pod의 포트에 임시로 포워딩합니다. 개발 중에 클러스터 내부 서비스에 직접 접근하거나 디버깅할 때 유용합니다. 서비스에도 사용 가능: kubectl port-forward service/SVC_NAME LOCAL_PORT:SVC_PORT.

Q45. Pod에 여러 네트워크 인터페이스를 추가하는 방법은?

A) spec.networks 필드에 추가 네트워크 지정 B) Multus CNI를 사용하여 NetworkAttachmentDefinition으로 추가 인터페이스 설정 C) kube-proxy 설정 변경 D) 여러 개의 Service 생성

정답: B

설명: Multus CNI는 Pod에 여러 네트워크 인터페이스를 붙일 수 있는 메타 CNI 플러그인입니다. NetworkAttachmentDefinition CRD를 사용하여 추가 네트워크를 정의하고, Pod annotation으로 참조합니다. 텔레콤, NFV, 고성능 네트워킹이 필요한 환경에서 사용됩니다.

Q46. ConfigMap에서 특정 키만 환경 변수로 주입하는 방법은?

A) envFrom.configMapRef 사용 B) env[].valueFrom.configMapKeyRef.key로 특정 키 지정 C) volumeMounts 사용 D) spec.config.env 사용

정답: B

설명: 특정 키만 주입: env[].valueFrom.configMapKeyRefname(ConfigMap 이름)과 key(키 이름)를 지정합니다. 모든 키를 주입할 때는 envFrom[].configMapRef.name을 사용합니다. 특정 키만 가져오면 불필요한 환경 변수를 방지할 수 있습니다.

Q47. Pod의 종료 시 graceful shutdown을 위한 설정은?

A) spec.terminationGracePeriodSeconds로 충분한 종료 시간 확보 및 컨테이너 내 SIGTERM 처리 B) restartPolicy: Never 설정 C) Liveness Probe 비활성화 D) privileged: true 설정

정답: A

설명: spec.terminationGracePeriodSeconds(기본 30초)는 SIGTERM 신호 후 강제 종료(SIGKILL) 전 대기 시간입니다. 애플리케이션은 SIGTERM 수신 시 진행 중인 요청 처리 완료 후 종료해야 합니다. Readiness Probe를 통해 종료 중인 Pod에 새 요청이 오지 않도록 합니다. preStop 훅으로 추가 정리 작업도 가능합니다.

Q48. 다음 중 CKAD 시험에서 자주 나오는 kubectl 명령어 단축키 설정으로 올바른 것은?

A) alias kubectl=k B) alias k=kubectl; export do="--dry-run=client -o yaml" C) kubectl config set alias k=kubectl D) export KUBECTL_ALIAS=k

정답: B

설명: alias k=kubectlexport do="--dry-run=client -o yaml"는 시험 시간을 절약하는 핵심 설정입니다. 예: k create deploy myapp --image=nginx $do > deploy.yaml로 빠르게 YAML 템플릿을 생성할 수 있습니다. vim의 YAML 들여쓰기 설정도 중요합니다: :set et ts=2 sw=2.

Q49. Pod의 컨테이너에서 readOnlyRootFilesystem: true를 설정하면?

A) 컨테이너가 파일을 읽을 수 없다 B) 컨테이너의 루트 파일시스템이 읽기 전용이 되어 런타임에 파일 수정이 불가능하다 C) 볼륨 마운트가 비활성화된다 D) 네트워크 접근이 차단된다

정답: B

설명: readOnlyRootFilesystem: true는 컨테이너의 루트 파일시스템을 읽기 전용으로 만듭니다. 공격자가 컨테이너에 침입해도 파일을 수정하거나 악성 코드를 설치하기 어려워집니다. 쓰기가 필요한 디렉토리는 emptyDir 볼륨으로 마운트합니다.

Q50. Kubernetes에서 Pod 내 컨테이너가 호스트 네임스페이스를 사용하도록 설정하는 필드는?

A) spec.hostPID, spec.hostNetwork, spec.hostIPC B) spec.network.host = true C) spec.containers.hostNamespace = true D) spec.shareHostNamespace = true

정답: A

설명: spec.hostPID: true는 호스트의 PID 네임스페이스 공유, spec.hostNetwork: true는 호스트 네트워크 스택 사용, spec.hostIPC: true는 호스트 IPC 네임스페이스 공유를 설정합니다. 이 설정들은 보안 위험이 있으므로 필요한 경우에만 사용해야 합니다.

Q51. kubectl apply와 kubectl create의 차이점은?

A) kubectl create는 YAML 파일을 지원하지 않는다 B) kubectl apply는 선언적 방식으로 변경사항만 적용하고 이미 존재하면 업데이트하며, kubectl create는 리소스가 이미 존재하면 오류를 반환한다 C) kubectl create는 더 빠르다 D) kubectl apply는 삭제도 수행한다

정답: B

설명: kubectl apply는 선언적 방식으로 리소스를 관리합니다. 존재하지 않으면 생성, 이미 존재하면 변경사항만 업데이트합니다. kubectl create는 명령형 방식으로 이미 존재하는 리소스에 대해 에러를 반환합니다. CI/CD 파이프라인에서는 kubectl apply를 권장합니다.

Q52. Pod에서 특정 호스트 경로를 볼륨으로 마운트하는 방법은?

A) spec.volumes.emptyDir 사용 B) spec.volumes.hostPath 사용 C) spec.volumes.configMap 사용 D) spec.volumes.secret 사용

정답: B

설명: hostPath 볼륨은 노드의 파일시스템 경로를 컨테이너에 마운트합니다. Docker 소켓(/var/run/docker.sock), 노드 로그(/var/log)에 접근하는 등에 사용됩니다. 보안상 위험(노드 파일시스템 직접 접근)이 있으므로 주의가 필요합니다. type 필드로 Directory, File, Socket 등을 지정합니다.

Q53. 환경 변수 KUBERNETES_SERVICE_HOST는 무엇을 나타내는가?

A) kubelet이 실행 중인 노드의 IP B) Pod 내부에서 Kubernetes API 서버에 접근하기 위한 ClusterIP (자동 주입됨) C) etcd 서버의 주소 D) Ingress Controller의 주소

정답: B

설명: Kubernetes는 모든 Pod에 KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORT 환경 변수를 자동으로 주입합니다. 이 변수들은 Pod 내에서 Kubernetes API에 프로그래밍 방식으로 접근할 때 사용됩니다. ServiceAccount 토큰과 함께 사용하여 클러스터 내부에서 API를 호출할 수 있습니다.

Q54. 다음 Probe 설정에서 initialDelaySeconds, periodSeconds, failureThreshold의 역할은?

A) 각각 최대 시간, 주기, 재시도 횟수를 설정한다 B) initialDelaySeconds: 첫 Probe 시작 전 대기 시간, periodSeconds: Probe 실행 주기, failureThreshold: 연속 실패 횟수 임계값 C) 모두 타임아웃 관련 설정이다 D) 데이터베이스 연결 관련 설정이다

정답: B

설명: initialDelaySeconds: 컨테이너 시작 후 첫 번째 Probe 실행까지 대기 시간(앱 초기화 시간 고려). periodSeconds: Probe를 실행하는 주기(기본 10초). failureThreshold: 이 횟수만큼 연속 실패하면 재시작(Liveness) 또는 트래픽 제외(Readiness). timeoutSeconds: 단일 Probe의 타임아웃.

Q55. Kubernetes에서 Pod 레벨의 fsGroup 설정의 역할은?

A) 파일시스템 암호화 그룹을 지정한다 B) 마운트된 볼륨의 파일 소유권을 지정된 GID로 설정하여 그룹 기반 파일 접근을 가능하게 한다 C) 컨테이너 사용자를 지정한다 D) 네트워크 그룹을 지정한다

정답: B

설명: spec.securityContext.fsGroup은 Pod에 마운트된 볼륨(PVC 포함)의 파일 소유 그룹 GID를 지정합니다. 마운트된 볼륨의 파일 권한이 자동으로 해당 GID로 변경됩니다. 여러 컨테이너가 볼륨을 공유할 때 파일 접근 권한 문제를 해결하는 데 유용합니다.


실기 시뮬레이션 (P1 ~ P10)

P1. Multi-Container Pod with Sidecar

시나리오: nginx 메인 컨테이너와 busybox sidecar 컨테이너로 구성된 Pod를 생성하시오. Sidecar는 /var/log/nginx/access.log를 읽어 stdout으로 출력하시오. 두 컨테이너는 emptyDir 볼륨을 통해 로그 디렉토리를 공유해야 합니다.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: nginx-with-sidecar
  labels:
    app: nginx-sidecar
spec:
  containers:
  - name: nginx
    image: nginx:latest
    volumeMounts:
    - name: log-volume
      mountPath: /var/log/nginx
  - name: log-sidecar
    image: busybox:latest
    command: ['sh', '-c', 'tail -f /var/log/nginx/access.log']
    volumeMounts:
    - name: log-volume
      mountPath: /var/log/nginx
  volumes:
  - name: log-volume
    emptyDir: {}
EOF

# 사이드카 컨테이너 로그 확인
kubectl logs nginx-with-sidecar -c log-sidecar -f

P2. ConfigMap과 Secret을 사용하는 Deployment

시나리오: db-config ConfigMap과 db-secret Secret을 생성하고, 이를 환경 변수로 주입한 Deployment를 생성하시오.

# ConfigMap 생성
kubectl create configmap db-config \
  --from-literal=DB_HOST=mysql-service \
  --from-literal=DB_PORT=3306 \
  --from-literal=DB_NAME=myapp

# Secret 생성
kubectl create secret generic db-secret \
  --from-literal=DB_USER=admin \
  --from-literal=DB_PASSWORD=secretpassword

# Deployment 생성
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: nginx:latest
        envFrom:
        - configMapRef:
            name: db-config
        env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: DB_USER
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: DB_PASSWORD
EOF

# 환경 변수 확인
kubectl exec -it deploy/myapp -- env | grep -E "DB_"

P3. Probe 설정

시나리오: nginx Deployment에 Liveness Probe(HTTP, /healthz, 포트 80), Readiness Probe(HTTP, /ready, 포트 80), Startup Probe를 설정하시오.

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-with-probes
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-probes
  template:
    metadata:
      labels:
        app: nginx-probes
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        startupProbe:
          httpGet:
            path: /
            port: 80
          failureThreshold: 30
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 15
          failureThreshold: 3
          timeoutSeconds: 5
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 10
          failureThreshold: 3
          successThreshold: 1
EOF

P4. Rolling Update 및 Rollback

시나리오: webapp Deployment를 생성하고 이미지를 업데이트하며 롤아웃 상태를 모니터링하시오. 업데이트 후 롤백하시오.

# 초기 Deployment 생성
kubectl create deployment webapp \
  --image=nginx:1.24 \
  --replicas=4

# 배포 전략 설정
kubectl patch deployment webapp -p \
  '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":1}}}}'

# 이미지 업데이트
kubectl set image deployment/webapp nginx=nginx:1.25

# 롤아웃 모니터링
kubectl rollout status deployment/webapp

# 히스토리 확인
kubectl rollout history deployment/webapp

# 일시 중지하여 카나리 테스트
kubectl rollout pause deployment/webapp

# Pod 상태 확인 (일부는 새 버전, 일부는 이전 버전)
kubectl get pods -l app=webapp -o wide

# 문제 없으면 재개
kubectl rollout resume deployment/webapp

# 또는 롤백
kubectl rollout undo deployment/webapp

P5. SecurityContext 설정

시나리오: 다음 보안 요구사항을 가진 Pod를 생성하시오:

  • 사용자 ID 1000으로 실행
  • root로 실행 불가
  • 읽기 전용 루트 파일시스템
  • 모든 Linux capabilities 제거
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsUser: 1000
    runAsNonRoot: true
    fsGroup: 2000
  containers:
  - name: app
    image: nginx:latest
    securityContext:
      readOnlyRootFilesystem: true
      allowPrivilegeEscalation: false
      capabilities:
        drop:
        - ALL
    volumeMounts:
    - name: tmp-dir
      mountPath: /tmp
    - name: var-cache
      mountPath: /var/cache/nginx
    - name: var-run
      mountPath: /var/run
  volumes:
  - name: tmp-dir
    emptyDir: {}
  - name: var-cache
    emptyDir: {}
  - name: var-run
    emptyDir: {}
EOF

# 보안 설정 확인
kubectl exec secure-pod -- id
kubectl exec secure-pod -- cat /proc/1/status | grep Cap

P6. Init Container 사용

시나리오: Init Container를 사용하여 메인 컨테이너가 시작되기 전에 데이터베이스 연결을 확인하는 Pod를 생성하시오.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: app-with-init
spec:
  initContainers:
  - name: wait-for-db
    image: busybox:latest
    command: ['sh', '-c',
      'until nc -z mysql-service 3306; do echo "Waiting for MySQL..."; sleep 5; done; echo "MySQL is ready!"']
  - name: migrate-db
    image: busybox:latest
    command: ['sh', '-c', 'echo "Running DB migration..."; sleep 2; echo "Migration complete"']
  containers:
  - name: app
    image: nginx:latest
    ports:
    - containerPort: 80
EOF

# Init Container 로그 확인
kubectl logs app-with-init -c wait-for-db
kubectl logs app-with-init -c migrate-db

# Pod 상태 확인
kubectl get pod app-with-init
kubectl describe pod app-with-init

P7. ResourceQuota와 LimitRange 설정

시나리오: team-dev 네임스페이스에 ResourceQuota(CPU 4코어, 메모리 8Gi, Pod 10개)와 LimitRange(컨테이너당 기본 CPU 100m/메모리 128Mi, 최대 CPU 1/메모리 1Gi)를 설정하시오.

kubectl create namespace team-dev

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-quota
  namespace: team-dev
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "10"
    services: "5"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: container-limits
  namespace: team-dev
spec:
  limits:
  - type: Container
    default:
      cpu: 200m
      memory: 256Mi
    defaultRequest:
      cpu: 100m
      memory: 128Mi
    max:
      cpu: "1"
      memory: 1Gi
    min:
      cpu: 50m
      memory: 64Mi
EOF

# 확인
kubectl describe resourcequota team-quota -n team-dev
kubectl describe limitrange container-limits -n team-dev

P8. Ingress with TLS

시나리오: TLS를 사용하는 Ingress를 설정하여 secure.example.com으로 https 접근이 가능하게 하시오.

# 자체 서명 인증서 생성
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /tmp/tls.key \
  -out /tmp/tls.crt \
  -subj "/CN=secure.example.com/O=myorg"

# TLS Secret 생성
kubectl create secret tls secure-tls \
  --cert=/tmp/tls.crt \
  --key=/tmp/tls.key

# 서비스 생성 (테스트용)
kubectl create deployment secure-app --image=nginx --replicas=2
kubectl expose deployment secure-app --port=80 --name=secure-app-service

# TLS Ingress 생성
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - secure.example.com
    secretName: secure-tls
  rules:
  - host: secure.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: secure-app-service
            port:
              number: 80
EOF

kubectl get ingress secure-ingress

P9. NetworkPolicy 이그레스 제어

시나리오: backend Pod가 포트 5432(PostgreSQL)의 database Pod에만 트래픽을 보낼 수 있도록 egress NetworkPolicy를 설정하시오. DNS 쿼리는 허용해야 합니다.

cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-egress-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
  - ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
EOF

# NetworkPolicy 확인
kubectl get networkpolicy backend-egress-policy
kubectl describe networkpolicy backend-egress-policy

P10. Job과 CronJob

시나리오: 1부터 10까지의 합계를 계산하는 Job을 생성하고, 매 분마다 현재 시간과 호스트 이름을 출력하는 CronJob을 생성하시오.

# 합계 계산 Job
cat <<EOF | kubectl apply -f -
apiVersion: batch/v1
kind: Job
metadata:
  name: sum-calculator
spec:
  completions: 1
  parallelism: 1
  backoffLimit: 3
  template:
    spec:
      containers:
      - name: calculator
        image: busybox:latest
        command:
        - /bin/sh
        - -c
        - |
          sum=0
          for i in 1 2 3 4 5 6 7 8 9 10; do
            sum=$((sum + i))
          done
          echo "Sum of 1 to 10 is: $sum"
      restartPolicy: OnFailure
EOF

# CronJob 생성
cat <<EOF | kubectl apply -f -
apiVersion: batch/v1
kind: CronJob
metadata:
  name: heartbeat
spec:
  schedule: "* * * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: heartbeat
            image: busybox:latest
            command:
            - /bin/sh
            - -c
            - echo "Heartbeat at $(date) from $(hostname)"
          restartPolicy: OnFailure
EOF

# Job 로그 확인
kubectl logs -l job-name=sum-calculator

# CronJob 확인
kubectl get cronjob heartbeat
kubectl get jobs --watch

시험 팁

  1. 도메인 파악: Application Environment, Configuration & Security(25%)가 가장 높은 비중
  2. YAML 빠른 생성: --dry-run=client -o yaml로 템플릿 생성
  3. probe 필드 암기: initialDelaySeconds, periodSeconds, failureThreshold 기억
  4. SecurityContext 레벨 구분: Pod 수준 vs 컨테이너 수준
  5. ConfigMap vs Secret: 민감 정보는 반드시 Secret 사용
  6. kubectl explain 활용: kubectl explain pod.spec.containers.securityContext로 필드 확인