6. Core Concepts - Section Introduction

  • Kubernetes 클러스터 아키텍처의 핵심 개념 소개
  • 주요 API 프리미티브: Pods, ReplicaSets, Deployments, Services
  • CKAD 과정을 이미 수료했다면 일부 섹션은 건너뛰고 Practice Test만 진행해도 됨

7. Cluster Architecture

공식문서: Kubernetes Components

항구 비유: 화물선(Worker Node) = 컨테이너 운반, 관제선(Master Node) = 모니터링 및 관리

Master Node (Control Plane) 구성 요소

컴포넌트역할
ETCD클러스터 전체 상태/설정을 key-value로 저장
Kube Scheduler새 컨테이너를 어느 Worker Node에 배치할지 결정
Controllers노드 생명주기, 컨테이너 복제, 시스템 안정성 관리
Kube API Server클러스터 통신/관리의 중앙 허브

Worker Node 구성 요소

컴포넌트역할
Kubelet노드의 “선장” - 컨테이너 생명주기 관리, 상태 보고
Kube Proxy네트워킹 규칙 설정, 노드 간 컨테이너 통신 지원
Container RuntimeDocker, Containerd, CRI-O 등
graph TB
    subgraph Master["Master Node (Control Plane)"]
        ETCD["ETCD"]
        SCH["Scheduler"]
        CTRL["Controllers"]
        API["API Server"]
    end

    subgraph W1["Worker 1"]
        K1["Kubelet"]
        KP1["Kube Proxy"]
        CR1["Container Runtime"]
        P1["Pod  Pod"]
    end

    subgraph W2["Worker 2"]
        K2["Kubelet"]
        KP2["Kube Proxy"]
        CR2["Container Runtime"]
        P2["Pod  Pod"]
    end

    subgraph W3["Worker 3"]
        K3["Kubelet"]
        KP3["Kube Proxy"]
        CR3["Container Runtime"]
        P3["Pod  Pod"]
    end

    API --> K1
    API --> K2
    API --> K3

8. Docker vs ContainerD

공식문서: Container Runtimes

Container Runtime 진화 과정

  1. Docker가 처음 컨테이너 생태계를 지배
  2. Kubernetes가 CRI (Container Runtime Interface) 도입 → OCI 표준 준수 런타임 지원
  3. Docker는 CRI 이전에 만들어져서 호환 X → Docker Shim 으로 임시 해결
  4. ContainerD 가 CRI-compatible 런타임으로 독립 → Docker Shim 불필요
  5. Kubernetes v1.24: Docker 런타임 지원 제거 (Docker Shim 제거)

Docker로 빌드한 이미지는 OCI 호환이므로 ContainerD에서 정상 동작

CLI 도구 비교

도구개발 주체용도비고
ctrContainerD디버깅 전용기능 제한적, 일상 사용 비추천
nerdctlContainerD범용 컨테이너 관리Docker CLI와 거의 동일한 문법
crictlKubernetes디버깅/검사모든 CRI 런타임과 호환
# ctr 사용 예시
ctr images pull docker.io/library/redis:alpine
ctr run docker.io/library/redis:alpine redis
 
# nerdctl 사용 (docker 명령어와 동일)
nerdctl run --name redis redis:alpine
nerdctl run --name webserver -p 80:80 -d nginx
 
# crictl 사용 (Kubernetes 디버깅용)
crictl pull busybox
crictl images
crictl ps -a
crictl pods  # Docker에는 없는 기능

Runtime Endpoint 설정 (v1.24+)

crictl --runtime-endpoint <endpoint>
# 또는
export CONTAINER_RUNTIME_ENDPOINT=<endpoint>

9. A Note on Docker Deprecation

  • Kubernetes v1.24부터 Docker 런타임 지원 공식 제거
  • Docker로 빌드한 이미지는 계속 사용 가능 (OCI 표준 준수)
  • ContainerD가 Docker의 핵심 런타임이었으므로, 실질적으로 동일한 컨테이너 실행
  • 기존 Docker 워크플로우(이미지 빌드, 푸시 등)는 변경 없음

10. ETCD For Beginners

  • 분산 key-value 저장소 (신뢰할 수 있고 일관성 있는 데이터 저장)
  • 쿼럼 메커니즘으로 데이터 일관성 보장

