$ yh.log
[CKA] 1주차 - 클러스터 구조와 Pod · Deployment, kubectl 기본기

[CKA] 1주차 - 클러스터 구조와 Pod · Deployment, kubectl 기본기

KubernetesCKAkubectlPodDeploymentminikube

작성자 : 오예환 | 작성일 : 2026-10-09 | 수정일 : 2026-10-09 | 조회수 :

CKA 1주차 - 클러스터 구조와 Pod · Deployment, kubectl 기본기

이 시리즈에 대해

AWS DevOps Engineer Professional에 합격한 뒤 다음 목표로 CKA(Certified Kubernetes Administrator) 를 준비하고 있다. 지금 회사가 AWS EKS로 인프라를 운영하고 있어서, 시험 준비가 곧 회사 인프라를 이해하는 공부가 된다는 점이 컸다.

나는 프론트엔드 개발자이고 쿠버네티스는 처음이다. 그래서 개념을 읽기만 하지 않고, 노트북의 minikube 클러스터에서 명령어를 하나씩 직접 쳐보면서 공부했다. 이 시리즈는 그 과정을 주차별로 정리한 기록이다.

  1. 1주차: 클러스터 구조, Pod · Deployment, kubectl 기본기 (이번 글)
  2. 2주차: ConfigMap · Secret, 리소스 requests/limits, 스케줄링(nodeSelector · taint · affinity), DaemonSet
  3. 3주차: Service 4종, EndpointSlice, kube-proxy, CoreDNS, Service 장애 진단

0. CKA는 어떤 시험인가

CKA는 객관식이 아니다. 원격 감독관이 웹캠으로 지켜보는 상태에서, 브라우저 안의 리눅스 터미널로 실제 클러스터를 조작해서 과제를 해결하는 실습형 시험이다.

항목내용
형식실습형(performance-based), 2시간 동안 15~20개 과제
합격선66점
허용 자료시험 중 kubernetes.io 공식 문서 열람 가능
언어문제는 영어 (Create a pod named ... in namespace ... 같은 정형화된 문장)

출제 비중은 다음과 같다.

도메인비중
Troubleshooting30%
Cluster Architecture, Installation & Configuration25%
Services & Networking20%
Workloads & Scheduling15%
Storage10%

명령어를 손에 익히는 속도가 곧 점수다. 그래서 공부 시간의 대부분을 실습에 쓰기로 했다.

합격선·응시료·허용 문서 범위는 바뀔 수 있으니 응시 전에 Linux Foundation 공식 페이지에서 다시 확인해야 한다.

실습 환경

  • Docker Desktop 위에서 minikube 2노드 클러스터를 띄웠다. minikube(control-plane)와 minikube-m02(worker) 두 대이고, CNI는 flannel, 쿠버네티스 버전은 v1.37.0이다.
  • 명령어는 EKS와 똑같다. 로컬 클러스터에서 익힌 kubectl 명령을 회사 EKS에서도 그대로 쓸 수 있다.
minikube start --driver=docker --nodes=2 --cni=flannel \
  --kubernetes-version=v1.37.0 --cpus=2 --memory=3072

1. 쿠버네티스 리소스의 계층

처음 쿠버네티스를 보면 Pod, ReplicaSet, Deployment, Node 같은 단어가 한꺼번에 나와서 헷갈린다. 가장 먼저 "무엇이 무엇을 감싸고 있는가"를 정리했다. 왼쪽이 가장 바깥, 오른쪽이 가장 안쪽이다.

  1. Cluster
  2. Node
  3. Deployment
  4. ReplicaSet
  5. Pod
  6. Container

안쪽부터 하나씩 보면 이렇다.

  • Container: 앱과 실행 환경을 이미지로 묶어 실행한 것이다. 이미지는 Docker Hub 같은 레지스트리에서 받아온다.
  • Pod: 보통 컨테이너 1개를 감싼다. 클러스터 내부에서만 쓰는 IP(10.244.x.x)를 하나 받는다.
  • ReplicaSet: "Pod를 항상 N개 유지"를 실제로 수행한다. Pod 이름 가운데 해시(web-68d995574f-xxxxx의 68d995574f)가 이 ReplicaSet의 ID다.
  • Deployment: ReplicaSet을 관리한다. 스케일 조정, 버전 업데이트, 롤백을 Deployment에 시킨다.
  • Node / Cluster: Node는 앱이 실행되는 서버이고(EKS에서는 보통 EC2 인스턴스), Cluster는 Node들과 이들을 관리하는 control plane을 합친 것이다.

