
생성 수정
Kubernetes · 1장
쿠버네티스 이론
손을 대기 전에 그림을 먼저 그린다. 오케스트레이터가 필요한 이유, 선언형 API와 제어 루프, 클러스터를 이루는 부품과 핵심 객체를 정리한다.
1장 · 총 8개 절 · 전체 9개 장 중 1번째
컨테이너에서 오케스트레이션으로
1장 · 01
컨테이너는 "어디서 실행해도 같게"를 풀었습니다. 남은 문제는 그 다음입니다 — 수십 개의 컨테이너를 어느 서버에 배치하고, 죽으면 누가 살리고, 버전을 바꾸는 동안 서비스는 어떻게 유지하는가. 오케스트레이터는 이 반복 노동을 대신 맡는 층입니다.
- docker run 은 한 대에서 한 개를 띄우는 명령이다 — 배치·복구·확장은 사람 몫으로 남는다
- 서버가 여러 대가 되는 순간 "어디에 띄울지" 정하는 스케줄러가 필요해진다
- 장애는 예외가 아니라 일상이다 — 복구를 사람의 대응 속도에 맡기지 않는 것이 출발점이다
- 쿠버네티스는 구글의 Borg 운영 경험에서 나왔고 지금은 CNCF가 관리하는 사실상의 표준이다
- 표준이라는 말의 실질 — 온프레미스든 AWS든 같은 YAML과 같은 kubectl 명령이 통한다
사람이 하던 일이 어디까지 넘어가는가
컨테이너만 있을 때
어느 서버에 띄울지
사람이 고른다
죽으면 다시 띄우기
알림 보고 사람이 대응
트래픽 늘면 늘리기
사람이 명령
새 버전 교체
내리고 올리는 순서를 사람이
오케스트레이터가 있을 때
스케줄러
자원·제약을 보고 배치
레플리카셋 컨트롤러
개수를 계속 맞춘다
replicas 값 하나
선언만 바꾸면 된다
롤링 업데이트
준비된 뒤 교체·되돌리기
도커 컴포즈와 무엇이 다른가
둘 다 여러 컨테이너를 한 번에 다루지만 경계가 다르다 — 컴포즈는 한 대(호스트)를, 쿠버네티스는 여러 대(클러스터)를 전제한다.
| 기준 | 도커 컴포즈 | 쿠버네티스 |
|---|---|---|
| 대상 범위 | 호스트 한 대 | 노드 여러 대로 이루어진 클러스터 |
| 장애 복구 | restart 정책까지 | 스케줄러가 다른 노드에 다시 배치 |
| 확장 | 한 대 안에서 scale | 노드를 가로질러 수평 확장 |
| 배포 전략 | 직접 내리고 올린다 | 롤링 업데이트·롤백이 기본 기능 |
| 쓰는 자리 | 로컬 개발·단일 서버 | 운영 클러스터·다중 노드 |
쿠버네티스 객체 — 컨테이너·파드·네임스페이스
1장 · 02
컨테이너는 실행되는 프로세스이고, 파드는 쿠버네티스가 관리하는 최소 단위입니다 — 둘은 대체 관계가 아니라 포함 관계입니다. 그 파드를 감싸는 바깥 경계가 네임스페이스이고, 클러스터는 이 경계로 리소스를 논리적으로 나눕니다.
- 컨테이너는 실행되는 프로세스, 파드는 그 프로세스(들)를 쿠버네티스가 관리하도록 감싼 최소 단위다 — 포함 관계이지 대체 관계가 아니다
- 같은 파드 안 컨테이너들은 네트워크·볼륨을 공유하고 생사를 함께한다 — 하나가 죽으면 파드 전체가 다시 스케줄링된다
- 파드는 되살아나지 않는다 — 디플로이먼트가 만드는 것은 같은 파드가 아니라 새 IP를 가진 새 파드다
- 여러 컨테이너를 한 파드에 묶는 대표적인 이유는 사이드카 패턴이다 — 로그 수집기나 Istio 프록시처럼 본체는 그대로 두고 기능만 옆에 붙인다
- 1.24부터 쿠버네티스는 도커 엔진을 직접 부르지 않는다(dockershim 제거, containerd·CRI-O 사용) — 그래도 OCI 이미지 표준 덕분에 docker build 로 만든 이미지는 그대로 호환된다
- 네임스페이스는 파드를 논리적으로 가르는 경계다 — default 는 사용자 워크로드, kube-system 은 클러스터 자체 부품이 쓴다
- "필요할 때만 생성된다"는 서버리스(Cloud Run·Lambda)를 설명하는 말이지 쿠버네티스의 기본 동작이 아니다 — replicas: 3 이면 트래픽이 없어도 파드 3개는 계속 떠 있다
그림으로 보는 포함 관계 — 네임스페이스 안의 파드, 파드 안의 컨테이너