기본 동작

# ETCD 설치 및 실행
tar -xzvf etcd-v3.5.0-linux-amd64.tar.gz
./etcd
 
# 기본 포트: 2379
 
# key-value 저장/조회
etcdctl put key1 value1
etcdctl get key1
 
# 모든 키 조회
etcdctl get / --prefix --keys-only

ETCD 버전

버전API비고
v2etcdctl (v2 API)이전 버전
v3etcdctl (v3 API)현재 기본값
# API 버전 확인/설정
export ETCDCTL_API=3
etcdctl version

11. ETCD in Kubernetes

  • 클러스터의 모든 정보 저장: Nodes, Pods, Configs, Secrets, Accounts, Roles, Bindings 등
  • kubectl get 명령의 모든 정보가 ETCD에서 조회됨
  • 클러스터에 대한 모든 변경사항이 ETCD에 반영되어야 완료로 간주

배포 방식에 따른 차이

수동 설치:

wget -q --https-only https://github.com/etcd-io/etcd/releases/download/...
# etcd 서비스 직접 구성
# --advertise-client-urls https://${INTERNAL_IP}:2379

kubeadm 설치:

# etcd가 kube-system 네임스페이스에 pod으로 실행
kubectl get pods -n kube-system | grep etcd
 
# etcd 내부의 모든 키 확인
kubectl exec etcd-master -n kube-system -- etcdctl get / \
  --prefix --keys-only \
  --limit=10 \
  --cacert /etc/kubernetes/pki/etcd/ca.crt \
  --cert /etc/kubernetes/pki/etcd/server.crt \
  --key /etc/kubernetes/pki/etcd/server.key

HA (고가용성) 환경

  • 여러 Master Node에 ETCD가 분산 배포
  • --initial-cluster 옵션으로 ETCD 인스턴스들의 주소 설정

12. ETCD - Commands (Optional)

# API v3 사용 설정
export ETCDCTL_API=3
 
# 필수 인증 옵션
etcdctl \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  member list
 
# 스냅샷 저장 (백업)
etcdctl snapshot save /tmp/etcd-backup.db
 
# 스냅샷 상태 확인
etcdctl snapshot status /tmp/etcd-backup.db

13. Kube-API Server

  • Kubernetes의 중앙 관리 컴포넌트
  • 모든 kubectl 명령은 API Server를 통해 처리됨
  • 유일하게 ETCD와 직접 통신하는 컴포넌트

요청 처리 흐름

  1. 사용자/kubectl → API Server로 요청
  2. Authentication — 누구인지 확인
  3. Authorization — 권한 있는지 확인
  4. Admission Control — 요청 내용 검증/수정
  5. ETCD 업데이트 — 변경사항 저장

API Server ↔ Scheduler / Controller / Kubelet 은 항상 양방향 통신

Pod 생성 시 동작 순서

  1. API Server가 요청 인증/인가
  2. Pod 객체 생성 (아직 노드 미할당)
  3. ETCD 업데이트
  4. Scheduler가 적절한 노드 결정 → API Server에 알림
  5. API Server가 ETCD 업데이트
  6. 해당 노드의 Kubelet이 컨테이너 런타임에 이미지 배포 지시
  7. Kubelet이 상태를 API Server에 보고 → ETCD 업데이트

설정 확인

# kubeadm 환경
cat /etc/kubernetes/manifests/kube-apiserver.yaml
 
# 서비스 환경
cat /etc/systemd/system/kube-apiserver.service
 
# 프로세스 확인
ps -aux | grep kube-apiserver

14. Kube Controller Manager

  • 다양한 Controller들을 하나의 프로세스로 관리하는 바이너리

주요 Controller

Controller역할
Node Controller5초 간격 노드 상태 감시, 40초 후 unreachable 처리, 5분 후 pod eviction
Replication Controller원하는 수의 pod 복제본 유지
Deployment ControllerDeployment 리소스 관리
Namespace ControllerNamespace 생명주기 관리
ServiceAccount ControllerServiceAccount 자동 생성
Job ControllerJob 리소스 관리

Node Controller 타이밍

Node Monitor Period:     5초 (상태 체크 간격)
Node Monitor Grace:     40초 (응답 없으면 unreachable)
Pod Eviction Timeout:    5분 (unreachable 노드의 pod 퇴출)

