🎯 CKA 문제 해석 가이드 (25문제)

핵심

문제 영어 → kubectl 명령어로 1:1 매핑. 문제별로 “뭘 만들고, 어떤 옵션이 필요한지” 빠르게 파악


📑 목차


📗 BASIC (Q1-Q10)

Q1. Pod 생성 (3분)

Create a pod named “web-pod” using the nginx:1.25 image in the namespace “dev”. The pod should have a label “app=web”.

문장명령어
Create a podkubectl run
named “web-pod”web-pod
using nginx:1.25--image=nginx:1.25
in namespace “dev”-n dev
label “app=web”--labels='app=web'
kubectl run web-pod --image=nginx:1.25 -n dev --labels='app=web'

포인트

“Create a pod” = kubectl run (deployment 아님!)


Q2. Deployment 생성 (3분)

Create a deployment named “api-deploy” in the default namespace. Image: httpd:2.4, Replicas: 3, Label: tier=backend

문장명령어
Create a deploymentkubectl create deployment
named “api-deploy”api-deploy
Image: httpd:2.4--image=httpd:2.4
Replicas: 3--replicas=3
Label: tier=backend별도 명령!
kubectl create deployment api-deploy --image=httpd:2.4 --replicas=3
kubectl label deployment api-deploy tier=backend

함정

kubectl create deployment에는 --labels 옵션이 없다!


Q3. Service 노출 (3분)

Expose the deployment “api-deploy” as a ClusterIP service named “api-svc” on port 80.

문장명령어
Exposekubectl expose
deployment “api-deploy”deployment api-deploy
as a ClusterIP service--type=ClusterIP (기본값)
named “api-svc”--name=api-svc
on port 80--port=80
kubectl expose deployment api-deploy --name=api-svc --port=80

주의

--name = 서비스 이름, --cluster-ip = IP 주소 (다른 용도!)


Q4. ConfigMap + Pod (5분)

Create a ConfigMap named “app-config” with: DB_HOST=mysql.default.svc, DB_PORT=3306. Create a pod named “config-pod” using nginx that loads this ConfigMap as environment variables.

Part 1: ConfigMap

kubectl create configmap app-config \
  --from-literal=DB_HOST=mysql.default.svc \
  --from-literal=DB_PORT=3306

Part 2: Pod - “as environment variables” = envFrom

kubectl run config-pod --image=nginx --dry-run=client -o yaml > pod.yaml
# envFrom 섹션 추가 후 apply
    envFrom:
    - configMapRef:
        name: app-config

Q5. Secret + Volume Mount (7분)

Create a Secret named “db-secret” with: username=admin, password=secretpass123. Create a pod “secret-pod” using busybox that mounts the secret as a volume at /etc/secrets. Command: sleep 3600

Part 1: Secret

kubectl create secret generic db-secret \
  --from-literal=username=admin \
  --from-literal=password=secretpass123

Part 2: Pod - “mount as a volume at /path” = volumes + volumeMounts

kubectl run secret-pod --image=busybox --dry-run=client -o yaml --command -- sleep 3600 > pod.yaml
    volumeMounts:
    - name: secret-vol
      mountPath: /etc/secrets
  volumes:
  - name: secret-vol
    secret:
      secretName: db-secret

Q6. Resource Limits (5분)

Create a pod named “limited-pod” with nginx image. Memory request: 64Mi, limit: 128Mi. CPU request: 100m, limit: 200m.

kubectl run limited-pod --image=nginx:1.25 --dry-run=client -o yaml > pod.yaml
# resources 섹션 추가
    resources:
      requests:
        memory: "64Mi"
        cpu: "100m"
      limits:
        memory: "128Mi"
        cpu: "200m"

포인트

resourcesrequests/limitsmemory/cpu 3단 구조


Q7. Multi-Container + Shared Volume (7분)

Create pod “multi-pod” with two containers: web(nginx), logger(busybox, sleep 3600). Both share volume “shared-data” mounted at /data.

kubectl run multi-pod --image=nginx --dry-run=client -o yaml > pod.yaml
# 두 번째 컨테이너 + volumes 추가
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: web
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /data
  - name: logger
    image: busybox
    command: ["sleep", "3600"]
    volumeMounts:
    - name: shared-data
      mountPath: /data

주의

  • volumesspec 바로 아래 (containers와 같은 레벨)
  • 두 번째 컨테이너는 containers: 배열에 -로 추가
  • emptyDir: {} 중괄호 필수

Q8. Node Selector (5분)

Label node with “disk=ssd”. Create pod “node-pod” with nginx that only runs on disk=ssd nodes.

Part 1: 노드 라벨링

# 노드 이름 확인
kubectl get nodes
# 라벨 추가
kubectl label node NODE_NAME disk=ssd

