infra
Platform

모듈 맵

[Docker] Docker Compose에서 Kubernetes로 — 컨테이너 오케스트레이션 전환 가이드

0 / 27 완료

펼치기
0 / 27 완료0%

도커 & 컨테이너 · 24 / 27

[Docker] Docker Compose에서 Kubernetes로 — 컨테이너 오케스트레이션 전환 가이드

단일 서버 Compose 운영의 한계에서 출발해 Kubernetes로 넘어가는 개념적 다리 — Pod, Deployment, Service가 docker run, Compose와 어떻게 대응되는지 이해합니다

Docker Compose에서 Kubernetes로 — 컨테이너 오케스트레이션 전환 가이드

🚨INCIDENT ALERT
HIGH

단일 서버에서는 Compose로 충분했지만, 서버가 여러 대가 되자 배포·복구·스케일링이 모두 수동 작업이 됩니다. Docker Swarm으로 멀티노드를 시도해보면 선언적 배포까지는 해결되지만, 롤링 업데이트·자동 스케일링·에코시스템 도구 부재로 결국 한계에 부딪힙니다. 장애가 나면 어느 노드에서 무엇이 죽었는지 찾는 데만 시간이 소모되고, 롤백도 일관되지 않습니다. 이 시점부터는 "컨테이너 실행"보다 "원하는 상태를 자동 유지"하는 오케스트레이션 사고가 필요합니다. 이 모듈은 Docker 경험을 Kubernetes 운영 개념으로 자연스럽게 연결합니다.

이 모듈의 위치: Docker Compose까지 배웠다면 "서버가 여러 대면 어떻게 하나?"라는 질문이 생깁니다. 그 답이 오케스트레이션입니다. 현업 표준은 Kubernetes(K8s)입니다. 이 모듈은 Docker 지식을 K8s 개념에 연결하는 다리 역할을 합니다.


이번 챕터에서 배울 것

Docker를 알면 Kubernetes의 절반은 이미 이해한 겁니다. 컨테이너 이미지, 포트 바인딩, 볼륨, 환경변수 — 모두 K8s에서 같은 개념이 다른 문법으로 존재합니다. 낯선 용어들을 Docker 용어에 대응시키면서 배우면 훨씬 빠릅니다.

  • 1Compose의 한계와 멀티 노드 현실을 통해 오케스트레이션의 필요성을 설명할 수 있다
  • 2Docker 개념을 Kubernetes 개념(run→Pod, Compose→Deployment)의 유사점과 차이로 연결할 수 있다
  • 3kubectl 기본 명령을 docker CLI와 비교하며 사용할 수 있다
  • 4YAML 작성부터 외부 노출까지 첫 번째 Deployment를 배포할 수 있다
  • 5Kubernetes가 무중단 배포를 처리하는 방식으로 롤링 업데이트와 롤백을 수행할 수 있다
실습 환경 준비

minikube는 노트북에서 단일 노드 Kubernetes를 실행하는 도구입니다. 실제 클러스터 없이 이 모듈의 모든 실습을 진행할 수 있습니다.

minikube 설치 확인 (로컬 K8s 클러스터)
minikube version
minikube 시작
minikube start
kubectl 설치 확인
kubectl version --client
클러스터 연결 확인
kubectl cluster-info
minikube 미설치 시 대안 (Docker Desktop)

Docker Desktop의 Settings → Kubernetes → Enable Kubernetes로 로컬 클러스터 활성화 가능합니다

💡개념

왜 Compose로는 부족한가 — 오케스트레이션의 필요성

Docker Compose로 운영 중인 서버가 다운됐습니다. 모든 컨테이너가 중단됩니다. 수동으로 서버를 복구하고 docker-compose up을 다시 실행해야 합니다. 트래픽이 갑자기 2배가 됐습니다. 컨테이너를 더 실행하려면 또 다른 서버에 SSH로 접속해서 수동으로 docker run을 해야 합니다. 배포할 때마다 잠깐 서비스가 중단됩니다. Compose는 단일 서버에서 컨테이너를 편하게 관리하는 도구지, 여러 서버를 자동으로 관리하는 도구가 아닙니다.

