K8s Flagger 프로그레시브 딜리버리

Flagger란 무엇인가

Flagger는 Kubernetes 위에서 프로그레시브 딜리버리(Progressive Delivery)를 자동화하는 오픈소스 도구입니다. Weaveworks가 개발했으며, 카나리(Canary), 블루/그린(Blue/Green), A/B 테스트 배포 전략을 메트릭 기반으로 자동 승격·롤백합니다. Istio, Linkerd, Nginx Ingress, Contour, Gloo 등 다양한 메시/인그레스 프로바이더를 지원합니다.

기존 ArgoCD나 Flux로 GitOps를 구현했더라도, 실제 트래픽을 점진적으로 전환하며 메트릭을 분석해 자동 롤백하는 기능은 Flagger가 담당합니다. 배포와 딜리버리는 다른 문제이며, Flagger는 후자에 집중합니다.

아키텍처 이해

Flagger는 Kubernetes CRD인 Canary 리소스를 통해 동작합니다. 핵심 구성 요소는 다음과 같습니다:

  • Primary (안정 버전): 현재 프로덕션 트래픽을 받는 Pod 세트
  • Canary (신규 버전): 점진적으로 트래픽을 받을 새 버전
  • Metric Provider: Prometheus, Datadog, CloudWatch 등에서 성공률·지연시간 조회
  • Webhook: 승격/롤백 시 Slack 알림, 로드 테스트 트리거 등 외부 연동

Flagger가 Canary 리소스를 감지하면, 원본 Deployment를 복제하여 <name>-primary Deployment와 Service를 자동 생성합니다. 이후 원본 Deployment에 이미지 변경이 감지되면 카나리 분석 루프가 시작됩니다.

설치 및 기본 설정

Helm으로 Flagger와 Prometheus 메트릭 서버를 설치합니다:

helm repo add flagger https://flagger.app
helm repo update

# Flagger 설치 (Istio 프로바이더 기준)
helm upgrade -i flagger flagger/flagger 
  --namespace=istio-system 
  --set crd.create=true 
  --set meshProvider=istio 
  --set metricsServer=http://prometheus:9090

# Flagger Loadtester (카나리 분석 시 부하 생성용)
helm upgrade -i flagger-loadtester flagger/loadtester 
  --namespace=test

Nginx Ingress를 사용한다면 meshProvider=nginx로 변경하고, --set nginx.create=true를 추가합니다.

카나리 배포 전략 심화

가장 핵심적인 Canary 리소스 정의를 살펴봅니다:

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: backend-api
  namespace: production
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: backend-api
  progressDeadlineSeconds: 600
  service:
    port: 8080
    targetPort: 8080
    gateways:
      - public-gateway.istio-system.svc.cluster.local
    hosts:
      - api.example.com
  analysis:
    interval: 1m          # 메트릭 체크 간격
    threshold: 5           # 실패 허용 횟수
    maxWeight: 50          # 최대 카나리 트래픽 비율
    stepWeight: 10         # 단계별 증가량
    metrics:
      - name: request-success-rate
        thresholdRange:
          min: 99          # 99% 이상 성공률 필요
        interval: 1m
      - name: request-duration
        thresholdRange:
          max: 500         # p99 지연시간 500ms 이하
        interval: 30s
    webhooks:
      - name: load-test
        type: rollout
        url: http://flagger-loadtester.test/
        metadata:
          cmd: "hey -z 1m -q 10 -c 2 http://backend-api-canary.production:8080/"
      - name: slack-notify
        type: event
        url: http://flagger-loadtester.test/slack
        metadata:
          channel: deployments

이 설정의 동작 흐름은 다음과 같습니다:

단계 카나리 트래픽 동작
1 0% 이미지 변경 감지, 카나리 Pod 생성
2 10% 첫 번째 stepWeight 적용, 메트릭 수집 시작
3 20% 성공률 99%↑, 지연시간 500ms↓ 충족 시 증가
4 30~50% 계속 메트릭 충족 시 stepWeight만큼 증가
5 100% 승격: canary → primary 교체 완료

