Kubernetes 배포에서 다운타임 없는 롤링 업데이트 수행 방법

Kubernetes 배포에서 다운타임 없는 롤링 업데이트를 수행하는 기술을 마스터하세요. 이 전문가 가이드에서는 전환 중에 지속적인 애플리케이션 가용성을 유지하는 데 필요한 필수 구성을 자세히 설명합니다. 강력한 준비 프로브(Readiness Probes)를 구현하고, 최대 가동 시간을 위해 `maxSurge` 및 `maxUnavailable` 배포 전략을 조정하며, 애플리케이션의 정상적인 종료를 보장하는 방법을 알아보세요. 이러한 실용적인 단계를 따르면 서비스 중단을 제거하고 최종 사용자에게 원활한 업데이트를 제공할 수 있습니다.

31 조회수

Kubernetes 배포에서 제로 다운타임 롤링 업데이트 수행 방법

소개

현대의 마이크로서비스 아키텍처에서 애플리케이션 업데이트 중 지속적인 가용성을 유지하는 것은 필수적인 요구 사항입니다. Kubernetes 배포는 기존 Pod 버전을 새 버전으로 점진적으로 교체하도록 설계된 전략인 자동 롤링 업데이트를 제공하여 이 프로세스를 간소화합니다.

하지만 진정한 제로 다운타임을 달성하려면 기본 Kubernetes 구성 이상의 것이 필요합니다. 이는 배포 매니페스트, 애플리케이션의 상태 엔드포인트, 그리고 정상 종료 프로세스 간의 신중한 조정이 필요합니다. 이 가이드는 애플리케이션 업데이트가 최종 사용자에게 원활하고 보이지 않도록 Kubernetes 배포를 구성하는 포괄적인 단계별 접근 방식을 제공합니다.

준비 상태 프로브의 중요한 역할, 배포 전략 매개변수(maxSurgemaxUnavailable) 조정 방법, 그리고 배포 전환 중 서비스 중단을 제거하기 위한 애플리케이션 종료 모범 사례를 다룰 것입니다.

제로 다운타임을 위한 사전 요구 사항

Kubernetes 매니페스트를 구성하기 전에 기본 애플리케이션이 제로 다운타임 배포를 지원하기 위해 특정 원칙을 준수해야 합니다.

  1. 애플리케이션 하위 호환성: 애플리케이션의 이전 버전과 새 버전이 동시에 실행되는 짧은 기간 동안에는 공유 리소스(데이터베이스, 큐, 캐시)와 호환되어야 합니다.
  2. 멱등성: 두 버전 모두에서 처리될 수 있는 작업은 부정적인 부작용 없이 반복 가능해야 합니다.
  3. 정상 종료: 애플리케이션은 Kubernetes가 보내는 SIGTERM 신호를 인식하고 종료하기 전에 현재 진행 중인 요청을 완료하면서 새 연결 수락을 정기적으로 중지하도록 프로그래밍되어야 합니다.

Kubernetes 롤링 업데이트 전략 이해

Kubernetes 배포는 기본적으로 RollingUpdate 전략을 사용합니다. 이 방법은 새 버전이 작동되기 전에 이전 애플리케이션 버전이 완전히 다운되지 않도록 보장하며, 두 가지 주요 매개변수를 사용하여 전환을 관리합니다.

매개변수 설명 제로 다운타임 영향
maxSurge 원하는 복제본 수를 초과하여 생성할 수 있는 최대 Pod 수를 정의합니다. 절대값 또는 백분율(기본값: 25%)로 지정할 수 있습니다. 롤아웃 속도를 제어하고 용량이 일시적으로 증가하도록 보장합니다.
maxUnavailable 업데이트 중에 사용할 수 없는 최대 Pod 수를 정의합니다. 절대값 또는 백분율(기본값: 25%)로 지정할 수 있습니다. 제로 다운타임에 중요합니다. 0%로 설정하면 새 Pod가 완전히 Ready 상태가 될 때까지 서비스 중인 Pod가 종료되지 않습니다.

제로 다운타임을 위한 권장 전략

