Kubernetes 배포를 몇 분에서 초 단위로 줄인 12가지 실전 기법

|Platform Decision|8분 읽기

배포 시간에 대한 생각

최근 팀 내에서 쿠버네티스 배포 시간이 자주 화두에 오르더라고요. 5분 걸리던 배포가 어느 순간 15분이 되고, 급한 핫픽스를 올려야 할 때마다 조바심이 나는 그런 상황들 말이에요. 그래서 지난 몇 달간 여러 프로젝트에서 시도했던 최적화 기법들을 정리해봤습니다.

1. 컨테이너 이미지, 무자비하게 줄여보기

이미지 크기는 배포 속도에 직접적인 영향을 미칩니다. 멀티스테이지 빌드Alpine 기반 이미지를 조합하면 극적인 개선을 볼 수 있어요.

# Before: 1GB 크기의 무거운 이미지
# After: 100MB 이하로 압축
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
EXPOSE 3000
CMD ["npm", "start"]

실제로 한 프로젝트에서 Ubuntu 기반 이미지를 Alpine으로 교체하니 풀 시간이 70% 단축되더라고요. dive 같은 도구로 이미지 레이어를 분석해보면 불필요한 파일들이 얼마나 많은지 놀라게 됩니다.

2. 헬스체크 프로브 정교하게 튜닝하기

Readiness와 Liveness 프로브는 배포 안정성의 핵심입니다. 초기 지연 시간을 앱 워밍업 시간에 맞추고, 체크 주기는 빠르게 설정하는 게 포인트에요.

spec:
  containers:
  - name: app
    image: myapp:v1
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 30  # 앱 시작 시간 고려
      periodSeconds: 10        # 빠른 감지
      timeoutSeconds: 5
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5   # 준비 상태 빠른 체크
      periodSeconds: 5

한 전자상거래 서비스에서 프로브 튜닝만으로 배포 실패율을 50% 줄였다는 사례도 있더라고요.

3. 리소스 요청과 제한, 현실적으로 설정하기

kubectl top으로 실제 사용량을 측정한 후 리소스를 설정하면 스케줄링이 훨씬 빨라집니다.

resources:
  requests:
    cpu: "250m"      # 실제 평균 사용량 기준
    memory: "256Mi"
  limits:
    cpu: "500m"      # 버스트 트래픽 고려
    memory: "512Mi"

적절한 리소스 설정 후 파드 배치가 40% 빨라졌다는 팀들의 보고가 꽤 많아요.

4. HPA로 자동 스케일링 활용하기

Horizontal Pod Autoscaler는 트래픽 급증 시 수동 대응을 대체합니다. CPU 사용률 50-70%를 목표로 설정하는 게 일반적이에요.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 2    # 콜드 스타트 방지
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60

5. 롤링 업데이트 전략 최적화

무중단 배포를 위해서는 maxUnavailable: 0으로 설정하고, 속도가 중요하다면 maxSurge를 높이는 방향으로 조정합니다.

strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0  # 무중단 보장

6. GitOps로 배포 자동화하기

ArgoCD나 Flux 같은 GitOps 도구를 도입하면 PR 병합만으로 자동 배포가 가능합니다. 수동 kubectl 명령을 없애고 5분 사이클의 지속적 배포를 구현할 수 있어요.

GitOps 도입 후 MTTR이 80% 감소했다는 사례들을 보면, 안정성과 속도를 모두 잡을 수 있는 방법인 것 같습니다.

7. 노드 타입과 친화성 최적화

ARM Graviton 인스턴스를 사용하면 비용 절약과 함께 20-40% 성능 향상을 기대할 수 있습니다.

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: node-type
          operator: In
          values: ["graviton"]

8. 이미지 풀 속도 개선하기

DaemonSet으로 이미지 미리 받기지역별 레지스트리 미러링을 활용하면 풀 시간을 대폭 단축할 수 있습니다. imagePullPolicy: IfNotPresent로 불필요한 재다운로드도 방지할 수 있어요.

글로벌 서비스를 운영하는 팀에서는 AWS ECR 미러링으로 풀 시간을 2분에서 20초로 줄였다고 하더라고요.

9. 네임스페이스와 리소스 쿼터로 격리하기

개발/스테이징/프로덕션을 네임스페이스로 구분하고, ResourceQuota로 리소스 경쟁을 방지하면 배포 성능이 안정화됩니다.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
spec:
  hard:
    requests.cpu: "10"
    requests.memory: 20Gi
    limits.cpu: "20"
    limits.memory: 40Gi

10. 네트워킹과 스토리지 간소화

Calico나 Cilium 같은 고성능 CNI를 사용하고, 상태없는 앱에서는 불필요한 PV 마운트를 제거하는 것만으로도 배포 속도가 개선됩니다.

11. ConfigMap/Secret으로 설정 외부화

환경별 설정을 ConfigMap으로 분리하면 이미지 재빌드 없이 배포가 가능합니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  LOG_LEVEL: "info"
  DB_HOST: "postgres.cluster"

설정이 복잡한 앱에서는 배포 속도가 5배 향상되는 경우도 봤어요.

12. 모니터링으로 지속적 개선하기

Prometheus와 Grafana로 배포 시간을 추적하고, 2분을 초과하는 배포에 대해 알림을 설정해두면 성능 저하를 빠르게 감지할 수 있습니다.

메트릭 목표값 모니터링 도구
배포 시간 < 2분 Grafana
이미지 풀 시간 < 30초 kubectl describe
파드 시작 시간 < 15초 Prometheus
롤아웃 성공률 > 95% ArgoCD/Flux

정기적인 감사를 통해 50%의 속도 향상을 유지하는 팀들이 많더라고요.

작은 변화가 만드는 큰 차이

이런 최적화 기법들을 하나씩 적용해보니, 배포에 대한 스트레스가 많이 줄었습니다. 무엇보다 핫픽스가 필요한 순간에 여유를 가질 수 있게 된 게 가장 큰 변화인 것 같아요.

#Kubernetes#DevOps#Container#배포최적화#GitOps