Part 2: Pod with nodeSelector

kubectl run node-pod --image=nginx --dry-run=client -o yaml > pod.yaml
# nodeSelector 추가
spec:
  nodeSelector:
    disk: ssd
  containers:
  - name: node-pod
    image: nginx

포인트

nodeSelectorspec 바로 아래 (containers와 같은 레벨) key: value 형태 (= 아님!)


Q9. ServiceAccount (5분)

Create namespace “prod” if not exists. Create ServiceAccount “app-sa” in namespace “prod”. Create pod “sa-pod” using nginx in “prod” with ServiceAccount “app-sa”.

kubectl create namespace prod --dry-run=client -o yaml | kubectl apply -f -
kubectl create serviceaccount app-sa -n prod
kubectl run sa-pod --image=nginx -n prod --dry-run=client -o yaml > pod.yaml
# serviceAccountName 추가
spec:
  serviceAccountName: app-sa
  containers:
  - name: sa-pod
    image: nginx

포인트

serviceAccountNamespec 바로 아래


Q10. 디버깅 (5분)

Run: kubectl run broken-pod —image=nginx:nonexistent-tag. Debug and fix the issue so the pod runs successfully.

# 1. 상태 확인
kubectl get pods
kubectl describe pod broken-pod
 
# 2. 이미지 수정
kubectl set image pod/broken-pod broken-pod=nginx:latest
 
# 또는 edit로 수정
kubectl edit pod broken-pod
# image: nginx:nonexistent-tag → image: nginx:latest

포인트

kubectl describe로 Events 확인 → ImagePullBackOff/ErrImagePull 확인 kubectl set image로 빠르게 이미지 변경


📙 INTERMEDIATE (Q11-Q20)

Q11. PersistentVolume (5분)

Create PV “pv-data”: Capacity 1Gi, ReadWriteOnce, Host Path /mnt/data, Storage Class manual

전체 YAML 작성 필요 (imperative 명령 없음)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-data
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  hostPath:
    path: /mnt/data
  storageClassName: manual
kubectl apply -f pv.yaml
kubectl get pv

주의

PV는 kubectl create 명령이 없음! YAML 직접 작성 필수 kubectl explain pv.spec으로 필드 확인


Q12. PVC + Pod (5분)

Create PVC “pvc-data”: 500Mi, ReadWriteOnce, storageClass manual. Create pod “pvc-pod” with nginx mounting PVC at /usr/share/nginx/html

Part 1: PVC

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-data
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi
  storageClassName: manual

Part 2: Pod

spec:
  volumes:
  - name: pvc-vol
    persistentVolumeClaim:
      claimName: pvc-data
  containers:
  - name: pvc-pod
    image: nginx
    volumeMounts:
    - name: pvc-vol
      mountPath: /usr/share/nginx/html

포인트

PVC 볼륨 = persistentVolumeClaim.claimName PV의 storageClassName과 PVC의 storageClassName이 일치해야 바인딩됨


Q13. Rolling Update (5분)

Create deployment “rolling-deploy”: nginx:1.19, Replicas 4. Update image to nginx:1.25. Verify rollout status.

# 생성
kubectl create deployment rolling-deploy --image=nginx:1.19 --replicas=4
 
# 이미지 업데이트
kubectl set image deployment/rolling-deploy nginx=nginx:1.25
 
# 롤아웃 상태 확인
kubectl rollout status deployment/rolling-deploy
 
# 히스토리 확인
kubectl rollout history deployment/rolling-deploy

포인트

kubectl set image deployment/NAME CONTAINER=IMAGE 컨테이너 이름은 kubectl describe deployment로 확인


Q14. Rollback (3분)

Rollback “rolling-deploy” to previous version. Verify image is back to nginx:1.19.

# 롤백
kubectl rollout undo deployment/rolling-deploy
 
# 확인
kubectl describe deployment rolling-deploy | grep Image

Q15. Scale (2분)

Scale deployment “rolling-deploy” to 6 replicas.

kubectl scale deployment rolling-deploy --replicas=6
kubectl get deployment rolling-deploy

Q16. NetworkPolicy (7분)

Create NetworkPolicy “api-netpol” in default namespace: Applies to pods with label “app=api”. Allow ingress only from pods with label “app=web”. Allow only port 80.

YAML 직접 작성 필요

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-netpol
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: web
    ports:
    - protocol: TCP
      port: 80

주의

  • podSelector = 이 정책이 적용되는 대상
  • ingress.from.podSelector = 허용할 출발지
  • kubectl explain networkpolicy.spec으로 구조 확인

Q17. Role (5분)

Create Role “pod-reader” in namespace “dev”: Allows get, list, watch on pods.