최고의 가용성을 위해, 제로 다운타임 용량 손실을 보장하는 것이 가장 좋은 구성입니다.

  • maxUnavailable: 0 (용량이 절대 떨어지지 않도록 합니다).
  • maxSurge: 1 또는 25% (용량이 대상보다 약간 초과되도록 허용하여 이전 Pod가 종료되기 전에 새 Pod가 준비되도록 합니다).

1단계: 준비 상태 프로브 구현

준비 상태 프로브는 제로 다운타임 업데이트를 보장하는 가장 중요한 메커니즘입니다. Kubernetes는 이 프로브를 사용하여 새 Pod가 사용자 트래픽을 받을 준비가 되었는지, 그리고 이전 Pod가 여전히 활발하게 트래픽을 처리 중인지 판단합니다.

라이브니스 vs. 준비 상태

  • 라이브니스 프로브: 컨테이너가 정상적이고 기능적인지 Kubernetes에 알립니다. 실패하면 컨테이너가 다시 시작됩니다.
  • 준비 상태 프로브: 컨테이너가 요청을 처리할 준비가 되었는지 Kubernetes에 알립니다. 실패하면 Pod는 연결된 서비스 엔드포인트에서 제거되어 준비 상태가 될 때까지 트래픽을 해당 Pod로 보내지 않습니다.

롤링 업데이트의 경우, 준비 상태 프로브가 전환을 제어하는 데 사용됩니다. Kubernetes는 새로 생성된 Pod가 준비 상태 확인을 성공적으로 통과할 때까지 이전 Pod를 종료하지 않습니다.

# deployment.yaml 발췌
spec:
  containers:
  - name: my-app
    image: myregistry/my-app:v2.0
    ports:
    - containerPort: 8080

    # --- 준비 상태 프로브 구성 ---
    readinessProbe:
      httpGet:
        path: /health/ready
        port: 8080
      initialDelaySeconds: 15  # 첫 번째 프로브 시도 전에 기다리는 시간
      periodSeconds: 5         # 확인을 수행하는 빈도
      timeoutSeconds: 3
      failureThreshold: 3      # Pod를 준비 안 됨으로 표시하기 위한 연속 실패 횟수

    # --- 라이브니스 프로브 구성 (표준 상태 확인) ---
    livenessProbe:
      httpGet:
        path: /health/live
        port: 8080
      initialDelaySeconds: 60
      periodSeconds: 10

팁: 애플리케이션의 /health/ready 엔드포인트가 초기화, 데이터베이스 연결 및 기타 외부 종속성이 완전히 작동할 때만 성공 코드(HTTP 200-299)를 반환하는지 확인하세요.

2단계: 배포 전략 구성

진정한 제로 다운타임을 강제하기 위해, 가용 복제본 수의 감소를 방지하도록 롤링 업데이트 전략을 명시적으로 구성합니다.

이 구성에서는 Kubernetes가 먼저 새 Pod(maxSurge: 1)를 생성합니다. 새 Pod가 준비 상태 프로브를 통과하면, Kubernetes가 이전 Pod를 종료합니다. maxUnavailable이 0이므로 서비스 용량은 대상 복제본 수를 절대 초과하지 않습니다.

# deployment.yaml 발췌
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-web-deployment
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      # 원하는 복제본 수(4) 이하로 용량이 떨어지지 않도록 보장
      maxUnavailable: 0 
      # 롤아웃 중에 추가 Pod 하나를 생성하도록 허용
      maxSurge: 1 
  template:
    # ... 컨테이너 사양 ...

3단계: 정상 종료 보장

강력한 준비 상태 프로브가 있어도 애플리케이션이 종료 신호를 받으면 즉시 종료되면 현재 진행 중인 요청이 손실될 위험이 있습니다.

Kubernetes는 특정 종료 시퀀스를 따릅니다.

  1. Pod가 종료 중으로 표시됩니다.
  2. Pod가 서비스 엔드포인트에서 제거됩니다(트래픽 라우팅이 중단됩니다).
  3. 사전 중지 후크(정의된 경우)가 실행됩니다.
  4. 컨테이너가 SIGTERM 신호를 받습니다.
  5. Kubernetes는 terminationGracePeriodSeconds(기본값: 30초)로 정의된 기간을 기다립니다.
  6. 컨테이너가 여전히 실행 중이면, 협상 불가한 SIGKILL을 받습니다.