설정 확인

# kubeadm 환경
cat /etc/kubernetes/manifests/kube-controller-manager.yaml
 
# 프로세스 확인
ps -aux | grep kube-controller-manager

15. Kube Scheduler

공식문서: Kubernetes Scheduler

  • Pod를 어느 노드에 배치할지 결정만 함 (실제 배치는 Kubelet이 담당)

스케줄링 2단계

1단계: Filter (필터링)
   → 리소스 부족한 노드 제외
   
2단계: Rank/Score (점수 매기기)  
   → 남은 노드들에 점수 부여
   → 예: pod 배치 후 남는 리소스가 많을수록 높은 점수

설정 확인

# kubeadm 환경
cat /etc/kubernetes/manifests/kube-scheduler.yaml
 
# 프로세스 확인
ps -aux | grep kube-scheduler

16. Kubelet

공식문서: kubelet Reference

  • Worker Node의 “선장” - 노드의 모든 활동을 관리
  • API Server로부터 지시를 받아 컨테이너 생성/삭제
  • 정기적으로 노드 및 pod 상태를 API Server에 보고

주요 역할

  1. 클러스터에 노드 등록
  2. 컨테이너 런타임(ContainerD 등)에 이미지 다운로드 및 컨테이너 실행 지시
  3. Pod/컨테이너 상태 모니터링 및 보고

kubeadm은 kubelet을 자동 배포하지 않음. Worker Node에 수동 설치 필요

# kubelet 프로세스 확인
ps -aux | grep kubelet

17. Kube Proxy

공식문서: kube-proxy Reference

  • 모든 노드에서 실행되는 네트워크 프로세스
  • Service 생성을 감시하고 iptables 규칙 설정
  • Pod 간 통신을 안정적으로 유지

동작 원리

  • Pod A (Node 1)Service IP (가상 IP) → iptables 규칙Pod B (Node 2)
  • Service에 IP가 할당되면, Kube Proxy가 각 노드의 iptables에 규칙 추가
  • 해당 Service IP로 향하는 트래픽을 실제 Pod IP로 포워딩

Kube Proxy는 DaemonSet으로 배포되어 모든 노드에서 실행됨

kubectl get daemonset -n kube-system | grep kube-proxy

18. Pods

공식문서: Pods

Pod란?

“Kubernetes에서 컨테이너를 직접 다루지 않고, 한 겹 감싸놓은 것”

왜 이렇게 감쌀까?

  • 컨테이너 하나로 끝나지 않는 경우가 많음 (앱 + 로그 수집기 같이 붙여 배포)
  • 같은 운명공동체로 묶으면 네트워크/볼륨 공유가 자연스러움
  • 스케줄링 단위를 통일해 관리 복잡도↓

비유: 컨테이너 = 선원, Pod = 선원이 일하는 작업 구역 — 한 방에 있는 선원끼리는 서로 바로 대화하고(localhost), 같은 물품 창고를 쓴다(volume).

  • Kubernetes에서 가장 작은 배포 단위
  • Pod = 하나의 애플리케이션 인스턴스

핵심 개념

  • 스케일링 = Pod 수 증가 (컨테이너 수 증가가 아님)
  • 보통 1 Pod = 1 컨테이너 (메인 애플리케이션)
  • Multi-container Pod도 가능 (보조/사이드카 컨테이너)

Pod 안의 컨테이너들은 같은 네트워크/볼륨 공유

  • Main Container — 보통 이것만 (1 Pod = 1 컨테이너 패턴)
  • Helper Container — 사이드카 등 보조 (선택)

kubectl 기본 명령

# Pod 생성 및 실행
kubectl run nginx --image nginx
 
# Pod 목록 조회
kubectl get pods
 
# Pod 상세 정보
kubectl describe pod nginx
 
# Pod 삭제
kubectl delete pod nginx

19. Pods with YAML

Kubernetes YAML 필수 4개 필드

apiVersion:  # API 버전
kind:        # 리소스 종류
metadata:    # 이름, 라벨 등 메타데이터
spec:        # 리소스 상세 사양

API Version 참고

kindapiVersion
Podv1
Servicev1
ReplicaSetapps/v1
Deploymentapps/v1

Pod YAML 예시

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
    type: front-end