오케스트레이션의 필요성 — 컨테이너가 수십·수백 개로 늘면 수동 배포·장애 복구·스케일링·롤링 업데이트가 한계. 오케스트레이터(Kubernetes)는 원하는 상태를 선언하면 배치·자가 치유·자동 확장·무중단 배포를 자동 수행 — docker run/compose의 단일 호스트 한계를 넘는 다중 노드 운영의 답확대

Compose의 한계

Docker Compose가 해결하는 것:
✓ 로컬 개발 환경 멀티 컨테이너 관리
✓ 단일 서버에서 서비스 간 네트워크
✓ 볼륨, 환경변수, 의존성 관리

Docker Compose가 해결하지 못하는 것:
✗ 여러 서버(노드)에 컨테이너 분산
✗ 노드 장애 시 자동 복구
✗ 트래픽에 따른 자동 스케일링
✗ 무중단 롤링 업데이트
✗ 서비스 간 부하분산

Kubernetes가 해결하는 것

Kubernetes(K8s)는 컨테이너 오케스트레이션 플랫폼입니다. 여러 서버를 하나의 클러스터로 추상화하고, 컨테이너의 배포·스케일링·복구를 자동화합니다.

Kubernetes 클러스터 구조 — Control Plane(API Server·Scheduler·etcd·Controller)이 상태를 관리하고 Worker 노드들이 Pod를 실행, 노드 장애 시 자동 재스케줄·HPA·롤링 업데이트확대


💡개념

Docker → Kubernetes 개념 매핑

K8s를 처음 배울 때 가장 힘든 것은 새로운 용어들입니다. Pod, Deployment, Service, ConfigMap, Ingress — 낯선 이름들이 쏟아집니다. Docker와 비슷한 역할을 하는 개념이 있지만 수명주기·네트워크·스케줄링 모델은 다릅니다. 매핑은 출발점으로만 쓰고 차이를 함께 확인해야 합니다.

Docker→Kubernetes 개념 비교 — docker run→Pod(실행 단위), Compose service→Deployment(복제·선언), -p 포트→Service, docker network→Service(ClusterIP), -e/-v→ConfigMap·Secret·PVC, healthcheck→liveness/readinessProbe. 역할이 비슷해도 수명주기와 네트워크 모델은 다르므로 매핑은 출발점으로만 사용확대

핵심 개념 매핑

Docker / ComposeKubernetes역할
docker runPod컨테이너 실행 단위
docker-compose.yml serviceDeployment(가장 가까운 비교)컨테이너 수·이미지·설정 선언 (수명주기는 다름)
--replicas: 3replicas: 3동일 — 복제본 수
-p 8080:80Service (NodePort/LB)외부 포트 노출
docker networkService (ClusterIP)컨테이너 간 통신
-e KEY=VALUEenv + ConfigMap환경변수
-e PASSWORD=...Secret민감한 환경변수
-v /host:/containerPersistentVolumeClaim영구 볼륨
healthcheck:livenessProbe / readinessProbe헬스체크
docker logskubectl logs컨테이너 로그
docker exec -itkubectl exec -it컨테이너 접속
docker pskubectl get pods실행 중인 컨테이너 목록

Compose를 K8s로 변환하는 패턴 — docker-compose.yml의 image·ports·environment·deploy.replicas·volumes가 Kubernetes Deployment(replicas→spec.replicas, image→containers[].image, environment→env)와 별도 Service(ports)로 변환됨. kompose 같은 도구로 자동 변환 가능확대

Pod란?

Pod는 K8s에서 가장 작은 배포 단위입니다. docker run nginx가 컨테이너 하나를 실행하는 것처럼, K8s에서는 Pod 안에 컨테이너가 실행됩니다. 대부분의 경우 Pod 하나 = 컨테이너 하나입니다.

YAML
# docker run nginx와 동일한 K8s Pod
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.25-alpine
    ports:
    - containerPort: 80

Deployment란?

Pod를 직접 만들지 않고 Deployment를 사용합니다. Deployment는 "nginx를 3개 실행하고 항상 3개 상태를 유지하라"는 선언입니다. Pod가 죽으면 자동으로 새 Pod를 만듭니다.

YAML
# docker-compose.yml의 service와 대응
# services:
#   web:
#     image: nginx:1.25-alpine
#     deploy:
#       replicas: 3

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3          # Compose의 replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25-alpine
        ports:
        - containerPort: 80
