Kubernetes Overview
컨테이너 오케스트레이션의 사실상 표준 — 선언적, 자가치유, 수평 확장
📌 이 글의 목적
Docker로 컨테이너를 실행할 수 있지만, 컨테이너가 수십~수천 개로 늘어나면 **"어떤 서버에 어떤 컨테이너를 배치하고, 장애 시 어떻게 복구하고, 어떻게 스케일링할 것인가"**를 자동으로 관리해야 함. 이것이 오케스트레이션이고, Kubernetes(K8s)가 그 표준임.
이 글을 읽고 나면:
- K8s가 해결하는 문제와 핵심 설계 원칙을 설명할 수 있음
- Control Plane과 Worker Node의 역할을 이해할 수 있음
- 주요 오브젝트(Pod, Deployment, Service 등)의 관계를 파악할 수 있음
- Docker Compose에서 K8s로의 전환 맥락을 이해할 수 있음
1. Kubernetes란
1.1 역사
timeline
title Kubernetes 역사
2003~2004 : Google 내부에서 Borg 시스템 운영 (컨테이너 오케스트레이션 원조)
2013 : Docker 등장 — 컨테이너 대중화
2014 : Google이 Borg 경험을 바탕으로 Kubernetes 오픈소스로 공개
2015 : CNCF(Cloud Native Computing Foundation) 설립, K8s를 첫 번째 프로젝트로 기증
2016 : K8s 1.0+ 안정화. Docker Swarm, Mesos와 경쟁
2017 : AWS EKS, Azure AKS 발표. 오케스트레이션 전쟁 사실상 K8s 승리
2018 : CNCF 졸업 프로젝트. 업계 표준으로 확립
2020 : K8s 1.20 — Dockershim 제거 예고 (containerd/CRI-O 전환)
2022 : K8s 1.24 — Dockershim 공식 제거
2024~2025 : Gateway API GA, Sidecar Container 지원, AI 워크로드 지원 강화
1.2 K8s가 해결하는 문제
| 문제 | Docker 단독 | Kubernetes |
|---|---|---|
| 다수 컨테이너 관리 | 수동 (docker run 반복) | 선언적 관리 (YAML로 원하는 상태 정의) |
| 컨테이너 장애 복구 | 수동 재시작 | 자가치유 (자동 재시작, 재스케줄링) |
| 스케일링 | 수동 | 자동 수평 확장 (HPA) |
| 서비스 디스커버리 | docker-compose 네트워크 | DNS 기반 서비스 디스커버리 |
| 로드밸런싱 | 외부 LB 필요 | Service, Ingress 내장 |
| 롤링 업데이트 | 수동 | Deployment 기반 자동 롤링 업데이트/롤백 |
| 설정 관리 | 환경변수, .env 파일 | ConfigMap, Secret |
| 스토리지 | docker volume | PV/PVC, StorageClass (동적 프로비저닝) |
| 멀티 호스트 | Docker Swarm (사실상 사장) | 클러스터 네이티브 |
1.3 핵심 설계 원칙
| 원칙 | 설명 |
|---|---|
| 선언적 (Declarative) | "3개의 nginx를 실행해라"가 아니라 "nginx가 3개인 상태를 유지해라" |
| 자가치유 (Self-healing) | Pod가 죽으면 자동으로 재생성 |
| 수평 확장 (Horizontal Scaling) | 부하에 따라 Pod 수를 자동 조절 |
| 불변 인프라 (Immutable) | 컨테이너를 수정하지 않고 새 버전으로 교체 |
| API 중심 | 모든 것이 API 오브젝트. kubectl은 API Server의 클라이언트 |
| 플러그인 아키텍처 | 네트워크(CNI), 스토리지(CSI), 런타임(CRI) 모두 플러그인 |
2. 아키텍처 전체 그림
2.1 클러스터 구조
flowchart TB
User["사용자<br/>(kubectl)"]
subgraph ControlPlane["Control Plane (Master)"]
APIServer["API Server<br/>(kube-apiserver)"]
etcd["etcd<br/>(분산 KV 저장소)"]
Scheduler["Scheduler<br/>(kube-scheduler)"]
CM["Controller Manager<br/>(kube-controller-manager)"]
end
subgraph Worker1["Worker Node 1"]
Kubelet1["kubelet"]
KubeProxy1["kube-proxy"]
Runtime1["Container Runtime<br/>(containerd)"]
Pod1A["Pod A"]
Pod1B["Pod B"]
end
subgraph Worker2["Worker Node 2"]
Kubelet2["kubelet"]
KubeProxy2["kube-proxy"]
Runtime2["Container Runtime"]
Pod2A["Pod C"]
Pod2B["Pod D"]
end
User --> APIServer
APIServer <--> etcd
APIServer --> Scheduler
APIServer --> CM
APIServer --> Kubelet1
APIServer --> Kubelet2
Kubelet1 --> Runtime1
Kubelet2 --> Runtime2
Runtime1 --> Pod1A & Pod1B
Runtime2 --> Pod2A & Pod2B
2.2 Control Plane 컴포넌트
| 컴포넌트 | 역할 | Proxmox/VMware 대응 |
|---|---|---|
| API Server | 모든 요청의 관문. 인증/인가, CRUD. 유일하게 etcd와 통신 | Proxmox REST API, vCenter API |
| etcd | 클러스터 상태 저장소. 분산 KV (Raft 합의) | pmxcfs(Proxmox), vCenter DB |
| Scheduler | Pod를 어떤 노드에 배치할지 결정 | DRS(VMware), 없음(Proxmox) |
| Controller Manager | 상태를 선언과 일치시키는 컨트롤 루프 모음 | HA Manager(Proxmox) |
2.3 Worker Node 컴포넌트
| 컴포넌트 | 역할 |
|---|---|
| kubelet | 노드의 에이전트. API Server와 통신하여 Pod 생명주기 관리 |
| kube-proxy | Service의 네트워크 규칙 관리 (iptables/IPVS) |
| Container Runtime | 실제 컨테이너를 실행 (containerd, CRI-O) |
2.4 요청 흐름 예시 — Deployment 생성
sequenceDiagram
participant User as kubectl
participant API as API Server
participant etcd as etcd
participant CM as Controller Manager
participant Sched as Scheduler
participant KL as kubelet
participant CR as containerd
User->>API: kubectl apply -f deployment.yaml
API->>etcd: Deployment 오브젝트 저장
API->>CM: Deployment 변경 알림
CM->>API: ReplicaSet 생성
API->>etcd: ReplicaSet 저장
CM->>API: Pod 생성 (Pending)
API->>etcd: Pod 저장
Sched->>API: Pending Pod 감지 → 노드 배정
API->>etcd: Pod에 노드 정보 업데이트
API->>KL: Pod 생성 지시
KL->>CR: 컨테이너 생성
KL->>API: Pod 상태 → Running
💡 모든 통신은 API Server를 경유함. 컴포넌트끼리 직접 통신하지 않음. 이것이 K8s의 핵심 설계 — API Server가 Single Source of Truth.
3. 핵심 오브젝트 맵
3.1 워크로드
flowchart TD
Deployment["Deployment<br/>(무상태 앱)"] --> ReplicaSet["ReplicaSet<br/>(Pod 수 유지)"]
ReplicaSet --> Pod["Pod<br/>(최소 단위)"]
StatefulSet["StatefulSet<br/>(상태 앱, DB)"] --> Pod
DaemonSet["DaemonSet<br/>(노드마다 1개)"] --> Pod
Job["Job<br/>(일회성)"] --> Pod
CronJob["CronJob<br/>(주기적)"] --> Job
| 오브젝트 | 용도 | 예시 |
|---|---|---|
| Pod | 최소 배포 단위. 1~N개 컨테이너 | 하나의 애플리케이션 인스턴스 |
| ReplicaSet | 지정 수만큼 Pod 유지 | (직접 사용 거의 안 함) |
| Deployment | ✅ 가장 많이 사용. 롤링 업데이트/롤백 | 웹 서버, API 서버 |
| StatefulSet | 상태 있는 앱. 안정적 네트워크/스토리지 ID | DB(MySQL, PostgreSQL), 메시지 큐 |
| DaemonSet | 모든 노드에 Pod 하나씩 | 로그 수집(Fluentd), 모니터링(node-exporter) |
| Job / CronJob | 일회성/주기적 작업 | 배치 처리, 백업, 리포트 생성 |
3.2 네트워킹
| 오브젝트 | 역할 |
|---|---|
| Service | Pod 그룹에 안정적인 IP와 DNS 이름 부여 (ClusterIP, NodePort, LoadBalancer) |
| Ingress | L7 라우팅 (HTTP/HTTPS). 도메인/경로 기반으로 Service에 연결 |
| NetworkPolicy | Pod 간 트래픽 제어 (방화벽) |
3.3 스토리지
| 오브젝트 | 역할 |
|---|---|
| PersistentVolume (PV) | 실제 스토리지 리소스 (NFS, Ceph, EBS 등) |
| PersistentVolumeClaim (PVC) | 사용자의 스토리지 요청 |
| StorageClass | 동적 프로비저닝 정책 (어떤 스토리지를 어떻게 만들지) |
3.4 설정 & 보안
| 오브젝트 | 역할 |
|---|---|
| ConfigMap | 설정 데이터 (비민감) |
| Secret | 민감한 데이터 (비밀번호, 키) |
| ServiceAccount | Pod의 API 접근 ID |
| Role / ClusterRole | RBAC 권한 정의 |
| RoleBinding / ClusterRoleBinding | 역할 바인딩 |
4. K8s 배포판 & 관리형 서비스
4.1 배포판 비교
| 배포판 | 특징 | 적합한 환경 |
|---|---|---|
| kubeadm | 공식 설치 도구. 가장 표준적. CKA 시험에서 사용 | ✅ 학습, 온프레미스 |
| k3s | 경량 K8s (Rancher). 단일 바이너리, ARM 지원 | 엣지, IoT, 홈랩 |
| RKE2 | Rancher의 프로덕션용. FIPS 140-2 지원 | 보안 요구 환경 |
| MicroK8s | Canonical(Ubuntu). snap으로 설치 | 개발, CI/CD |
| kind | Docker 안에 K8s 클러스터. 테스트 전용 | 로컬 테스트 |
| minikube | 단일 노드 K8s. 학습용 | 로컬 학습 |
4.2 관리형 서비스 (Managed K8s)
| 서비스 | 클라우드 | 특징 |
|---|---|---|
| EKS | AWS | 가장 넓은 생태계. Fargate(서버리스) 지원 |
| AKS | Azure | Azure AD 통합, Azure Arc |
| GKE | GCP | K8s 원조(Google). Autopilot 모드 |
| NKS | Naver Cloud | 공공 SI에서 활용 |
4.3 엔터프라이즈 배포판
| 배포판 | 특징 |
|---|---|
| OpenShift (Red Hat) | K8s + 빌드/배포/모니터링/보안 올인원. RHCE 생태계 |
| Tanzu (VMware/Broadcom) | vSphere 위 K8s. VM Service로 Pod를 VM처럼 실행 |
| Rancher (SUSE) | 멀티클러스터 관리 UI |
5. Docker → Kubernetes 대응표
| Docker / Compose | Kubernetes | 비고 |
|---|---|---|
docker run | Pod | K8s의 최소 단위 |
docker-compose.yml (서비스 정의) | Deployment | 복제, 롤링 업데이트 포함 |
docker-compose.yml (여러 서비스) | Deployment + Service (여러 개) | 각 서비스가 독립 |
docker network | Service, CNI | K8s는 모든 Pod가 고유 IP |
ports: | Service (NodePort/LoadBalancer) | 외부 노출 |
volumes: | PV / PVC | 동적 프로비저닝 가능 |
environment: | ConfigMap, Secret | 분리된 설정 관리 |
restart: always | Deployment (자가치유) | K8s는 기본적으로 자가치유 |
docker-compose up --scale web=3 | replicas: 3 (Deployment) | HPA로 자동화 가능 |
.env 파일 | ConfigMap, Secret | |
| docker-compose (단일 호스트) | K8s (멀티 호스트 클러스터) | 핵심 차이 |
💡 Docker Compose는 단일 호스트에서 여러 컨테이너를 관리하는 도구. Kubernetes는 멀티 호스트 클러스터에서 컨테이너를 관리하는 도구. 규모가 다름.
6. Kubernetes를 쓸지 말지 판단
6.1 K8s가 필요한 경우
| 상황 | K8s 필요 |
|---|---|
| 마이크로서비스 아키텍처 (서비스 10개+) | ✅ |
| 자동 스케일링이 필요 | ✅ |
| 무중단 배포 (롤링 업데이트/카나리) | ✅ |
| 멀티 호스트, 고가용성 | ✅ |
| CI/CD 파이프라인 통합 | ✅ |
| CKA 자격증 목표 | ✅ |
6.2 K8s가 과한 경우
| 상황 | 대안 |
|---|---|
| 서비스 1~3개, 단일 서버 | Docker Compose |
| 정적 사이트 | Vercel, Netlify |
| 팀 1~2명, 빠른 프로토타입 | Docker Compose, PaaS |
| 학습 비용을 감당할 수 없음 | Docker Compose → 나중에 K8s |
flowchart TD
Q1{"서비스 수 > 5?<br/>멀티 호스트?"}
Q1 -->|"Yes"| Q2{"자동 스케일링/<br/>무중단 배포 필요?"}
Q1 -->|"No"| Compose["Docker Compose<br/>로 충분"]
Q2 -->|"Yes"| K8s["✅ Kubernetes"]
Q2 -->|"No"| Q3{"운영 팀 역량?"}
Q3 -->|"K8s 경험 있음"| K8s
Q3 -->|"없음"| Managed["관리형 K8s<br/>(EKS/AKS/GKE)"]
7. K8s와 가상화의 관계
7.1 VM 위의 K8s
대부분의 온프레미스 K8s는 VM 위에 배포됨.
flowchart TB
subgraph HW["물리 서버"]
subgraph Hypervisor["하이퍼바이저 (Proxmox/VMware)"]
VM1["VM: Master 1"]
VM2["VM: Master 2"]
VM3["VM: Master 3"]
VM4["VM: Worker 1"]
VM5["VM: Worker 2"]
VM6["VM: Worker 3"]
end
end
subgraph K8sCluster["K8s Cluster"]
CP["Control Plane<br/>(VM 1~3)"]
Workers["Workers<br/>(VM 4~6)"]
end
Hypervisor --> K8sCluster
| 구성 | 설명 |
|---|---|
| Master VM ×3 | Control Plane HA (API Server, etcd) |
| Worker VM ×3+ | 워크로드 실행 |
| 스토리지 | Ceph CSI, NFS CSI (Proxmox 연동) |
| 네트워크 | Calico/Cilium CNI + Proxmox SDN/Bridge |
7.2 VM vs 컨테이너 vs K8s
flowchart LR
Physical["물리 서버"]
Physical --> VM["VM<br/>(Proxmox/VMware)<br/>OS 격리"]
VM --> Container["컨테이너<br/>(Docker)<br/>앱 격리"]
Container --> K8s_Layer["K8s<br/>컨테이너 오케스트레이션"]
| 계층 | 단위 | 격리 수준 | 관련 시리즈 |
|---|---|---|---|
| 하이퍼바이저 | VM | 하드웨어 수준 | Virtualization 시리즈 |
| 컨테이너 | Container | OS(커널) 수준 | Docker 시리즈 |
| 오케스트레이션 | Pod/Deployment | 앱 수준 | ✅ 이 시리즈 |
8. CKA 시험과 이 시리즈
8.1 CKA 시험 정보
| 항목 | 내용 |
|---|---|
| 시험 | Certified Kubernetes Administrator |
| 발급 | CNCF / Linux Foundation |
| 형식 | 실기 (라이브 클러스터에서 문제 풀기) |
| 시간 | 2시간, 15~20문제 |
| 합격 | 66% |
| 유효 | 2년 |
| 비용 | $395 (할인 시 ~$280) |
| 리트라이 | 1회 포함 |
| 도구 | kubernetes.io 공식 문서 참조 가능 |
8.2 이 시리즈의 CKA 커버리지
| CKA 도메인 | 비중 | 해당 글 |
|---|---|---|
| Cluster Architecture, Installation & Configuration | 25% | #1 Overview, #2 Architecture, #10 Admin |
| Workloads & Scheduling | 15% | #3 Pod & Workload, #8 Scheduling |
| Services & Networking | 20% | #4 Service & Networking |
| Storage | 10% | #5 Storage |
| Troubleshooting | 30% | #9 Observability, #10 Admin |
💡 이 시리즈를 완주하면 CKA 시험 범위를 이론적으로 커버할 수 있음. 실기 시험이므로 반드시 hands-on 실습(lab/TIL에 기록)이 필요함.
정리
| 개념 | 핵심 |
|---|---|
| K8s | 컨테이너 오케스트레이션 표준. 선언적, 자가치유, 수평 확장 |
| Control Plane | API Server(관문), etcd(상태 저장), Scheduler(배치), Controller Manager(상태 유지) |
| Worker Node | kubelet(Pod 관리), kube-proxy(네트워크), Container Runtime(실행) |
| 핵심 원칙 | 모든 통신은 API Server 경유. 선언적 상태 관리. 플러그인 아키텍처 |
| Docker → K8s | docker-compose = 단일 호스트, K8s = 멀티 호스트 클러스터. 규모의 차이 |
| 배포판 | kubeadm(표준), k3s(경량), EKS/AKS/GKE(관리형) |
| CKA | 실기 시험, 이 시리즈가 이론적 기반 |
다음 글
→ #2 Cluster Architecture — Control Plane 심화, etcd, HA 구성, 통신 흐름 상세
🔗 관련 문서
- Docker Series — 선행 학습 (Docker 기초)
- Container Virtualization — 컨테이너 개념
- Kubernetes Series Index — 시리즈 목차
- Certification — CKA — CKA 로드맵