spec:
  containers:
    - name: nginx-container
      image: nginx
# YAML로 Pod 생성
kubectl apply -f pod-definition.yml
 
# YAML로 Pod 정의 확인
kubectl get pod myapp-pod -o yaml

20. Demo - Pods with YAML

# 1. YAML 파일 작성
vim pod.yml
 
# 2. Pod 생성
kubectl apply -f pod.yml
 
# 3. 상태 확인
kubectl get pods
 
# 4. 상세 정보 확인 (이벤트, 컨테이너 상태 등)
kubectl describe pod myapp-pod
 
# 5. Pod 내부 로그 확인
kubectl logs myapp-pod

kubectl describe로 Pod 문제 디버깅 시 Events 섹션을 가장 먼저 확인


21-25. Practice Tests & Labs - Pods

# 유용한 명령어 모음
 
# 현재 네임스페이스의 pod 수 확인
kubectl get pods --no-headers | wc -l
 
# 특정 pod의 이미지 확인
kubectl describe pod <pod-name> | grep -i image
 
# pod 생성 (imperative)
kubectl run redis --image=redis
 
# YAML 파일 생성 (dry-run)
kubectl run redis --image=redis --dry-run=client -o yaml > redis-pod.yaml
 
# pod 수정
kubectl edit pod <pod-name>
 
# 강제 교체
kubectl replace --force -f pod.yaml

26. Recap - ReplicaSets

공식문서: ReplicaSet

ReplicaSet이란?

“Pod 개수를 원하는 숫자로 유지해주는 감시자”

왜 필요한가?

  • Pod는 노드 장애나 OOM 등으로 언제든 죽을 수 있음
  • 사람이 매번 재생성하면 SRE가 잠을 못 잠
  • ReplicaSet이 “replicas: 3” 선언하면 항상 3개로 자동 복구

Label/Selector로 동작: ReplicaSet은 자기가 만든 Pod가 아니어도 selector에 맞는 Pod라면 관리 대상으로 취급. 이미 떠있는 Pod를 흡수하기도 함.

Replication Controller vs ReplicaSet

구분Replication ControllerReplicaSet
apiVersionv1apps/v1
selector선택적필수 (matchLabels)
상태구버전 (deprecated)현재 권장

Replication Controller 정의

apiVersion: v1
kind: ReplicationController
metadata:
  name: myapp-rc
  labels:
    app: myapp
    type: front-end
spec:
  replicas: 3
  template:
    metadata:
      name: myapp-pod
      labels:
        app: myapp
        type: front-end
    spec:
      containers:
      - name: nginx-container
        image: nginx

ReplicaSet 정의

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-replicaset
  labels:
    app: myapp
    type: front-end
spec:
  replicas: 3
  selector:
    matchLabels:
      type: front-end
  template:
    metadata:
      name: myapp-pod
      labels:
        app: myapp
        type: front-end
    spec:
      containers:
      - name: nginx-container
        image: nginx

스케일링 방법

# 방법 1: YAML 파일 수정 후 교체
kubectl replace -f replicaset-definition.yml
 
# 방법 2: scale 명령어
kubectl scale --replicas=6 -f replicaset-definition.yml
kubectl scale --replicas=6 replicaset myapp-replicaset
 
# ReplicaSet 확인
kubectl get replicaset
kubectl describe replicaset myapp-replicaset

kubectl scale 명령어로 스케일링하면 YAML 파일에는 반영되지 않음


27-28. Labs - ReplicaSets

# ReplicaSet 조회
kubectl get rs
 
# ReplicaSet 상세 정보
kubectl describe rs <name>
 
# ReplicaSet 삭제 (관련 pod도 함께 삭제)
kubectl delete rs <name>
 
# ReplicaSet 수정
kubectl edit rs <name>
 
# YAML 에러 디버깅 팁
# apiVersion이 v1이면 에러 → apps/v1로 변경
# selector.matchLabels와 template.metadata.labels가 일치해야 함

29. Deployments

공식문서: Deployment

Deployment란?

“ReplicaSet을 감싼 배포 관리자”

ReplicaSet만 있어도 Pod 개수 유지는 되는데 왜 Deployment가 필요한가?

  • 이미지를 v1 → v2로 바꿀 때 하나씩 교체해서 다운타임 없이 업데이트하고 싶다
  • 문제 생기면 이전 버전으로 즉시 롤백하고 싶다
  • 배포 히스토리(revision)를 남기고 싶다