💡개념

선언한 Deployment는 어떻게 '항상 3개'로 유지되나 — apply부터 롤링까지 5단계

kubectl apply -freplicas: 3을 선언하면 잠시 뒤 Pod 3개가 뜨고, 하나를 죽여도 곧 다시 3개가 됩니다. 이 "선언하면 알아서 유지된다"는 동작의 정체는 API 서버 저장 → 스케줄러 배정 → kubelet 실행 → 컨트롤러 조정(reconcile) → 롤링 업데이트로 이어지는 제어 루프입니다. Docker Swarm의 매니저·워커·태스크도 이름만 다를 뿐 같은 흐름이며, 이 단계를 알면 "Pod가 왜 안 뜨지", "왜 여기서 멈추지"를 단계로 좁혀 진단할 수 있습니다.

TEXT
[사용자]  kubectl apply -f deployment.yaml   (replicas: 3)
   │
   ① 선언 저장 — API 서버가 '원하는 상태'를 etcd에 기록     (desired = 3)
   │
   ② 스케줄 — 스케줄러가 각 Pod를 배치할 노드를 고른다       (CPU·메모리·taint 고려)
   │
   ③ 실행 — 대상 노드의 kubelet이 컨테이너(Pod)를 띄운다     (이미지 pull → start)
   │
   ④ 상태 조정 — 컨트롤러가 desired(3) vs current를 계속 비교  (죽으면 새로 만들고 재배치)
   │     → 이 reconcile 루프가 'self-healing'의 정체
   │
   ⑤ 롤링 업데이트 — 이미지 바꾸면 새 ReplicaSet을 조금씩 교체  (old 축소·new 확대, 무중단)
   ▼
[클러스터]  READY 3/3 유지 — 선언과 실제가 같아질 때까지 루프가 계속 돈다

각 단계에서 무슨 일이 일어나고, 막히면 어떤 증상인가:

단계하는 일여기서 막히면
① 선언 저장kubectl apply가 매니페스트를 API 서버로 보내고 desired state가 etcd에 저장된다YAML 문법·필드 오류면 apply 자체가 거부(error validating data) — 클러스터엔 아무 것도 안 뜸
② 스케줄스케줄러가 requests·taint·노드 여유를 보고 Pod를 노드에 배정배치할 노드가 없으면 Pod가 Pendingdescribe pod의 Events에 Insufficient cpu/memory
③ 실행배정된 노드의 kubelet이 이미지를 pull하고 컨테이너를 start이미지 오타·프라이빗 접근 실패는 ImagePullBackOff, 앱이 바로 죽으면 CrashLoopBackOff
④ 상태 조정컨트롤러가 desired와 current를 끊임없이 비교해 부족하면 새 Pod 생성·재배치replica가 1이면 그 Pod 재시작 동안 서비스 다운 — 가용성 원하면 최소 2
⑤ 롤링 업데이트이미지 교체 시 새 ReplicaSet을 점진 확대·구버전 축소로 무중단 배포, 실패 시 rollout undo로 롤백새 Pod가 readiness를 못 넘으면 롤아웃이 멈춤(rollout status가 진행 중에서 정체)

즉 Kubernetes(와 Swarm)의 핵심은 "컨테이너를 실행한다"가 아니라 **"선언한 상태와 실제 상태의 차이를 컨트롤러가 계속 0으로 만든다"**는 것입니다 — Pod가 죽어도 다시 뜨는 이유가 ④의 reconcile 루프입니다. 접속·배포가 안 될 때 이 다섯 단계 중 어디서 끊겼는지를 kubectl get pods(상태)와 kubectl describe pod(Events)로 좁힙니다 — Pending이면 ②(배치할 곳 없음), CrashLoopBackOff면 ③(앱이 못 산다), 롤아웃 정체면 ⑤(새 버전이 준비 안 됨)입니다.