정상 종료를 보장하려면 애플리케이션이 SIGTERM을 처리해야 하며, terminationGracePeriodSeconds는 애플리케이션이 기존 요청을 완료할 수 있을 만큼 충분히 길어야 합니다.

# deployment.yaml 발췌, 컨테이너 사양 내
    terminationGracePeriodSeconds: 45 # 정상 종료를 위한 시간 증가
    containers:
    - name: my-app
      image: myregistry/my-app:v2.0

      lifecycle:
        preStop:
          exec:
            # 예시: 연결을 즉시 드레인하기 위한 스크립트 실행
            command: ["/bin/sh", "-c", "sleep 10"] 

모범 사례: Pod가 준비 상태 프로브(2단계)를 실패한 시점과 SIGTERM(4단계)을 받은 시점 사이의 시간은 중요합니다. 애플리케이션이 SIGTERM을 올바르게 처리하는 경우, 약간 더 긴 terminationGracePeriodSeconds(예: 45 또는 60초)를 설정하면 강제 종료를 방지합니다.

4단계: 업데이트 수행 및 모니터링

배포 매니페스트에 최적화된 전략과 강력한 프로브가 포함되면 업데이트 수행은 간단합니다.

  1. 이미지 태그 업데이트: 배포 매니페스트를 수정하여 새 이미지 버전을 반영합니다(예: v2.0에서 v2.1).

  2. 구성 적용:

    bash kubectl apply -f deployment.yaml

    또는 이미지를 직접 패치할 수 있습니다.

    bash kubectl set image deployment/my-web-deployment my-app=myregistry/my-app:v2.1

  3. 롤아웃 상태 모니터링: Kubernetes가 단계를 진행하면서 준비된 Pod 수가 원하는 수 이하로 떨어지지 않는지 확인합니다.

    bash kubectl rollout status deployment/my-web-deployment

  4. Pod 가용성 확인: 이전 Pod(v2.0)가 새 Pod(v2.1)가 완전히 준비된 후에만 정상적으로 종료되는지 확인하기 위해 Pod 상태를 관찰합니다.

    bash kubectl get pods -l app=my-web-deployment -w

고급 고려 사항

Pod 중단 예산(PDB) 사용

배포 전략은 자발적 업데이트를 관리하지만, Pod 중단 예산(PDB)예기치 않은 중단(예: 노드 유지 보수, 클러스터 업그레이드) 중에도 최소 수의 Pod가 가용하도록 보장합니다. PDB는 롤링 업데이트 속도를 직접 제어하지 않지만 안전망 역할을 합니다.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 75%  # 복제본의 최소 75%가 항상 사용 가능하도록 보장
  selector:
    matchLabels:
      app: my-web-deployment

초기 지연의 중요성

애플리케이션이 시작하는 데 시간이 걸리는 경우(예: 대규모 구성 파일 로드 또는 캐시 설정), 준비 상태 프로브의 initialDelaySeconds가 충분히 긴지 확인하세요. 프로브가 너무 일찍 확인하고 실패하면 Pod가 비정상으로 표시되고 충돌 루프에 갇힐 수 있으며 전체 배포가 중단될 수 있습니다.

결론

Kubernetes에서 진정한 제로 다운타임 롤링 업데이트를 달성하는 것은 강력한 플랫폼 구성과 규율 잡힌 애플리케이션 개발의 조합입니다. 준비 상태 프로브를 사용하여 운영 상태를 올바르게 신호화하고, 용량을 유지하기 위해 배포 전략(maxUnavailable: 0)을 조정하고, 정상 종료 핸들러를 구현함으로써 사용자에게 서비스를 중단하지 않고 애플리케이션 업데이트를 안정적으로 수행할 수 있습니다. 항상 스테이징 환경에서 업데이트 프로세스를 철저히 테스트하여 종료 유예 기간과 프로브 논리를 검증하십시오.