볼륨이 파드 안에 있는 이유 — 컨테이너 안이 아니라 파드 레벨에 붙어 있어야 같은 파드의 컨테이너들이 볼륨을 공유할 수 있습니다. 사이드카가 앱 로그를 읽어가는 것도 이 구조 덕분입니다.
kube-system 은 건드리지 마세요 — 쿠버네티스가 자기 자신을 돌리는 데 쓰는 네임스페이스입니다. CoreDNS·kube-proxy 같은 부품이 여기 있고, K3s 라면 Traefik 도 들어갑니다. 실습에서 잘못 지우면 클러스터가 멈춥니다.
metallb-system 은 기본 구성이 아닙니다 — 온프레미스 클러스터에서 LoadBalancer 타입 서비스를 쓰려고 따로 설치하는 것입니다. 클라우드에서는 프로바이더가 로드밸런서를 붙여주지만 온프레미스에는 그게 없어 MetalLB 가 대신합니다. K3s 에는 ServiceLB(Klipper)가 기본 내장이라 굳이 안 깔아도 됩니다.
서비스가 왼쪽에서 세로로 걸쳐 있는 이유 — 서비스는 네임스페이스 안에 속하지만, 파드 IP 가 계속 바뀌어도 변하지 않는 접점 역할을 합니다. 앞서 말한 "파드는 가축"이라는 개념이 여기서 그림으로 드러납니다.
| 네임스페이스 | 보통 담기는 것 |
|---|---|
| default | 사용자가 만드는 워크로드 — 별도 지정 없으면 여기로 간다 |
| kube-system | CoreDNS·kube-proxy 등 클러스터 자체 부품(K3s 는 Traefik 도) — 함부로 지우면 클러스터가 멈춘다 |
| metallb-system | 온프레미스에서 LoadBalancer 타입 서비스를 쓰려고 따로 설치하는 애드온(K3s 는 ServiceLB 내장이라 없어도 된다) |
컨테이너와 파드 — 네 가지 핵심 차이
컨테이너는 실행되는 프로세스, 파드는 쿠버네티스가 관리하는 최소 단위입니다. 대체 관계가 아니라 포함 관계입니다.
| 도커 컨테이너 하나 | 파드 | |
|---|---|---|
| 여러 개를 묶으면 | 독립된 네트워크·스토리지 | 같은 IP·볼륨을 공유 |
| 하나가 죽으면 | 그 컨테이너만 재시작 | 파드 전체가 생사를 함께한다 |
| 복구 방식 | 같은 컨테이너를 재시작 | 같은 파드가 아니라 새 IP의 새 파드 |
| 실행 방식 | docker run 명령형 | YAML 로 선언한 상태 |
왜 굳이 파드로 묶는가 — 사이드카
본체 컨테이너는 그대로 두고, 로그 수집기나 Istio 프록시 같은 보조 기능을 같은 파드 안 옆 컨테이너로 붙입니다. 네트워크·볼륨을 공유하므로 보조 컨테이너가 본체의 로그 파일이나 트래픽을 바로 볼 수 있습니다.
한 가지 오해 — 쿠버네티스는 도커를 직접 쓰지 않는다
1.24부터 dockershim 이 제거돼 containerd·CRI-O 로 컨테이너를 실행합니다. 그래도 docker build 로 만든 이미지가 그대로 도는 이유는 이미지 포맷이 도커 고유가 아니라 OCI(Open Container Initiative) 표준이기 때문입니다 — docker buildx 로 만들어 GHCR 같은 레지스트리에 올린 이미지를 쿠버네티스가 그대로 당겨 씁니다.
파드는 "필요할 때만 생성"이 아니라 "언제든 교체될 수 있다"
"필요할 때만 생성된다"는 서버리스(Cloud Run·Lambda)를 설명하는 말입니다. 디플로이먼트의 replicas: 3 은 트래픽이 있든 없든 파드 3개를 항상 유지합니다 — 요청이 없어도 파드는 떠 있고, 수요에 따라 늘리려면 HPA·KEDA 같은 오토스케일러를 별도로 붙여야 합니다(뒤 장의 k3s 실습에서 다룬다).
| 반려동물(pets) | 가축(cattle) — 쿠버네티스 파드 | |
|---|---|---|
| 관리 대상 | 이름 붙여 개별 관리 | 번호로 관리, 서로 대체 가능 |
| 죽으면 | 치료해서 되살린다 | 같은 것을 되살리지 않고 새로 만든다 |
| IP·이름 | 고정, 애착을 갖는다 | 바뀌어도 상관없다 — 서비스가 가린다 |
| 애착 | 있다 | 없다 — 언제든 교체될 수 있다는 전제로 설계한다 |
선언형 API와 제어 루프
1장 · 03
쿠버네티스를 이해하는 핵심 한 문장은 "명령하지 않고 선언한다"입니다. 사용자는 원하는 상태(spec)를 YAML로 제출하고, 컨트롤러는 현재 상태(status)를 그 선언에 맞추려 끊임없이 돌아갑니다.
- 명령형 — "컨테이너 3개를 띄워라". 실행 시점의 동작만 있고 그 뒤는 책임지지 않는다
- 선언형 — "컨테이너가 항상 3개여야 한다". 하나가 죽으면 시스템이 스스로 채운다
- 그래서 kubectl apply 는 "실행"이 아니라 "등록"에 가깝다 — 여러 번 적용해도 결과가 같다(멱등)
- 손으로 고친 상태는 다음 조정 주기에 되돌려진다 — 변경은 선언(YAML) 쪽에서 해야 한다
- 모든 리소스가 spec(원하는 상태)과 status(현재 상태)를 갖는다 — 이 대비가 전체 설계의 뼈대다
제어 루프 — 끝나지 않는 세 단계
관찰 (observe)
현재 상태를 읽는다
비교 (diff)
spec 과 status 의 차이
조정 (act)
차이를 메우는 동작
다시 관찰
루프는 멈추지 않는다
모든 객체가 갖는 네 부분
apiVersion: apps/v1 # 이 객체를 다루는 API 그룹과 버전
kind: Deployment # 객체의 종류
metadata: # 이름·네임스페이스·라벨 등 식별 정보
name: web
spec: # 원하는 상태 — 사람이 적는 부분
replicas: 3
# status: # 현재 상태 — 시스템이 채우는 부분(사람이 적지 않는다)클러스터 구성 — 컨트롤 플레인과 노드
1장 · 04
클러스터는 결정을 내리는 컨트롤 플레인과, 실제로 컨테이너를 실행하는 워커 노드로 나뉩니다. 사용자의 모든 요청은 API 서버 하나를 거치고, 클러스터의 모든 상태는 etcd 한 곳에 저장됩니다.
- kube-apiserver — 유일한 출입구. kubectl·컨트롤러·kubelet 모두 여기를 통해서만 대화한다
- etcd — 클러스터의 단일 진실 공급원. 여기가 날아가면 상태가 사라진다(백업 1순위)
- kube-scheduler — 새 파드를 어느 노드에 놓을지 정한다(자원 요청과 제약 조건을 본다)
- kube-controller-manager — 각종 컨트롤러의 제어 루프를 한 프로세스에서 돌린다
- kubelet — 각 노드에서 파드를 실제로 띄우고 상태를 보고하는 에이전트
- kube-proxy·CNI — 노드 간 네트워크와 서비스 트래픽 전달을 담당한다
- 컨테이너 런타임 — containerd·CRI-O 등(도커 엔진 직접 연동은 1.24에서 제거됐다)
클러스터 구성도
컨트롤 플레인
kube-apiserver
유일한 출입구
etcd
상태 저장소
scheduler
배치 결정
controller-manager
제어 루프
워커 노드 1
kubelet
파드 실행·보고
kube-proxy
서비스 트래픽
런타임
containerd
파드들
실제 컨테이너
워커 노드 2
kubelet
파드 실행·보고
kube-proxy
서비스 트래픽
런타임
containerd
파드들
실제 컨테이너
요청 하나가 지나가는 길
- 1kubectl apply -f web.yaml인증·인가·검증을 거쳐 API 서버로
- 2API 서버 → etcd원하는 상태를 기록한다
- 3스케줄러노드가 정해지지 않은 파드를 발견해 노드를 배정
- 4kubelet배정을 감지해 런타임에 컨테이너 실행을 요청
- 5API 서버 → etcd실행 결과가 status 로 되돌아온다
워크로드 객체 — 파드·레플리카셋·디플로이먼트
1장 · 05
실습에서 직접 만들 객체는 사실상 셋입니다 — 디플로이먼트, 서비스, 그리고 필요할 때의 설정·볼륨. 파드는 결과로 생기는 것이지 손으로 만드는 것이 아닙니다.
- 파드(Pod) — 스케줄링의 최소 단위. 같은 IP·볼륨을 공유하는 컨테이너 묶음이다
- 레플리카셋(ReplicaSet) — 같은 파드를 몇 개 유지할지 책임진다. 사람이 직접 만들지 않는다
- 디플로이먼트(Deployment) — 레플리카셋을 세대별로 관리해 롤링 업데이트·롤백을 가능하게 한다
- 라벨(label)과 셀렉터(selector)가 이 모든 것을 잇는다 — 서비스가 파드를 찾는 방법도 라벨이다
- 그래서 파드를 지워도 사라지지 않는다 — 지운 것은 결과물이고, 선언은 위층에 남아 있다
디플로이먼트가 파드까지 내려오는 층
Deployment — web
버전과 세대를 관리한다 (replicas: 3)
ReplicaSet — web-5dd9d5dc5b
이 세대의 파드 개수를 3으로 유지한다
Pod
app=web
Pod
app=web
Pod
app=web
워크로드 종류 — 무엇을 쓸지 고르는 기준
| 종류 | 쓰는 자리 | 특징 |
|---|---|---|
| Deployment | 웹·API 같은 무상태 앱 | 개수 유지 + 롤링 업데이트·롤백 |
| StatefulSet | DB처럼 상태를 가진 앱 | 파드 이름과 저장소가 고정된다 |
| DaemonSet | 로그 수집·모니터링 에이전트 | 모든 노드에 하나씩 배치 |
| Job / CronJob | 끝나는 작업 · 주기 작업 | 완료가 목표다(계속 떠 있지 않는다) |
네트워킹 — 서비스·인그레스·클러스터 DNS
1장 · 06
네트워킹의 전제는 "모든 파드는 서로 통신할 수 있고, 파드 IP는 언제든 바뀐다"입니다. 그래서 IP가 아니라 이름으로 부르는 층이 필요하고, 서비스와 클러스터 DNS가 그 역할을 맡습니다.
- 서비스(Service) — 라벨로 파드 묶음을 고르고 그 앞에 고정 이름·고정 IP를 둔다
- 클러스터 DNS(CoreDNS) — <서비스>.<네임스페이스>.svc.cluster.local 로 이름이 풀린다
- 인그레스(Ingress) — 호스트·경로 규칙으로 여러 서비스를 한 진입점 뒤에 모으고 TLS를 종료한다
- 인그레스는 객체일 뿐이고 트래픽은 인그레스 컨트롤러(Traefik·NGINX)가 처리한다 — 컨트롤러가 없으면 아무 일도 일어나지 않는다
- port-forward 는 노출이 아니라 디버깅용 임시 터널이다(6장에서 쓴 그것이다)
바깥에서 파드까지 오는 길
사용자
브라우저
Ingress
host·path 규칙, TLS
Service
고정 이름 · selector: app=web
Pod
10.42.0.7
Pod
10.42.1.3
서비스 타입 — 어디까지 열 것인가
| 타입 | 접근 범위 | 쓰는 자리 |
|---|---|---|
| ClusterIP | 클러스터 내부만(기본값) | 백엔드·DB 등 내부 통신 |
| NodePort | 노드의 30000~32767 포트 | 실습에서 가장 빠른 외부 확인(6장에서 쓴 방식) |
| LoadBalancer | 외부 로드밸런서 주소 | 클라우드, 또는 K3s의 ServiceLB·MetalLB |
| Ingress | 80/443 한 진입점 뒤 | 도메인·경로로 여러 서비스를 가를 때 |
설정과 스토리지 — 컨피그맵·시크릿·볼륨
1장 · 07
이미지는 불변이어야 하고, 환경마다 달라지는 값과 남아야 하는 데이터는 이미지 바깥에 둡니다. 설정은 컨피그맵·시크릿으로, 데이터는 볼륨과 PVC로 분리합니다.
- 컨피그맵(ConfigMap) — 평문 설정값. 환경변수 또는 파일로 파드에 주입한다
- 시크릿(Secret) — 비밀번호·토큰. base64 인코딩일 뿐 암호화가 아니다(RBAC·저장소 암호화가 함께 필요하다)
- 볼륨(Volume) — 파드 수명에 묶인 저장 공간. emptyDir 은 파드와 함께 사라진다
- PVC/PV — 저장 공간에 대한 요청서(PVC)와 실제 공간(PV)을 분리해 다룬다
- 스토리지클래스 — PVC가 오면 볼륨을 자동으로 만들어주는 규칙(동적 프로비저닝)
- 원칙 한 줄 — 설정은 코드가 아니라 환경에 있다
파드 안에 두지 않는 것들
ConfigMap
LOG_LEVEL=info
Secret
API_KEY=***
PVC
1Gi 요청
Pod
env
환경변수로 주입
volumeMounts
파일·디렉터리로 마운트
파드가 사라져도 위 세 가지는 남는다
배포판 고르기 — 도커 데스크톱·미니쿠베·K3s·kubeadm
1장 · 08
쿠버네티스는 하나의 제품이 아니라 규격에 가깝습니다. 같은 API를 여러 배포판이 다른 방식으로 구현하고, 목적에 따라 고를 배포판이 달라집니다. 이 시리즈가 다음 네 장에서 밟는 순서가 곧 그 선택지입니다.
- 5장 도커 데스크톱 — 이미 깔린 도구의 체크박스 하나로 클러스터를 켠다. 가장 빠른 출발점이다
- 6장 미니쿠베 — 도커 데스크톱 밖에서 클러스터를 띄운다. 버전을 직접 고를 수 있다
- 7장 K3s — 단일 바이너리 경량 배포판. 실제 서버에 올려 노드를 붙여본다
- 8장 K8s(kubeadm) — 표준 부품을 직접 조립해 컨트롤 플레인을 뜯어본다
- 9장 헬름 — 배포판이 아니라 그 위에서 매니페스트를 패키징하는 도구다
- 어느 쪽을 고르든 kubectl·YAML·개념은 같다 — 배운 것이 그대로 옮겨간다는 것이 표준의 값어치다
이 시리즈가 가는 길
1장 이론
지금 여기
2~4장 종합 개요
구조·객체·운영
5장 도커 데스크톱
체크박스 하나
6장 미니쿠베
노트북 한 대
7장 K3s
서버·다중 노드
8장 K8s
부품을 직접 조립
9장 헬름
패키징해서 배포
LangTailor