오케스트레이션 선택 판단 — 무엇을 언제 쓰나
단일 호스트, 컨테이너 몇 개docker-compose면 충분 — 오케스트레이터 도입은 운영 복잡도만 늘린다. '한 대에서 몇 개면 Compose'. 굳이 K8s로 시작하지 말 것
여러 호스트, 간단한 분산이 필요Docker Swarm — Compose 문법 그대로 멀티노드 확장, 학습 곡선 완만. 소규모 팀·단순 서비스에 적합. '쉬운 멀티노드=Swarm'
대규모·복잡한 운영(오토스케일·롤링·생태계)Kubernetes — 자동 복구·스케일·풍부한 생태계. 단 운영 인력·학습 비용이 크다. '규모와 복잡도가 비용을 정당화할 때만 K8s'
Pod가 Pending에서 안 뜬다스케줄 가능한 노드 없음 — kubectl describe pod의 Events에 insufficient cpu/memory·taint 표시. 리소스 요청(requests) 과다 또는 노드 부족. 'Pending=배치할 곳이 없다'
CrashLoopBackOff 반복컨테이너가 시작 직후 죽음 — kubectl logs --previous로 직전 로그. 잘못된 커맨드·환경변수·의존 서비스 미준비가 흔함. 'BackOff=앱이 못 산다, 로그부터'
replicas를 몇으로최소 2(무중단·롤링), 트래픽 기준 여유 30~50%. 단일 replica는 그 Pod 재시작 시 다운 — '가용성 원하면 최소 2개부터'

1첫 번째 Deployment 배포 — YAML 작성부터 외부 노출까지

minikube 환경에서 nginx를 3개 복제본으로 배포하고, Service로 외부에 노출합니다.

YAML
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25-alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
Kubernetes
# Deployment와 Service 동시 배포
kubectl apply -f nginx-deployment.yaml

# 배포 상태 확인
kubectl get pods
kubectl get deployment nginx-deployment
kubectl get service nginx-service

# minikube에서 외부 접근 URL 확인
minikube service nginx-service --url
kubectl apply -f nginx-deployment.yaml
🔍실행 후 확인할 것
  • REPLICAS 컬럼 먼저: kubectl get deployment nginx-deployment 에서 READY 컬럼이 3/3인지 확인. 0/3이나 1/3이면 아직 초기화 중 — 30초 후 재확인. 계속 0/3이면 kubectl describe pod 로 Events 섹션 확인
  • Pod 수 기준: kubectl get pods 에서 nginx-deployment-* 이름의 Pod가 정확히 3개이고 모두 STATUS=Running 이어야 정상. 2개 이하면 스케줄러가 리소스 부족으로 일부 Pod 배치 실패한 것 (Pending 상태 Pod 확인)
  • READY=3/3이고 curl 응답 200: Deployment + Service가 정상 동작. READY=3/3인데 curl 타임아웃이면 Service selector(app: nginx)와 Pod labels(app: nginx)가 불일치한 것 — kubectl get pods --show-labels 로 비교

트러블슈팅

증상

Deployment를 배포했는데 Pod가 Running이 되지 않고 계속 Pending 상태입니다.

Kubernetes
kubectl get pods
# NAME                               READY   STATUS    RESTARTS   AGE
# nginx-deployment-7d9c4bbfd-xk2p9   0/1     Pending   0          2m

kubectl describe pod nginx-deployment-7d9c4bbfd-xk2p9
# Events:
#   Warning  FailedScheduling  2m  default-scheduler
#   0/1 nodes are available: 1 Insufficient memory.

원인 진단

Kubernetes
# 노드 리소스 현황 확인
kubectl describe nodes | grep -A 5 "Allocated resources"
# Allocated resources:
#   Resource    Requests    Limits
#   cpu         950m (47%)  2 (100%)
#   memory      1900Mi (95%) 2000Mi (99%)
# → 메모리가 거의 꽉 찬 상태

# Pod의 리소스 요청량 확인
kubectl get pod nginx-deployment-7d9c4bbfd-xk2p9 -o yaml | grep -A 10 resources

해결

Kubernetes
# 방법 1: 다른 Pod 삭제하여 리소스 확보
kubectl get pods --all-namespaces | grep -v Running
# 불필요한 Pod 삭제

# 방법 2: Deployment에 resources.requests 조정
kubectl edit deployment nginx-deployment
# resources:
#   requests:
#     memory: "64Mi"   ← 낮춤
#     cpu: "100m"

# 방법 3: minikube 메모리 늘려서 재시작
minikube stop
minikube start --memory=4096

증상