Deployment는 이걸 대신 해주는 고수준 리소스. 내부적으로 ReplicaSet을 새로 만들어 점진적으로 트래픽을 이동시킴.

비유: ReplicaSet = “항상 3명 있어”, Deployment = “3명에서 5명으로 서서히 바꿔줘, 문제 생기면 되돌려”

  • ReplicaSet 상위 개념으로, 롤링 업데이트, 롤백, 일시정지/재개 기능 제공
  • 프로덕션에서 가장 많이 사용하는 리소스

Deployment 정의

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
  labels:
    app: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2

Deployment YAML은 ReplicaSet YAML과 거의 동일 (kind만 다름)

주요 명령어

# 생성
kubectl create -f deployment-definition.yml
 
# 조회 (Deployment → ReplicaSet → Pod 계층 확인)
kubectl get deployments
kubectl get rs
kubectl get pods
 
# 모든 리소스 한번에 확인
kubectl get all
 
# 이미지 업데이트 (롤링 업데이트)
kubectl set image deployment/myapp-deployment nginx=nginx:1.16.0
 
# 롤아웃 상태 확인
kubectl rollout status deployment/myapp-deployment
 
# 롤아웃 히스토리
kubectl rollout history deployment/myapp-deployment
 
# 롤백
kubectl rollout undo deployment/myapp-deployment
 
# 스케일링
kubectl scale deployment myapp-deployment --replicas=5

30. Certification Tip!

# 시험에서 YAML 빠르게 생성하는 방법
 
# Pod
kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml
 
# Deployment
kubectl create deployment nginx --image=nginx --replicas=3 --dry-run=client -o yaml > deploy.yaml
 
# Service (ClusterIP)
kubectl expose pod nginx --port=80 --target-port=8080 --dry-run=client -o yaml > svc.yaml

--dry-run=client -o yaml 조합을 반드시 외워두기


31-32. Labs - Deployments

# Deployment 생성
kubectl create deployment httpd-frontend --image=httpd:2.4-alpine --replicas=3
 
# Deployment 상세 확인
kubectl describe deployment <name>
 
# Deployment가 관리하는 ReplicaSet과 Pod 확인
kubectl get all

33. Services

공식문서: Service

Service란?

“여러 Pod를 대표하는 고정 주소 + 로드밸런서”

왜 필요한가?

  • Pod는 재시작/재배포 시 IP가 바뀜 — 다른 Pod가 이 IP를 하드코딩할 수 없음
  • 동일한 앱이 여러 Pod로 떠 있는데, 요청을 알아서 분산해줘야 함

Service가 해결하는 것:

  1. 고정 DNS 이름 (web-service.default.svc.cluster.local)
  2. 고정 가상 IP (ClusterIP)
  3. selector 라벨로 대상 Pod 자동 묶기 + 부하 분산

Label/Selector가 Kubernetes의 모든 리소스 연결 방식의 핵심. Service → Pod, ReplicaSet → Pod, NetworkPolicy → Pod 전부 라벨로 연결.

  • Pod 간 통신 및 외부 접근을 위한 안정적인 엔드포인트 제공
  • Pod IP는 동적이므로 Service가 고정 접점 역할

Service 3가지 타입

타입외부 접근포함 관계용도
ClusterIP (기본)클러스터 내부 통신용 가상 IP
NodePort노드 IP:30000~32767ClusterIP + 외부 포트외부 테스트
LoadBalancerLB 외부 IPNodePort + 클라우드 LB프로덕션 외부

상위 타입은 하위 타입 기능을 모두 포함: LoadBalancer ⊃ NodePort ⊃ ClusterIP

NodePort 서비스 포트 개념

  1. 외부 사용자 → 노드 IP의 nodePort: 30008 접속
  2. (Node 내부) nodePort: 30008 → Service의 port: 80
  3. Service의 port: 80 → Pod의 targetPort: 80

외부 → 노드 → Service → Pod, 3단계 포트 매핑

NodePort 정의

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  type: NodePort
  ports:
  - port: 80        # Service 포트
    targetPort: 80   # Pod 포트
    nodePort: 30008  # 노드 포트 (30000-32767)
  selector:
    app: myapp