kubectl create role pod-reader \
  --verb=get --verb=list --verb=watch \
  --resource=pods \
  -n dev

포인트

--verb를 각각 반복! (--from-literal과 같은 패턴)


Q18. RoleBinding (5분)

Create RoleBinding “read-pods” in namespace “dev”: Bind role “pod-reader” to user “jane”.

kubectl create rolebinding read-pods \
  --role=pod-reader \
  --user=jane \
  -n dev

Q19. Logs & Exec (3분)

Given pod “web-pod” in namespace “dev”: 1) Get last 50 lines of logs. 2) Exec into pod and run: cat /etc/os-release

# 마지막 50줄
kubectl logs web-pod -n dev --tail=50
 
# exec
kubectl exec web-pod -n dev -- cat /etc/os-release

포인트

--tail=N = 마지막 N줄 exec 뒤에 -- 필수


Q20. ResourceQuota (5분)

Create ResourceQuota “dev-quota” in namespace “dev”: Max pods 10, requests.cpu 4, requests.memory 4Gi.

kubectl create quota dev-quota -n dev \
  --hard=pods=10,requests.cpu=4,requests.memory=4Gi

포인트

kubectl create quota로 imperative 생성 가능! --hard=key=value,key=value 콤마로 구분 (—from-literal과 다름!)


📕 ADVANCED (Q21-Q25)

Q21. Ingress (7분)

Create Ingress “web-ingress”: Host myapp.example.com, Path /api, Backend service “api-svc” port 80.

kubectl create ingress web-ingress \
  --rule="myapp.example.com/api=api-svc:80"

또는 YAML:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-svc
            port:
              number: 80

포인트

kubectl create ingress로 imperative 가능! --rule="host/path=service:port" 형식


Q22. Init Container (7분)

Create pod “init-pod” with: Init container name=init, image=busybox, command: [“sh”, “-c”, “echo ‘init’ && sleep 5”]. Main container name=main, image=nginx.

kubectl run init-pod --image=nginx --dry-run=client -o yaml > pod.yaml
# initContainers 섹션 추가
spec:
  initContainers:
  - name: init
    image: busybox
    command: ["sh", "-c", "echo 'init' && sleep 5"]
  containers:
  - name: main
    image: nginx

주의

initContainerscontainers와 같은 레벨 (spec 바로 아래) Init이 완료되어야 Main이 시작됨


Q23. Taint & Toleration (5분)

  1. Taint node: key=dedicated, value=web, effect=NoSchedule. 2) Create pod “taint-pod” with nginx that tolerates this taint.

Part 1: Taint 추가

kubectl taint nodes NODE_NAME dedicated=web:NoSchedule

Part 2: Pod with Toleration

spec:
  tolerations:
  - key: "dedicated"
    operator: "Equal"
    value: "web"
    effect: "NoSchedule"
  containers:
  - name: taint-pod
    image: nginx

포인트

Taint = 노드에 “경고 딱지” 붙이기 Toleration = Pod에 “이 딱지 괜찮아” 설정 kubectl explain pod.spec.tolerations


Q24. Sidecar 로그 패턴 (7분)

Create pod “sidecar-pod”: Main nginx writes logs to /var/log/nginx. Sidecar busybox runs “tail -f /var/log/nginx/access.log”. Share volume “logs”.

spec:
  volumes:
  - name: logs
    emptyDir: {}
  containers:
  - name: main
    image: nginx
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx
  - name: sidecar
    image: busybox
    command: ["tail", "-f", "/var/log/nginx/access.log"]
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx

포인트

Q7과 같은 패턴! emptyDir + 두 컨테이너가 같은 경로 마운트


Q25. 클러스터 정보 조회 (5분)

  1. List all nodes and status. 2) List pods in kube-system. 3) Get cluster version. 4) Check events in default namespace.
# 1. 노드 목록
kubectl get nodes
 
# 2. kube-system pods
kubectl get pods -n kube-system
 
# 3. 클러스터 버전
kubectl version
 
# 4. 이벤트
kubectl get events --sort-by='.lastTimestamp'

📊 난이도별 핵심 요약

구간핵심imperative 가능 여부
Q1-Q7run/create + dry-run → yaml 편집대부분 가능
Q8-Q10nodeSelector, serviceAccount, 디버깅부분 가능
Q11-Q12PV/PVCYAML 직접 작성 필수
Q13-Q15rollout, scale전부 imperative
Q16NetworkPolicyYAML 직접 작성 필수
Q17-Q20RBAC, logs, quota전부 imperative
Q21-Q25Ingress, init, taint, sidecar혼합

YAML 직접 작성 필수 리소스

PV, PVC, NetworkPolicy, Toleration → 이 4개는 반드시 YAML 구조 암기!