kubectl apply 직후에는 Running이었다가 금방 Error → CrashLoopBackOff로 바뀝니다.

Kubernetes
kubectl get pods
# NAME                              READY   STATUS             RESTARTS   AGE
# myapp-deployment-abc123-x7k2p   0/1     CrashLoopBackOff   5          3m

# 재시작 횟수가 계속 늘어남
kubectl get pods -w
# myapp-..   0/1   Error              3   90s
# myapp-..   0/1   CrashLoopBackOff   3   95s
# myapp-..   0/1   Running            4   110s
# myapp-..   0/1   Error              4   115s

원인 진단

Kubernetes
# 컨테이너 로그 확인 — docker logs와 동일한 역할
kubectl logs myapp-deployment-abc123-x7k2p
# Error: Cannot find module '/app/server.js'   ← 이런 에러 메시지 확인

# 이전 충돌 컨테이너의 로그 확인
kubectl logs myapp-deployment-abc123-x7k2p --previous

# Pod 상세 이벤트 확인
kubectl describe pod myapp-deployment-abc123-x7k2p
# Events:
#   Warning  BackOff  2m  kubelet  Back-off restarting failed container

주요 원인별 해결

Kubernetes
# 원인 1: 이미지 내 실행 파일 경로 오류 → Dockerfile ENTRYPOINT/CMD 확인
# 원인 2: 환경변수 누락 → kubectl get pod -o yaml 로 env 확인
# 원인 3: ConfigMap/Secret 마운트 실패 → kubectl describe pod Events 확인

# 임시 디버깅: 같은 이미지로 셸 접속
kubectl run debug --image=myapp:latest --restart=Never -it -- /bin/sh

증상

단일 노드에서는 Pod 간 통신이 잘 됐는데, 멀티 노드 클러스터(또는 Swarm) 환경에서 서로 다른 노드에 뜬 Pod끼리 통신이 안 됩니다.

Kubernetes
# Pod A (Node 1)에서 Pod B (Node 2)로 ping/curl 실패
kubectl exec -it pod-a -- curl http://pod-b-service
# curl: (7) Failed to connect to pod-b-service port 80: Connection timed out

원인 진단

로컬 터미널
# 노드 간 오버레이 네트워크 포트 확인 (방화벽 문제)
# Kubernetes(Flannel/Calico): UDP 8472, UDP 4789 필요
# Kubernetes API: TCP 6443
# Swarm: TCP 2377, TCP/UDP 7946, UDP 4789

# 방화벽 상태 확인
sudo firewall-cmd --list-all  # CentOS/RHEL
sudo ufw status               # Ubuntu

해결

로컬 터미널
# Ubuntu (ufw) — 오버레이 네트워크 포트 허용
sudo ufw allow 6443/tcp    # K8s API Server
sudo ufw allow 8472/udp    # Flannel VXLAN
sudo ufw allow 4789/udp    # Overlay network
sudo ufw allow 7946/tcp    # Calico BGP / Swarm gossip
sudo ufw allow 7946/udp

# 설정 후 Pod 간 통신 재확인
kubectl exec -it pod-a -- curl http://pod-b-service

심화 — HEALTHCHECK 하나가 K8s에서 셋으로 갈라진다

💡개념

심화: liveness·readiness·startup probe — HEALTHCHECK 하나가 셋으로 갈라지는 이유

Docker에는 HEALTHCHECK 하나뿐입니다. 그런데 K8s는 같은 "헬스체크"를 목적이 다른 세 probe로 쪼갭니다. 이 분리를 모르면 앞의 매핑 표에서 healthcheck → liveness/readiness를 봤어도, 정작 운영에서 엉뚱한 probe에 엉뚱한 검사를 넣어 사고를 냅니다.

  • livenessProbe = "죽었나?": 실패하면 kubelet이 컨테이너를 kill 후 재시작합니다. 프로세스가 데드락에 빠져 스스로 못 살아나는 걸 복구하는 용도입니다. 여기에 DB 연결 같은 의존성 체크를 넣으면, DB가 잠깐 느릴 때 멀쩡한 앱까지 재시작됩니다.
  • readinessProbe = "지금 트래픽 받아도 되나?": 실패해도 컨테이너는 살려두고 Service 엔드포인트에서만 빼 트래픽을 끊습니다. 워밍업 중이거나 의존성이 아직 안 붙었을 때 "재시작 말고 잠깐 트래픽만 보류"가 필요한 곳이 여기입니다.
  • startupProbe = "다 떴나?": 초기화가 느린 앱(대형 JVM 등)을 위해, 이게 성공할 때까지 liveness·readiness를 미뤄줍니다. 없으면 느린 부팅을 liveness가 "죽었다"고 오판해 부팅 도중 계속 죽입니다.