실무에서는 Pod를 직접 만들지 않는다. Deployment를 만들면 Deployment → ReplicaSet → Pod 순서로 쿠버네티스가 알아서 만들어준다. 왜 그런지는 아래 자가 치유 실습에서 확인했다.


2. 명령형과 선언형

리소스를 만드는 방법은 두 가지다.

방식명령의미
명령형 (imperative)k run, k create"지금 이걸 하나 만들어"
선언형 (declarative)k apply -f x.yaml"이 파일에 적힌 상태로 맞춰줘"
# 명령형: Pod를 바로 만든다
k run myweb --image=nginx
 
# 선언형: YAML 파일을 만든 뒤 그 내용대로 반영한다
k run web2 --image=nginx --dry-run=client -o yaml > web2.yaml
k apply -f web2.yaml

--dry-run=client -o yaml이 이번 주에 가장 많이 쓴 옵션이다.

  • --dry-run=client: 클러스터에 실제로 만들지 않고 결과만 계산한다.
  • -o yaml: 그 결과를 YAML로 출력한다.
  • > web2.yaml: 화면 대신 파일로 저장한다.

시험에서 YAML을 처음부터 손으로 쓰면 들여쓰기 실수도 나고 시간도 오래 걸린다. 명령형으로 뼈대를 뽑은 뒤 필요한 부분만 고치는 방식이 훨씬 빠르다.

apply는 무조건 새로 만드는 명령이 아니다. YAML에 적힌 상태와 클러스터의 현재 상태를 비교해서 다른 부분만 바꾼다. 같은 파일로 apply를 여러 번 실행해도 리소스가 늘어나거나 망가지지 않는다. 이 성질을 멱등성(idempotency) 이라고 한다. 실제로 내용이 같은 파일을 다시 적용하면 unchanged가 출력된다.

모든 매니페스트는 4개의 최상위 필드로 시작한다.

apiVersion: v1 # 이 리소스를 정의한 API 버전
kind: Pod # 리소스 종류
metadata: # 이름, 라벨 같은 식별 정보
  name: web2
spec: # 원하는 상태 (어떤 컨테이너를 어떻게 실행할지)
  containers:
    - name: web2
      image: nginx

3. Pod 하나를 만들고 들여다보기

Pod를 하나 만들고 상태를 확인하는 명령부터 익혔다.

k run myweb --image=nginx          # Pod 생성
k get pod myweb -o wide            # IP와 배치된 노드까지 표시
k describe pod myweb               # 상세 정보와 이벤트
k logs myweb                       # 컨테이너 로그
k exec myweb -- hostname           # 컨테이너 안에서 명령 실행
k get pods -A -o wide              # 모든 네임스페이스의 Pod 조회

이 중에서 describe가 가장 중요하다. 출력 맨 아래의 Events 에 "이미지를 받는 중", "스케줄링 실패", "컨테이너 재시작" 같은 기록이 시간 순서로 남는다. Pod가 이상하면 제일 먼저 Events를 본다. 2주차와 3주차의 장애 실습에서도 원인은 전부 여기서 찾았다.


4. Deployment: 자가 치유, 스케일, 롤링 업데이트

자가 치유 (self-healing)

k create deployment web --image=nginx --replicas=3
k get deployment,replicaset,pod

Pod 3개가 뜬 상태에서 Pod 하나를 직접 지워봤다.

k delete pod web-68d995574f-abcde
k get pod

지운 Pod는 사라지지만 곧바로 다른 이름의 새 Pod 가 생겨서 다시 3개가 된다. ReplicaSet이 "원하는 개수는 3개인데 현재 2개"라는 차이를 발견하고 하나를 새로 만든 것이다.

반대로 k run으로 직접 만든 Pod는 지우면 그걸로 끝이다. 다시 만들어줄 관리자가 없다. 실무에서 Pod를 직접 만들지 않고 Deployment를 쓰는 이유가 이것이다.

스케일

k scale deployment web --replicas=5
k scale deployment web --replicas=2

명령 한 줄로 개수가 3 → 5 → 2로 바뀌었다.

비슷해 보이지만 결과가 다른 두 명령도 비교했다.

명령결과
k scale deployment web --replicas=0Deployment와 ReplicaSet은 남고 Pod만 0개가 된다. 다시 --replicas=2로 올리면 같은 ReplicaSet이 Pod를 새로 만든다
k delete deployment webDeployment, ReplicaSet, Pod가 모두 삭제된다

잠시 트래픽을 멈추고 싶을 때는 scale 0, 완전히 걷어낼 때는 delete를 쓴다.

롤링 업데이트와 롤백