만약 어느 단계에서든 메트릭 기준을 threshold 횟수만큼 연속 실패하면, Flagger는 즉시 롤백하고 모든 트래픽을 Primary로 복원합니다.

블루/그린 배포 전략

카나리와 달리 트래픽을 점진적으로 나누지 않고, 전체를 한 번에 전환하는 방식입니다. Flagger에서는 analysis에서 트래픽 가중치 대신 iteration 기반으로 설정합니다:

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: frontend
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: frontend
  service:
    port: 80
  analysis:
    interval: 1m
    threshold: 3
    iterations: 10        # 10회 반복 체크 후 승격
    # maxWeight/stepWeight 없음 → 블루/그린 모드
    metrics:
      - name: request-success-rate
        thresholdRange:
          min: 99
        interval: 1m
    webhooks:
      - name: smoke-test
        type: pre-rollout
        url: http://flagger-loadtester.test/
        metadata:
          type: bash
          cmd: "curl -sf http://frontend-canary.production/"

블루/그린에서는 카나리 Pod가 준비되면 pre-rollout 웹훅으로 스모크 테스트를 실행합니다. 이후 iterations 횟수만큼 메트릭을 검증한 뒤, 통과하면 서비스 셀렉터를 전환하여 한 번에 트래픽을 이동합니다.

커스텀 메트릭 정의

내장 메트릭 외에 비즈니스 로직 기반 커스텀 메트릭을 정의할 수 있습니다:

apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
  name: error-rate-by-route
  namespace: production
spec:
  provider:
    type: prometheus
    address: http://prometheus.monitoring:9090
  query: |
    100 - (
      sum(rate(http_requests_total{
        namespace="{{ namespace }}",
        pod=~"{{ target }}-[0-9a-zA-Z]+",
        status!~"5.*",
        route="{{ route }}"
      }[{{ interval }}]))
      /
      sum(rate(http_requests_total{
        namespace="{{ namespace }}",
        pod=~"{{ target }}-[0-9a-zA-Z]+",
        route="{{ route }}"
      }[{{ interval }}]))
    ) * 100

Canary 리소스에서 이 템플릿을 참조합니다:

metrics:
  - name: "payment-error-rate"
    templateRef:
      name: error-rate-by-route
      namespace: production
    templateVariables:
      route: "/api/v1/payments"
    thresholdRange:
      max: 1    # 결제 API 에러율 1% 이하
    interval: 1m

이처럼 특정 API 경로의 에러율, 특정 gRPC 메서드의 지연시간 등 세밀한 기준을 설정할 수 있어 비즈니스 크리티컬 엔드포인트에 대한 안전한 배포가 가능합니다.

GitOps 연동: Flux + Flagger

Flux와 Flagger를 함께 사용하면 완전한 GitOps 프로그레시브 딜리버리 파이프라인을 구축할 수 있습니다:

# HelmRelease 정의 (Flux)
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: backend-api
spec:
  interval: 5m
  chart:
    spec:
      chart: ./charts/backend-api
      sourceRef:
        kind: GitRepository
        name: app-repo
  values:
    image:
      repository: ghcr.io/myorg/backend-api
      tag: v2.3.1  # Git에서 이 값만 변경하면 자동 배포

워크플로우는 다음과 같습니다:

  • 1단계: 개발자가 Git에서 이미지 태그 변경 → PR 머지
  • 2단계: Flux가 변경 감지 → HelmRelease 적용 → Deployment 업데이트
  • 3단계: Flagger가 Deployment 변경 감지 → 카나리 분석 시작
  • 4단계: 메트릭 기반 자동 승격 또는 롤백
  • 5단계: Slack/PagerDuty 웹훅으로 결과 알림

Alert 및 알림 설정