# Service 생성
kubectl create -f service-definition.yml
 
# Service 조회
kubectl get svc
 
# Service 상세
kubectl describe svc myapp-service

34. Services - ClusterIP

  • 기본 Service 타입 (type 생략 시 ClusterIP)
  • 클러스터 내부에서만 접근 가능한 안정적 IP 제공
  • 마이크로서비스 간 통신에 사용

멀티 티어 애플리케이션 예시

  • Frontend Podsfrontend-svc (ClusterIP) → Backend Podsbackend-svc (ClusterIP) → DB Pods
  • Pod 간 통신을 직접 IP 대신 Service를 거쳐 안정적으로 — Pod IP가 바뀌어도 영향 없음
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: backend

DNS 기반 접근

# 같은 namespace 내
backend-service
 
# 다른 namespace
backend-service.default.svc.cluster.local

Headless Service

# 개별 Pod IP에 직접 접근이 필요한 경우 (예: StatefulSet)
spec:
  clusterIP: None
  selector:
    app: db
  ports:
  - port: 3306

35. Services - LoadBalancer

  • 클라우드 환경에서 외부 트래픽 분산을 위한 Service 타입
  • 클라우드 프로바이더의 LB와 자동 연동 (AWS ELB, Azure LB, GCP LB)

NodePort vs LoadBalancer

구분NodePortLoadBalancer
외부 접근노드IP:포트LB의 외부 IP
포트 범위30000-32767표준 포트 (80, 443)
IP 안정성노드 장애 시 변경안정적 외부 IP
클라우드 필요XO
비용무료유료 (클라우드 과금)
용도테스트/내부프로덕션/공개
apiVersion: v1
kind: Service
metadata:
  name: voting-service
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: voting-app

온프레미스 환경에서는 MetalLB 같은 오픈소스 LB 구현체 사용 가능


36-37. Labs - Services

# Service 조회
kubectl get svc
 
# Deployment를 Service로 노출
kubectl expose deployment webapp --type=NodePort --port=8080 --name=webapp-service
 
# Service 접근 테스트
curl <node-ip>:<node-port>

Service 생성 3가지 방법 비교 (시험 필수)

방법장점한계Selector
kubectl run --exposePod + Service 한 번에ClusterIP만, 옵션 제한자동 추출
kubectl expose기존 리소스 기반 빠름nodePort 직접 지정 불가기존 리소스에서 자동 추출
kubectl create servicenodePort 지정 가능, 세밀 제어selector 수동 지정 필요이름과 동일하게 자동

방법 1: kubectl run —expose (Pod + Service 동시)

# Pod 생성과 동시에 ClusterIP Service 생성
kubectl run nginx --image=nginx --port=80 --expose
# → Pod "nginx" + Service "nginx" (ClusterIP, port 80)
 
# 한계: ClusterIP만 지원, NodePort 불가

방법 2: kubectl expose (권장 - 기존 리소스)

# ── 기본 (ClusterIP) ──────────────────────────────────────
kubectl expose pod redis --port=6379 --name=redis-svc
kubectl expose deploy nginx --port=80 --name=web-svc
 
# ── NodePort ──────────────────────────────────────────────
kubectl expose deploy nginx --port=80 --type=NodePort --name=web-np
# ❌ 한계: --node-port 옵션 없음 → 무작위 할당됨 (30000-32767 중)
 
# ── LoadBalancer ──────────────────────────────────────────
kubectl expose deploy nginx --port=80 --type=LoadBalancer
 
# ── targetPort 지정 ───────────────────────────────────────
kubectl expose deploy web --port=80 --target-port=8080
 
# ── YAML 뽑아서 nodePort 수정 ─────────────────────────────
kubectl expose deploy nginx --port=80 --type=NodePort --dry-run=client -o yaml > svc.yaml
# vi svc.yaml에서 ports 아래 nodePort: 30080 추가

방법 3: kubectl create service (NodePort 지정 필요시)

# ── ClusterIP ─────────────────────────────────────────────
kubectl create service clusterip my-svc --tcp=80:8080
 
# ── NodePort (nodePort 직접 지정 가능!) ───────────────────
kubectl create service nodeport my-svc --tcp=80:8080 --node-port=30080
 