k set image deployment/web nginx=nginx:1.27   # 이미지 버전 변경
k rollout status deployment/web               # 배포 진행 상황
k rollout history deployment/web              # 리비전 목록
k rollout undo deployment/web                 # 직전 리비전으로 되돌리기

이미지를 바꾸면 Deployment는 기존 ReplicaSet을 수정하지 않는다. 새 ReplicaSet을 만들어 Pod를 하나씩 옮기고, 기존 ReplicaSet은 Pod 0개로 남겨둔다.

  1. rev1: ReplicaSet A(nginx)의 Pod가 3개 → 0개가 된다. ReplicaSet A는 지우지 않고 남겨둔다.
  2. rev2: ReplicaSet B(nginx:1.27)의 Pod가 0개 → 3개가 된다.
  3. rollout undo 후 rev3: 남겨둔 ReplicaSet A를 다시 사용해서 Pod를 0개 → 3개로 늘린다.

rollout undo가 빠른 이유가 여기에 있다. 이전 버전의 ReplicaSet이 그대로 남아 있어서 그 ReplicaSet의 Pod 개수만 다시 늘리면 된다. k get rs로 보면 Pod 0개짜리 ReplicaSet이 남아 있는 것을 확인할 수 있다.

실습하면서 하나 더 알게 된 점이 있다. nginx처럼 태그 없이 쓰면 latest가 되는데, latest는 받는 시점마다 실제 버전이 달라질 수 있다. 로그를 보니 nginx/1.31.3이 실행되고 있었다. 언제 배포하든 같은 결과가 나오게 하려면 nginx:1.27처럼 태그를 명시해야 한다.


5. kubectl은 어느 클러스터를 조작하고 있나: context

kubectl은 ~/.kube/config(kubeconfig) 파일에 적힌 클러스터 목록 중 current-context 로 지정된 클러스터에 명령을 보낸다.

k config current-context           # 지금 조작 중인 클러스터
k config get-contexts              # 전체 목록
k config use-context <이름>        # 전환
aws eks update-kubeconfig --name <클러스터>   # EKS 클러스터를 kubeconfig에 추가

시험에서는 문제마다 대상 클러스터가 다르다. 각 문제 상단에 적힌 k config use-context ...를 먼저 실행하지 않으면, 엉뚱한 클러스터에서 작업하게 되고 그 문제는 0점이 된다.


6. 시험용 셸 세팅

alias k=kubectl
source <(kubectl completion bash)
export do='--dry-run=client -o yaml'
export now='--force --grace-period=0'
  • k run web --image=nginx $do > web.yaml처럼 YAML 뼈대를 빠르게 만들 수 있다.
  • k delete pod web $now는 Pod가 종료될 때까지 기다리지 않고 바로 지운다.
  • 리소스 이름은 줄여 쓸 수 있다. po(pods), deploy(deployments), rs(replicasets), svc(services), no(nodes), ns(namespaces), cm(configmaps).

내 맥은 zsh라서 $do가 하나의 문자열로 넘어가 옵션이 쪼개지지 않는 문제가 있었다. zsh에서는 ${=do}로 쓰거나 옵션을 풀어서 쳐야 한다. 시험 환경은 bash라서 $do를 그대로 쓰면 된다.


7. 1주차 명령어 정리

목적명령
노드 · Pod 조회k get no · k get po -A -o wide
상세 정보 · 이벤트k describe pod <이름>
로그 · 내부 명령k logs <pod> · k exec <pod> -- <cmd>
Pod 생성k run myweb --image=nginx
YAML 뼈대k run myweb --image=nginx --dry-run=client -o yaml > p.yaml
선언형 적용k apply -f p.yaml
Deployment 생성k create deployment web --image=nginx --replicas=3
스케일k scale deployment web --replicas=5
버전 변경k set image deployment/web nginx=nginx:1.27
롤아웃 상태 · 이력 · 롤백k rollout status | history | undo deployment/web
삭제k delete pod <이름> · k delete -f p.yaml

정리

  • 쿠버네티스에서는 Pod를 직접 다루기보다 Deployment에 "원하는 상태"를 알려주고, 실제 맞추는 일은 ReplicaSet에 맡긴다.
  • YAML은 --dry-run=client -o yaml로 뼈대를 만들고 고친다. apply는 원하는 상태와 현재 상태의 차이만 반영한다.
  • 문제가 생기면 describe의 Events부터 본다.

다음 글에서는 앱 설정을 이미지 밖으로 빼는 ConfigMap · Secret과, Pod를 어느 노드에 배치할지 정하는 스케줄링을 정리한다.