Flagger는 자체 AlertProvider CRD를 제공합니다:

apiVersion: flagger.app/v1beta1
kind: AlertProvider
metadata:
  name: slack-alert
  namespace: production
spec:
  type: slack
  channel: deploy-alerts
  address: https://hooks.slack.com/services/T00/B00/xxx
---
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: backend-api
spec:
  # ... 기존 설정 ...
  analysis:
    alerts:
      - name: "deploy-slack"
        severity: info
        providerRef:
          name: slack-alert

Slack 외에도 Microsoft Teams, Discord, Rocket.Chat을 기본 지원하며, 범용 웹훅으로 어떤 시스템이든 연동 가능합니다.

Nginx Ingress 프로바이더 실전 설정

Istio 없이 Nginx Ingress만으로도 카나리 배포를 구현할 수 있습니다. Flagger가 Nginx의 canary-weight 어노테이션을 자동 관리합니다:

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: web-app
spec:
  provider: nginx
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  ingressRef:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    name: web-app
  service:
    port: 80
  analysis:
    interval: 1m
    threshold: 5
    maxWeight: 50
    stepWeight: 5
    metrics:
      - name: request-success-rate
        thresholdRange:
          min: 99
        interval: 1m

Flagger는 내부적으로 web-app-canary Ingress를 생성하고, nginx.ingress.kubernetes.io/canary-weight 어노테이션을 5%씩 증가시킵니다. 서비스 메시 없이도 L7 수준의 카나리 배포를 실현합니다.

트러블슈팅 및 운영 팁

실제 운영 시 자주 만나는 문제와 해결 방법입니다:

  • 카나리가 Initializing에서 멈춤: kubectl describe canary <name>로 이벤트 확인. HPA가 있다면 autoscalerRef를 반드시 Canary에 지정해야 합니다.
  • 메트릭이 수집되지 않음: Prometheus 쿼리를 직접 실행하여 데이터 존재 여부 확인. flagger_canary_weight 메트릭으로 현재 상태를 모니터링합니다.
  • 롤백이 너무 잦음: threshold 값을 높이거나, interval을 늘려 일시적 스파이크에 의한 오탐을 줄입니다.
  • ConfigMap/Secret 변경 감지: Canary spec에 configTracking을 활성화하면 Config 변경 시에도 카나리 분석을 트리거합니다.
# Flagger 상태 모니터링 명령어
kubectl get canaries -A
kubectl describe canary backend-api -n production
kubectl logs -n istio-system deploy/flagger -f

# Grafana 대시보드용 주요 메트릭
flagger_canary_weight          # 현재 카나리 트래픽 비율
flagger_canary_status          # 0=초기화, 1=진행중, 2=성공, 3=실패
flagger_canary_duration_seconds # 카나리 분석 소요 시간

프로덕션 체크리스트

Flagger를 프로덕션에 도입하기 전 확인해야 할 사항입니다:

  • ✅ Prometheus 또는 Datadog 등 메트릭 수집 파이프라인 구축 완료
  • ✅ 대상 서비스에 PodDisruptionBudget 설정
  • ResourceQuota/LimitRange로 네임스페이스 리소스 제한
  • ✅ Slack/Teams 알림 웹훅 연동
  • ✅ 로드 테스터 또는 스모크 테스트 스크립트 준비
  • ✅ 롤백 시나리오 사전 테스트 (의도적 에러 주입)
  • ✅ HPA 사용 시 autoscalerRef 설정 확인

정리

Flagger는 메트릭 기반 자동 카나리 분석이라는 핵심 가치를 제공합니다. 수동으로 트래픽 비율을 조정하고 대시보드를 감시하는 대신, 선언적으로 성공 기준을 정의하면 나머지는 Flagger가 처리합니다. GitOps(Flux/ArgoCD) + Flagger 조합은 현재 Kubernetes 생태계에서 가장 성숙한 프로그레시브 딜리버리 솔루션입니다.

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux