Kubernetes에서 Ingress 애노테이션을 활용한 단계적 배포 실습

현대의 마이크로서비스 아키텍처에서는 응용 프로그램의 업데이트와 배포가 매우 빈번하고 중요한 작업입니다. 사용자 경험에 영향을 주지 않으면서 안전하고 원활하게 새로운 버전의 애플리케이션을 프로덕션 환경으로 이동시키는 것은 모든 개발자와 운영 팀이 해결해야 할 과제입니다. 단계적 배포(그레이스풀 리릴리즈)는 출시 위험을 줄이는 데 효과적인 점진적인 배포 전략이며, Kubernetes의 Ingress 애노테이션 기능은 이를 간단하고 강력하게 구현하는 방법을 제공합니다.

이 문서에서는 Kubernetes에서 Ingress 애노테이션을 사용하여 단계적 배포를 어떻게 수행할 수 있는지 자세히 설명하며, 트래픽 분배 및 가중치 제어와 같은 핵심 기술을 단계적으로 익힐 수 있습니다. Kubernetes 초보자나 숙련된 사용자 모두에게 유용한 지식과 실행 가이드를 제공합니다.

단계적 배포란?

단계적 배포 또는 캔러리 배포(Canary Release)는 점진적인 애플리케이션 배포 전략입니다. 이 방식의 핵심 아이디어는 다음과 같습니다: 새로운 버전의 애플리케이션을 소수의 사용자에게만 단계적으로 배포하여 그 상태를 관찰하고 문제가 없다면 점차 범위를 확장하여 완전한 배포를 완료합니다.

전체 배포에 비해 단계적 배포는 다음과 같은 이점이 있습니다:

  1. 위험 감소: 전체 시스템 고장을 방지하기 위해 작은 범위에서 새 버전을 검증합니다.
  2. 빠른 롤백: 새 버전에 문제가 발생하면 기존 버전으로 신속하게 복귀할 수 있습니다.
  3. 사용자 경험이 개선됨: 점진적인 배포로 인해 사용자에게 미치는 영향을 최소화합니다.

Kubernetes에서 단계적 배포 구현 방법

Kubernetes에서는 다양한 방법으로 단계적 배포를 구현할 수 있습니다:

  • Deployment + Service: 트래픽 스위칭을 수동으로 제어합니다.
  • Istio: 서비스 메시를 통해 고급 트래픽 관리를 수행합니다.
  • Ingress 애노테이션: Nginx Ingress 컨트롤러의 애노테이션 기능을 사용하여 트래픽을 분배합니다.

본 문서에서는 간단하고 추가 구성 요소 없이도 사용 가능한 Ingress 애노테이션 방법에 중점을 두겠습니다.

Ingress 애노테이션을 통한 단계적 배포

Nginx Ingress 컨트롤러는 단계적 배포를 쉽게 구현할 수 있도록 다양한 애노테이션(Annotations)을 제공합니다. 아래는 구체적인 단계입니다:

  1. 기존 및 새 버전 애플리케이션 배포

먼저 두 가지 버전의 애플리케이션을 배포해야 합니다:

  • 기존 버전(v1): 현재 프로덕션에서 실행 중인 버전.
  • 새 버전(v2): 배포될 예정인 새 버전.

1.1 v1 버전 Deployment 및 Service 생성

# v1 버전 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-old-version
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
        version: old
    spec:
      containers:
      - name: app-container
        image: my-app:old
        ports:
        - containerPort: 80

# v1 버전 Service
apiVersion: v1
kind: Service
metadata:
  name: service-old
spec:
  selector:
    app: my-app
    version: old
  ports:
  - port: 80
    targetPort: 80

1.2 v2 버전 Deployment 및 Service 생성

# v2 버전 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-new-version
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
        version: new
    spec:
      containers:
      - name: app-container
        image: my-app:new
        ports:
        - containerPort: 80

# v2 버전 Service
apiVersion: v1
kind: Service
metadata:
  name: service-new
spec:
  selector:
    app: my-app
    version: new
  ports:
  - port: 80
    targetPort: 80
  1. Ingress 설정을 통한 단계적 배포

Nginx Ingress Controller의 canary 애노테이션을 사용하여 트래픽 분배를 쉽게 구현할 수 있습니다.

2.1 Ingress 리소스 생성

다음은 예제 구성입니다:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: progressive-deployment
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"  # 단계적 배포 활성화
    nginx.ingress.kubernetes.io/canary-weight: "20"  # 새 버전으로 20% 트래픽 전송
spec:
  rules:
  - host: example.myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-new
            port:
              number: 80
  - host: example.myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-old
            port:
              number: 80

2.2 주요 애노테이션 설명

  • nginx.ingress.kubernetes.io/canary: "true": 단계적 배포 기능 활성화.
  • nginx.ingress.kubernetes.io/canary-weight: "20": 새 버전(v2)으로 20%의 트래픽을 전달하고 나머지 80%는 기존 버전(v1)으로 유지.
  1. 트래픽 가중치 점진적 조정

단계적 배포 과정에서 새 버전으로 전달되는 트래픽 비율을 점진적으로 증가시킬 수 있습니다:

  • 초기 단계: v2로 20% 트래픽 전달.
  • 확인 후: 가중치를 70%로 조정.
  • 최종 단계: 가중치를 100%로 조정하여 전체 배포 완료.

canary-weight 애노테이션 값을 수정하여 조정 가능:

nginx.ingress.kubernetes.io/canary-weight: "70"  # 새 버전으로 70% 트래픽 전달
  1. 모니터링 및 롤백

단계적 배포 과정에서 새 버전의 상태를 꾸준히 모니터링해야 합니다:

  • 애플리케이션 로그: 오류나 예외가 있는지 확인.
  • 성능 지표: 응답 시간, 오류율 등.
  • 사용자 피드백: 사용자 경험 수집.

문제가 발견되면 canary-weight 애노테이션을 조정하여 트래픽을 기존 버전으로 되돌릴 수 있습니다:

nginx.ingress.kubernetes.io/canary-weight: "0"  # 모든 트래픽을 기존 버전으로 이동

고급 단계적 배포 방법

가중치 기반 트래픽 분배 외에도 Nginx Ingress Controller는 다음 단계적 배포 전략을 지원합니다:

  1. 요청 헤더 기반 트래픽 분배

nginx.ingress.kubernetes.io/canary-by-header 애노테이션을 사용하여 특정 요청 헤더의 트래픽을 새 버전으로 라우팅합니다.

예제 구성

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: header-based-routing
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "Custom-Header"
    nginx.ingress.kubernetes.io/canary-by-header-value: "active"
spec:
  rules:
  - host: example.myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-new
            port:
              number: 80
  - host: example.myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-old
            port:
              number: 80

설명

  • 요청 헤더에 Custom-Header: active가 포함되어 있으면 새 버전(v2)으로 라우팅됩니다.
  • 다른 요청은 기존 버전(v1)을 계속 사용합니다.
  1. 쿠키 기반 트래픽 분배

nginx.ingress.kubernetes.io/canary-by-cookie 애노테이션을 사용하여 특정 쿠키의 트래픽을 새 버전으로 라우팅합니다.

예제 구성

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cookie-based-routing
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-cookie: "testCookie"
spec:
  rules:
  - host: example.myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-new
            port:
              number: 80
  - host: example.myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-old
            port:
              number: 80

설명

  • 요청에 testCookie=true 쿠키가 포함되어 있으면 새 버전(v2)으로 라우팅됩니다.
  • 다른 요청은 기존 버전(v1)을 계속 사용합니다.
  1. 조합 사용

가중치, 요청 헤더 및 쿠키를 동시에 사용하여 더 복잡한 단계적 배포 전략을 구현할 수 있습니다.

예제 구성

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: combined-strategy
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "15"
    nginx.ingress.kubernetes.io/canary-by-header: "Special-Header"
    nginx.ingress.kubernetes.io/canary-by-header-value: "enable"
    nginx.ingress.kubernetes.io/canary-by-cookie: "customCookie"
spec:
  rules:
  - host: example.myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-new
            port:
              number: 80
  - host: example.myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-old
            port:
              number: 80

설명

  • 15%의 트래픽은 새 버전(v2)으로 전달됩니다.
  • 요청 헤더에 Special-Header: enable 또는 쿠키에 customCookie=true가 포함된 경우에도 새 버전으로 라우팅됩니다.

태그: kubernetes ingress canary-release

9월 13일 23:56에 게시됨