내부 동작으로 보면 readiness는 엔드포인트 컨트롤러가 Service의 대상 목록을 갱신하는 신호이고, liveness는 kubelet이 컨테이너를 재시작하는 신호로, 완전히 다른 주체가 반응합니다. 그래서 원칙은 하나입니다 — liveness는 프로세스 생존만 가볍게, 의존성·준비 상태는 readiness로, 느린 초기화는 startupProbe로. Docker의 단일 HEALTHCHECK 감각으로 liveness에 무거운 검사를 몰아넣는 것이 K8s 전환 초기의 가장 흔한 자해입니다.

상황

새 서비스를 올린 뒤 응답도 정상이고 사용자 오류도 없는데, kubectl get pods의 RESTARTS 숫자가 시간마다 1씩 늘어납니다. 트래픽이 몰리는 시간대에 재시작이 더 잦습니다.

원인

앱이 죽은 게 아니라 livenessProbe가 멀쩡한 앱을 죽이고 있습니다. timeoutSeconds가 1초처럼 너무 짧거나 failureThreshold가 낮으면, GC 정지·순간 부하로 probe 응답이 몇백 ms만 늦어도 실패로 집계됩니다. 게다가 liveness 경로에 DB·캐시 같은 의존성 확인을 넣어뒀다면, 의존성이 잠깐 느릴 때 앱까지 재시작 대상이 됩니다.

진단

Kubernetes
# Events에 Liveness probe failed / Killing 이 반복되는지
kubectl describe pod myapp-deployment-abc123-x7k2p | grep -A2 -i "liveness\|killing"

# 같은 Pod의 직전 로그에 앱 크래시가 없는지 (없으면 probe가 원인)
kubectl logs myapp-deployment-abc123-x7k2p --previous

# probe 정의와 임계값 확인
kubectl get deploy myapp-deployment -o yaml | grep -A8 livenessProbe

로그는 멀쩡한데 재시작만 반복되면 probe가 원인이라는 확정 신호입니다.

해결

liveness는 프로세스가 응답만 하는지 보는 가벼운 경로(예: /healthz가 즉시 200)로 바꾸고 timeoutSeconds·failureThreshold를 현실적으로 키웁니다. 느린 초기화는 startupProbe로 감싸 부팅 동안 liveness를 미룹니다. DB 등 의존성 준비 여부는 liveness가 아니라 readinessProbe로 옮겨, 준비가 안 됐을 땐 재시작 대신 트래픽만 잠깐 끊기게 합니다. Docker의 HEALTHCHECK 하나를 K8s의 세 probe로 올바르게 나누는 것이 핵심입니다.


💼
실무 맥락
현업 패턴

"Compose로 충분한가" — 팀이 Kubernetes로 전환하는 실제 기준점

스타트업 초기에는 EC2 한 대에 docker-compose로 운영합니다. 빠르고 단순합니다. 그러다 어느 순간 이런 상황이 옵니다: 새벽 3시에 서버가 멈추고, 자동 복구가 없어서 수동으로 SSH 접속해서 docker-compose up을 칩니다. 다음 날 오전 트래픽 피크 때 컨테이너를 더 늘려야 하는데 새 서버에 일일이 접속해서 설정합니다. 이 지점이 오케스트레이션을 고민해야 할 때입니다.

팀 규모별 현실적 판단:

1~3명 팀, 단일 서버:
  → docker-compose + systemd restart=always 로 충분
  → K8s 도입하면 운영 오버헤드가 더 큼

4~10명 팀, 서버 3대 이상:
  → Kubernetes 도입 고려 시작
  → EKS/GKE 같은 매니지드 서비스가 현실적

10명+ 팀, MSA:
  → K8s는 선택이 아닌 필수
  → Helm, ArgoCD, Istio 등 생태계 전체 활용

실무에서 K8s를 배워야 하는 이유: 대부분의 중소기업 이상 회사의 인프라는 이미 K8s로 전환됐거나 전환 중입니다. 채용 공고에서 "K8s 운영 경험"이 필수 요건으로 등장하는 비율이 빠르게 늘고 있습니다. Docker를 잘 안다면 K8s 진입 장벽은 생각보다 낮습니다 — 이 모듈에서 배운 개념 매핑이 그 다리 역할을 합니다.


명령어·단축키 빠른 참조

이 모듈에서 Docker 개념과 대응시켜 다룬 kubectl·minikube 명령을 실전 예와 함께 모았습니다. "용도"의 괄호는 대응되는 Docker 명령입니다.

명령어/단축키용도자주 쓰는 예
kubectl apply -fYAML로 Deployment·Service 배포(선언적)kubectl apply -f nginx-deployment.yaml
kubectl get pods실행 중 Pod 목록(= docker ps)kubectl get pods -w (상태 변화 감시) · --show-labels
kubectl get deployment복제본 READY 상태 확인kubectl get deployment nginx-deploymentREADY 3/3
kubectl get service서비스·노출 포트 확인kubectl get service nginx-service
kubectl logs컨테이너 로그(= docker logs)kubectl logs <pod> --previous (직전 크래시 로그)
kubectl describe podPending·CrashLoop 원인 Events 확인kubectl describe pod <pod> → Events의 FailedScheduling·BackOff
kubectl exec -it컨테이너 접속(= docker exec -it)kubectl exec -it pod-a -- curl http://pod-b-service
kubectl rollout undo이전 버전으로 즉시 롤백kubectl rollout undo deployment/<name> · --to-revision=2
kubectl edit deployment실행 중 Deployment 설정 수정kubectl edit deployment nginx-deployment (requests 조정)
kubectl run임시 디버그 Pod 실행kubectl run debug --image=myapp:latest --restart=Never -it -- /bin/sh
kubectl describe nodes노드 리소스 할당 현황 확인kubectl describe nodes | grep -A5 "Allocated resources"
minikube service --url로컬 클러스터 외부 접근 URLminikube service nginx-service --url

관련 모듈로 더 깊이:

다음 모듈에서는 Kubernetes 트랙에서 실제 클러스터 운영, Helm 패키지 관리, 그리고 서비스 메시(Istio)를 심층적으로 다룹니다.

지식 확인

퀴즈 — 8문제

Q1

Docker Compose의 `services` 항목이 Kubernetes에서 대응되는 개념은?

Q2

kubectl apply -f deployment.yaml 명령 후 Pod가 CrashLoopBackOff 상태입니다. 원인 파악을 위한 첫 번째 명령은?

Q3

Kubernetes에서 외부 트래픽을 Pod에 전달하려면 무엇이 필요한가?

Q4

배포 후 문제가 생겨서 이전 버전으로 되돌려야 합니다. 올바른 명령은?

Q5

docker-compose.yml에서 environment 항목이 Kubernetes에서 대응되는 방법으로 가장 적절한 것은?

Q6

단일 호스트의 docker compose만으로 운영하기 어려워 Kubernetes 같은 오케스트레이터로 가는 이유로 가장 적절한 것은?

Q7

[심화] Docker의 HEALTHCHECK 하나가 Kubernetes에서 livenessProbe와 readinessProbe 둘로 나뉜다. 두 probe가 실패했을 때 kubelet과 엔드포인트 컨트롤러의 동작 차이로 가장 정확한 것은?

Q8

[심화] 배포한 Pod가 정상 트래픽을 잘 처리하는데도 RESTARTS 카운트가 계속 오른다. kubectl logs에는 애플리케이션 에러가 없고, describe의 Events에는 Liveness probe failed와 Killing container가 반복되며 부하가 몰릴 때 특히 잦다. 원인으로 가장 정확한 것은?

0 / 8 답변

🧪 실습으로 확인하기

Docker Compose 멀티 서비스 구성

초급

docker-compose.yml로 nginx + 앱 컨테이너를 함께 정의하고, 서비스 간 통신과 볼륨 마운트를 구성한다.

35📋 4단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요