Docker가 서버 개발자들의 로컬 개발 환경 문제를 해결했다면, 프로덕션 레벨에서 수십, 수백 개의 도커 컨테이너를 통합적으로 관리해주는 시스템이 필요해졌습니다. 그리고 구글에서 자신들의 내부 노하우를 담아 오픈소스로 공개한 것이 바로 쿠버네티스(Kubernetes, K8s)입니다. 이번 포스트에서는 K8s의 아키텍처부터 실제 배포 YAML 작성, 그리고 실무 패턴까지 단계별로 알아보겠습니다.
1. 컨테이너 오케스트레이션이란?
다수의 서버에 분산하여 여러 컨테이너 애플리케이션을 자동으로 배포하고 무중단 스케일링, 복원, 네트워크 라우팅 등을 하나의 교향악단 지휘자(Orchestrator)처럼 조율해주는 과정을 의미합니다. 오케스트레이션이 해결하는 문제들은 다음과 같습니다.
- 컨테이너가 충돌하면 자동으로 재시작합니다.
- 트래픽이 증가하면 컨테이너 수를 자동으로 늘립니다(Auto-scaling).
- 새 버전 배포 시 서비스 중단 없이 롤링 업데이트를 수행합니다.
- 여러 서버(노드)에 컨테이너를 효율적으로 배치합니다(스케줄링).
- 서비스 간 통신과 외부 트래픽 라우팅을 관리합니다.
2. 쿠버네티스 아키텍처
쿠버네티스 클러스터는 크게 컨트롤 플레인(Control Plane)과 워커 노드(Worker Node)로 구성됩니다.
컨트롤 플레인은 클러스터의 두뇌 역할을 합니다. 주요 구성 요소는 다음과 같습니다.
- API Server: 모든 K8s 작업의 진입점. kubectl 명령도, 내부 컴포넌트 간 통신도 API Server를 통해 이루어집니다.
- etcd: 클러스터 전체의 상태(state)를 저장하는 분산 키-값 저장소. 클러스터의 "단일 진실의 원천(Single Source of Truth)"입니다.
- Scheduler: 새 파드를 어느 노드에 배치할지 결정합니다. CPU, 메모리 가용량, 어피니티(Affinity) 규칙 등을 고려합니다.
- Controller Manager: Deployment, ReplicaSet 등 각종 컨트롤러(오브젝트 상태를 목표 상태로 유지하는 루프)를 실행합니다.
워커 노드는 실제 컨테이너(파드)가 실행되는 서버입니다. 구성 요소는 다음과 같습니다.
- kubelet: 컨트롤 플레인의 지시를 받아 파드 내 컨테이너를 실행/모니터링합니다.
- kube-proxy: 노드 수준의 네트워크 프록시로, 서비스 트래픽을 적절한 파드로 라우팅합니다.
- Container Runtime: 컨테이너를 실제로 실행하는 런타임입니다. (containerd, CRI-O 등)
3. 쿠버네티스의 핵심 오브젝트
- Pod (파드): 쿠버네티스의 가장 작은 배포 단위입니다. 하나의 파드 내에 하나 이상의 컨테이너가 들어갈 수 있으며, 동일한 네트워크 네임스페이스(IP, 포트)를 공유합니다.
- ReplicaSet: 지정된 수의 파드 복제본이 항상 실행 중임을 보장합니다. 파드가 죽으면 자동으로 새 파드를 생성합니다.
- Deployment (디플로이먼트): ReplicaSet을 관리하며 롤링 업데이트와 롤백을 담당합니다. 실제로 애플리케이션을 배포할 때 가장 많이 사용하는 오브젝트입니다.
- Service (서비스): 파드들의 고정적인 진입점(Load Balancer) 역할을 합니다. ClusterIP(내부), NodePort(외부 노드 포트), LoadBalancer(클라우드 LB 연결) 유형이 있습니다.
- Ingress: L7(HTTP/HTTPS) 라우팅을 담당합니다. URL 경로나 호스트명 기반으로 트래픽을 여러 서비스로 분산합니다.
- ConfigMap / Secret: 설정값(ConfigMap)과 민감한 데이터(Secret)를 파드와 분리하여 관리합니다.
- PersistentVolume / PersistentVolumeClaim: 파드가 삭제되어도 데이터가 유지되는 영속적인 스토리지를 관리합니다.
4. 선언형 아키텍처(Declarative) — 실제 YAML 예시
쿠버네티스의 가장 중요한 철학 중 하나는 선언형(Declarative) 상태 관리입니다. "A 서버에는 2개의 컨테이너를 올리고..." 하는 식으로 절차를 지시하는 것이 아닙니다.
"내 웹 서버 파드를 항상 4개씩 켜져 있는 상태로 유지해"
라고 YAML 파일에 목표 상태(Desired State)를 선언하면, 쿠버네티스는 현재 상태를 스스로 모니터링하여 목표 상태를 자동으로 맞춰 나갑니다(Reconciliation Loop). 아래는 실제 Deployment 배포 YAML 예시입니다.
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web-app
labels:
app: my-web-app
spec:
replicas: 4 # 항상 4개의 파드를 유지
selector:
matchLabels:
app: my-web-app
template:
metadata:
labels:
app: my-web-app
spec:
containers:
- name: app
image: my-web-app:v2.0.0
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef: # Secret에서 환경변수 주입
name: app-secrets
key: database-url
---
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-web-app-service
spec:
selector:
app: my-web-app
ports:
- port: 80
targetPort: 3000
type: ClusterIP
kubectl apply -f deployment.yaml 명령으로 위 파일을 클러스터에 적용하면, 쿠버네티스가 자동으로 4개의 파드를 생성합니다. 서버 하나가 고장나 파드가 2개 죽으면 정상적인 노드에 2개를 자동으로 새로 띄웁니다.
5. Helm: 쿠버네티스의 패키지 매니저
실제 프로덕션 환경에서는 수십 개의 YAML 파일을 관리해야 합니다. Helm은 이 파일들을 패키지(Chart)로 묶어 버전 관리하고, 환경별(개발/스테이징/프로덕션) 설정값(values)을 유연하게 오버라이드할 수 있게 해주는 쿠버네티스의 패키지 매니저입니다.
# Helm으로 Nginx Ingress Controller 설치
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install my-ingress ingress-nginx/ingress-nginx \
--set controller.replicaCount=2 \
--namespace ingress-nginx --create-namespace
# 내 앱 Helm Chart 배포 (환경별 다른 값 사용)
helm upgrade --install my-app ./my-chart \
-f values-prod.yaml \
--set image.tag=v2.0.0
6. 관리형 쿠버네티스 서비스 (EKS, GKE, AKS)
쿠버네티스를 직접 구축하고 컨트롤 플레인을 관리하는 것은 상당한 운영 부담이 따릅니다. 클라우드 제공사들은 컨트롤 플레인 관리를 대신해주는 관리형 서비스를 제공합니다.
- AWS EKS (Elastic Kubernetes Service): AWS 생태계(ALB, IAM, EFS 등)와 깊이 통합됩니다.
- Google GKE (Google Kubernetes Engine): 구글이 쿠버네티스를 만든 만큼 가장 완성도 높고, Autopilot 모드로 노드 관리까지 자동화가 가능합니다.
- Azure AKS: Microsoft Azure 서비스와 통합이 뛰어납니다.
마무리
쿠버네티스는 학습 곡선이 가파른 도구인 것은 부정할 수 없는 사실이지만, 대규모 트래픽 분산과 고가용성 아키텍처(Highly Available Architecture)를 서버 개발자들이 안심하고 구성하게 해주는 인프라 세계의 클라우드 운영 체제입니다. 처음에는 Minikube나 k3s로 로컬에서 실습을 시작하고, 이후 관리형 서비스(GKE, EKS)로 넘어가는 것을 추천합니다. Docker와 Linux를 먼저 잘 이해하는 것이 K8s 학습의 견고한 토대가 됩니다.