# ── LoadBalancer ──────────────────────────────────────────
kubectl create service loadbalancer my-svc --tcp=80:8080
 
# ── ExternalName ──────────────────────────────────────────
kubectl create service externalname my-db --external-name=db.example.com
 
# ── Headless Service ──────────────────────────────────────
kubectl create service clusterip my-svc --clusterip=None --tcp=80:80

NodePort를 정확히 지정해야 하면 kubectl create service nodeport --node-port=XXXXX 사용. kubectl expose 는 nodePort 옵션이 없음.

Selector 차이 주의

# expose: 기존 리소스의 selector를 그대로 승계
kubectl expose deploy web --port=80
# → Service selector는 deploy의 matchLabels 그대로
 
# create service: Service 이름과 동일한 selector로 자동 설정
kubectl create service clusterip my-svc --tcp=80:80
# → selector: app=my-svc (Pod에 이 라벨이 있어야 연결됨)
# → 기존 Pod 라벨이 다르면 Endpoint 안 잡힘 → 수정 필요

38. Namespaces

공식문서: Namespaces

Namespace란?

“하나의 클러스터를 여러 개의 ‘논리적 공간’으로 나누는 폴더 같은 것”

왜 필요한가?

  • 개발/스테이징/운영 환경을 한 클러스터 안에서 분리하고 싶다
  • 팀별로 리소스 이름 충돌을 방지 (A팀 web, B팀 web이 공존)
  • 리소스 사용량(CPU/메모리) 팀별로 쿼터 제한 가능
  • RBAC으로 팀별 접근 권한 분리

무엇이 namespace를 가지나?

  • Pod, Service, Deployment, ConfigMap, Secret 등 대부분의 리소스
  • 반면 Node, PV, ClusterRole 등 클러스터 전역 리소스는 namespace 없음

기본 4개 namespace는 클러스터 생성과 동시에 만들어짐. default는 사용자용, 나머지는 시스템용.

  • 클러스터 내 리소스를 논리적으로 분리하는 가상 클러스터

기본 Namespace

Namespace용도
default기본 작업 공간
kube-systemKubernetes 시스템 컴포넌트
kube-public모든 사용자 접근 가능한 리소스
kube-node-lease노드 하트비트 관리

리소스 접근 방식

# 같은 namespace 내
mysql.connect("db-service")
 
# 다른 namespace
mysql.connect("db-service.dev.svc.cluster.local")
db-service . dev . svc . cluster.local
─────────   ───   ───   ────────────
서비스 이름   NS   서비스   도메인

Namespace 명령어

# 특정 namespace의 pod 조회
kubectl get pods -n kube-system
 
# 모든 namespace의 pod 조회
kubectl get pods --all-namespaces
kubectl get pods -A
 
# Namespace 생성
kubectl create namespace dev
 
# 기본 namespace 변경
kubectl config set-context --current --namespace=dev

ResourceQuota (네임스페이스 리소스 제한)

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: dev
spec:
  hard:
    pods: "10"
    requests.cpu: "4"
    requests.memory: 5Gi
    limits.cpu: "10"
    limits.memory: 10Gi

39-40. Labs - Namespaces

# namespace 목록
kubectl get ns
 
# 특정 namespace의 pod 수
kubectl get pods -n <namespace> --no-headers | wc -l
 
# 다른 namespace에 리소스 생성
kubectl run redis --image=redis -n finance
 
# YAML에서 namespace 지정
metadata:
  name: myapp
  namespace: dev

41. Imperative vs Declarative

Imperative (명령형)

  • 어떻게 할지 하나하나 지시 (How)
  • 빠르고 간편하지만, 추적/재현 어려움
# Imperative 명령 예시
kubectl run nginx --image=nginx
kubectl create deployment nginx --image=nginx --replicas=3
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl set image deployment/nginx nginx=nginx:1.18
kubectl scale deployment nginx --replicas=5
kubectl edit deployment nginx

Declarative (선언형)

  • 무엇을 원하는지 선언 (What)
  • YAML 파일로 원하는 상태를 정의하고 kubectl apply로 적용
  • GitOps, 버전 관리에 적합
# Declarative 방식
kubectl apply -f nginx.yaml
kubectl apply -f /path/to/configs/

비교

구분ImperativeDeclarative
방식명령어로 직접 실행YAML 파일 + apply
추적어려움Git으로 관리 가능
시험O (빠른 작업에 유리)O (복잡한 작업에 유리)
프로덕션비추천권장

CKA 시험에서는 Imperative + Declarative 모두 잘 활용해야 함

  • 간단한 작업: Imperative (kubectl run, kubectl create)
  • 복잡한 작업: --dry-run=client -o yaml로 YAML 생성 후 수정

42. Certification Tips - Imperative Commands with Kubectl

# Pod 생성
kubectl run nginx --image=nginx --port=80 --labels="tier=frontend"
 
# Deployment 생성
kubectl create deployment webapp --image=nginx --replicas=3
 
# Service 생성 (ClusterIP)
kubectl expose pod redis --port=6379 --name=redis-service
 
# Service 생성 (NodePort) - YAML 생성 후 nodePort 수동 추가
kubectl expose pod nginx --port=80 --type=NodePort --name=nginx-service --dry-run=client -o yaml > svc.yaml
 
# Namespace 생성
kubectl create namespace dev-ns
 
# ConfigMap 생성
kubectl create configmap app-config --from-literal=key1=value1
 
# Secret 생성
kubectl create secret generic app-secret --from-literal=password=pass123

43. Kubectl Explain Command

# 리소스 필드 설명 확인
kubectl explain pod
kubectl explain pod.spec
kubectl explain pod.spec.containers
kubectl explain deployment.spec.strategy
 
# 재귀적으로 모든 필드 확인
kubectl explain pod --recursive | less

시험 중 YAML 필드가 기억나지 않을 때 kubectl explain 활용


44-45. Labs - Imperative Commands

# 유용한 조합 패턴
 
# 1. dry-run으로 YAML 생성 → 수정 → 적용
kubectl run custom-nginx --image=nginx --port=8080 --dry-run=client -o yaml > custom.yaml
vim custom.yaml
kubectl apply -f custom.yaml
 
# 2. Deployment + expose 한번에
kubectl create deployment redis-deploy --image=redis --replicas=2 -n dev-ns
 
# 3. Pod를 Service로 노출
kubectl run httpd --image=httpd:alpine --port=80 --expose
# 위 명령은 Pod와 ClusterIP Service를 동시에 생성

46. Kubectl Apply Command

3-way Merge 동작 원리

kubectl apply는 3가지 설정을 비교하여 변경사항을 결정:

1. Local YAML 파일 (로컬에 저장된 파일)
2. Live Object Config (클러스터에 실제 존재하는 설정)
3. Last Applied Config (마지막으로 apply한 설정 - annotation에 JSON으로 저장)

Local YAML 과 Last Applied Config 두 입력을 함께 비교 → Live Object 에 어떤 필드를 추가/수정/삭제할지 결정

Last Applied Config는 Live Object의 metadata.annotationskubectl.kubernetes.io/last-applied-configuration 키로 JSON 형태로 저장됨

kubectl createkubectl replace는 Last Applied Config를 저장하지 않음. Declarative 방식에서는 항상 kubectl apply 사용


47-49. 마무리

  • Core Concepts는 CKA 시험의 기본이 되는 가장 중요한 섹션
  • 모든 컴포넌트의 역할과 관계를 이해하는 것이 핵심
  • Practice Test를 반복하여 명령어에 익숙해지기

핵심 컴포넌트 요약 표

컴포넌트위치핵심 역할
ETCDMaster클러스터 상태 저장소
API ServerMaster모든 통신의 중앙 허브
SchedulerMasterPod 배치 결정
Controller ManagerMaster원하는 상태 유지
KubeletWorker컨테이너 관리 실행
Kube ProxyWorker네트워크 규칙 관리

핵심 리소스 계층 구조

graph TD
    DEP["Deployment<br/>배포 관리, 롤링 업데이트"] --> RS["ReplicaSet<br/>복제본 수 유지"]
    RS --> POD["Pod<br/>컨테이너 실행 단위"]
    POD --> CTR["Container<br/>실제 애플리케이션"]

    SVC["Service (네트워크 접근점)"] --> CIP["ClusterIP<br/>내부 통신"]
    SVC --> NP["NodePort<br/>외부 테스트"]
    SVC --> LB["LoadBalancer<br/>프로덕션 외부 접근"]