Flagger

Flagger Canary(カナリア結果分析)完全ガイド

目次

  1. はじめに
  2. Flagger の概要とアーキテクチャ
  3. カナリアデプロイメントの基本概念
  4. Flagger のコアコンポーネント
  5. カナリア分析(Canary Analysis)の仕組み
  6. メトリクス分析の詳細
  7. Canary Result Analysis の内部動作
  8. カスタムメトリクスの設定
  9. Webhook と連携機能
  10. トラフィック管理の詳細
  11. サービスメッシュとの統合
  12. Ingress Controller との統合
  13. アラートと通知
  14. 高度な設定パターン
  15. トラブルシューティング
  16. 本番環境でのベストプラクティス
  17. ケーススタディ
  18. まとめ

1. はじめに

1.1 プログレッシブデリバリーの必要性

現代のソフトウェア開発において、アプリケーションのデプロイメントは最もリスクの高い作業の一つである。従来のローリングアップデートやブルー/グリーンデプロイメントでは、新バージョンが本番環境のトラフィックに完全にさらされる前に、その品質を十分に検証することが困難であった。

プログレッシブデリバリーは、この課題を解決するためのデプロイメント戦略であり、新バージョンのリリースを段階的に行い、各段階で自動的な品質検証を実施する。問題が検出された場合は即座にロールバックを行い、本番環境への影響を最小限に抑える。

1.2 Flagger とは

Flagger は、Kubernetes 上でプログレッシブデリバリーを実現するオープンソースのオペレーターである。Weaveworks(現在は Flux プロジェクトの一部)によって開発され、以下のデプロイメント戦略をサポートする:

  • カナリアデプロイメント(Canary Deployment):トラフィックを段階的に新バージョンに移行
  • A/B テスト(A/B Testing):HTTP ヘッダやクッキーに基づくトラフィック分割
  • ブルー/グリーンデプロイメント(Blue/Green Deployment):ミラーリングとトラフィック切り替え

本稿では、特にカナリアデプロイメントにおける**カナリア結果分析(Canary Result Analysis)**に焦点を当て、その仕組み、設定方法、および実践的な活用方法について詳細に解説する。

1.3 本稿の対象読者

  • Kubernetes クラスタの運用に携わる SRE エンジニア
  • プログレッシブデリバリーの導入を検討しているプラットフォームエンジニア
  • Flagger の設定をより深く理解したいデベロッパー
  • カナリア分析の自動化に興味を持つ DevOps エンジニア

2. Flagger の概要とアーキテクチャ

2.1 全体アーキテクチャ

Flagger は Kubernetes のカスタムリソース定義(CRD)を使用して動作するコントローラーである。以下に全体アーキテクチャを示す。

┌─────────────────────────────────────────────────────────────┐
│                    Kubernetes Cluster                         │
│                                                               │
│  ┌──────────────┐    ┌──────────────┐    ┌───────────────┐  │
│  │   Flagger     │    │  Metrics     │    │  Service Mesh  │  │
│  │  Controller   │◄──►│  Server      │    │  / Ingress     │  │
│  │              │    │ (Prometheus) │    │  Controller    │  │
│  └──────┬───────┘    └──────────────┘    └───────┬───────┘  │
│         │                                         │           │
│         ▼                                         ▼           │
│  ┌──────────────┐    ┌──────────────┐    ┌───────────────┐  │
│  │   Canary      │    │   Primary    │    │    Canary      │  │
│  │   CRD         │    │   Service    │    │    Service     │  │
│  │  (Config)     │    │  & Deploy    │    │   & Deploy     │  │
│  └──────────────┘    └──────────────┘    └───────────────┘  │
│                                                               │
│  ┌──────────────┐    ┌──────────────┐                        │
│  │  Webhooks     │    │  Alert       │                        │
│  │  (confirm/    │    │  Providers   │                        │
│  │   rollback)   │    │ (Slack etc)  │                        │
│  └──────────────┘    └──────────────┘                        │
└─────────────────────────────────────────────────────────────┘

2.2 動作フロー

Flagger の基本的な動作フローは以下の通りである:

  1. 変更検出:Flagger コントローラーが Deployment/DaemonSet の変更(コンテナイメージ、環境変数など)を検出する
  2. カナリアインスタンス作成:新バージョンのカナリアデプロイメントを作成する
  3. トラフィック段階的移行:設定に基づいてトラフィックを段階的にカナリアに移行する
  4. メトリクス分析:各ステップでメトリクスを収集・分析し、閾値を評価する
  5. プロモーション/ロールバック:分析結果に基づいてプロモーション(昇格)またはロールバックを実行する

2.3 Flagger が管理するリソース

Flagger は Canary CRD の定義に基づいて、以下のリソースを自動的に作成・管理する:

リソース命名規則用途
Primary Deployment<name>-primary安定版のデプロイメント
Primary Service<name>-primary安定版へのルーティング
Canary Service<name>-canaryカナリア版へのルーティング
Apex Service<name>トラフィック分割の基点
VirtualService/TrafficSplit設定依存トラフィック管理
# 初期状態のリソース構成例
apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
  namespace: test
spec:
  replicas: 2
  selector:
    matchLabels:
      app: podinfo
  template:
    metadata:
      labels:
        app: podinfo
    spec:
      containers:
      - name: podinfo
        image: ghcr.io/stefanprodan/podinfo:6.0.0
        ports:
        - containerPort: 9898
          name: http
        resources:
          requests:
            cpu: 100m
            memory: 64Mi
          limits:
            cpu: 200m
            memory: 128Mi

Flagger が初期化を完了すると、以下のリソースが自動生成される:

Deployments:
  podinfo          (0 replicas - 元のDeploymentはスケールダウンされる)
  podinfo-primary  (2 replicas - Flaggerが管理するプライマリ)

Services:
  podinfo          (apex - トラフィックのエントリポイント)
  podinfo-primary  (プライマリPodへのルーティング)
  podinfo-canary   (カナリアPodへのルーティング)

2.4 コントローラーの起動オプション

Flagger コントローラーの主要な起動パラメータは以下の通りである:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flagger
  namespace: flagger-system
spec:
  template:
    spec:
      containers:
      - name: flagger
        image: ghcr.io/fluxcd/flagger:1.37.0
        args:
        - -mesh-provider=istio           # サービスメッシュプロバイダー
        - -metrics-server=http://prometheus.monitoring:9090  # メトリクスサーバーURL
        - -log-level=info                # ログレベル
        - -include-label-prefix=app.kubernetes.io  # ラベル同期のプレフィックス
        - -enable-config-tracking=true   # ConfigMap/Secret変更の追跡
        - -slot=default                  # コントローラースロット
        - -namespace=                    # 監視対象ネームスペース(空=全て)

3. カナリアデプロイメントの基本概念

3.1 カナリアリリースとは

カナリアリリースは、炭鉱のカナリアに由来するデプロイメント手法である。少量のトラフィックを新バージョンに振り向け、問題がないことを確認してから徐々にトラフィックを増加させる。

トラフィック移行の時系列:

Step 0:  [████████████████████████████████████████] 100% Primary / 0% Canary
Step 1:  [████████████████████████████████████░░░░] 90% Primary / 10% Canary
Step 2:  [████████████████████████████████░░░░░░░░] 80% Primary / 20% Canary
Step 3:  [██████████████████████████░░░░░░░░░░░░░░] 70% Primary / 30% Canary
Step 4:  [████████████████████░░░░░░░░░░░░░░░░░░░░] 50% Primary / 50% Canary
Step 5:  [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 0% Primary / 100% Canary
         (プロモーション完了)

3.2 Flagger のカナリア CRD

Flagger のカナリア設定は Canary カスタムリソースで定義する。以下は基本的な設定例である:

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: podinfo
  namespace: test
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: podinfo
  autoscalerRef:
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    name: podinfo
  service:
    port: 9898
    portName: http
    targetPort: 9898
    trafficPolicy:
      tls:
        mode: ISTIO_MUTUAL
    retries:
      attempts: 3
      perTryTimeout: 1s
      retryOn: "gateway-error,connect-failure,refused-stream"
  analysis:
    interval: 1m
    threshold: 10
    maxWeight: 50
    stepWeight: 5
    metrics:
    - name: request-success-rate
      thresholdRange:
        min: 99
      interval: 1m
    - name: request-duration
      thresholdRange:
        max: 500
      interval: 1m
    webhooks:
    - name: load-test
      type: rollout
      url: http://flagger-loadtester.test/
      timeout: 15s
      metadata:
        cmd: "hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/"

3.3 カナリア分析のライフサイクル

カナリアリリースは以下のステータスで遷移する:

ステータス説明
InitializedFlagger がリソースの初期化を完了。カナリア分析待機状態
Progressing変更が検出され、カナリア分析が進行中
Promotingメトリクス閾値をパスし、プロモーション処理中
Finalisingプロモーション完了、リソースのクリーンアップ中
Succeededカナリアリリースが正常に完了
Failedメトリクス閾値違反またはWebhookエラーによりロールバック

3.4 ステートマシンの詳細

                    ┌────────────────────┐
                    │    Initialized     │
                    └────────┬───────────┘
                             │ (変更検出)
                             ▼
                    ┌────────────────────┐
              ┌────►│    Progressing     │◄───┐
              │     └────────┬───────────┘    │
              │              │                 │
              │    ┌─────────┴─────────┐      │
              │    ▼                    ▼      │
         (重み増加) │              (閾値違反)  │
              │    │                    │      │
              │    ▼                    ▼      │
              │ ┌──────┐        ┌──────────┐  │
              │ │分析OK│        │分析NG    │  │
              │ └──┬───┘        └────┬─────┘  │
              │    │                  │        │
              │    ▼                  ▼        │
              │ maxWeight     ┌──────────┐    │
              │ 未到達?       │  Failed   │    │
              └───YES         └──────────┘    │
                   │                           │
                   ▼ NO                        │
            ┌──────────────┐                   │
            │  Promoting   │                   │
            └──────┬───────┘                   │
                   ▼                           │
            ┌──────────────┐                   │
            │  Finalising  │                   │
            └──────┬───────┘                   │
                   ▼                           │
            ┌──────────────┐                   │
            │  Succeeded   │───────────────────┘
            └──────────────┘    (次回変更検出時)

4. Flagger のコアコンポーネント

4.1 コントローラーマネージャー

Flagger のコントローラーマネージャーは、Kubernetes の controller-runtime を基盤として構築されている。主要なコンポーネントは以下の通りである:

┌─────────────────────────────────────────────────┐
│              Flagger Controller                    │
│                                                    │
│  ┌─────────────────┐  ┌──────────────────────┐  │
│  │  Canary          │  │  Scheduler            │  │
│  │  Reconciler      │  │  (CanaryJob)          │  │
│  │                  │  │                       │  │
│  │  - Initialize    │  │  - 定期実行 (interval)│  │
│  │  - Reconcile     │  │  - メトリクス収集      │  │
│  │  - Promote       │  │  - 閾値評価           │  │
│  │  - Rollback      │  │  - Webhook呼び出し     │  │
│  └─────────────────┘  └──────────────────────┘  │
│                                                    │
│  ┌─────────────────┐  ┌──────────────────────┐  │
│  │  Router           │  │  Observer             │  │
│  │                   │  │                       │  │
│  │  - Istio         │  │  - Prometheus         │  │
│  │  - Linkerd       │  │  - Datadog            │  │
│  │  - App Mesh      │  │  - CloudWatch         │  │
│  │  - Contour       │  │  - New Relic          │  │
│  │  - Gloo          │  │  - Graphite           │  │
│  │  - NGINX         │  │  - Dynatrace          │  │
│  │  - Skipper       │  │  - InfluxDB           │  │
│  │  - Traefik       │  │  - Stackdriver        │  │
│  │  - OSM           │  │  - Kayenta            │  │
│  │  - Kuma          │  │                       │  │
│  │  - GatewayAPI    │  │                       │  │
│  └─────────────────┘  └──────────────────────┘  │
└─────────────────────────────────────────────────┘

4.2 Reconciliation ループ

// 擬似コード:Reconciliation ループの概要
func (c *Controller) Reconcile(canary *flaggerv1.Canary) {
    // 1. ターゲットリソースの状態確認
    target, err := c.getTarget(canary)

    // 2. プライマリリソースの初期化(必要に応じて)
    if !c.isInitialized(canary) {
        c.initialize(canary)
        return
    }

    // 3. 変更検出
    if c.hasChanged(canary, target) {
        c.startCanaryAnalysis(canary)
        return
    }

    // 4. 分析進行中の場合
    if canary.Status.Phase == Progressing {
        result := c.analyzeMetrics(canary)
        if result == Failed {
            c.rollback(canary)
            return
        }
        if c.shouldPromote(canary) {
            c.promote(canary)
        } else {
            c.increaseWeight(canary)
        }
    }
}

4.3 メッシュプロバイダーインターフェース

type Router interface {
    Initialize(canary *flaggerv1.Canary) error
    SetRoutes(canary *flaggerv1.Canary, primaryWeight int, canaryWeight int) error
    GetRoutes(canary *flaggerv1.Canary) (primaryWeight int, canaryWeight int, mirrored bool, err error)
    Reconcile(canary *flaggerv1.Canary) error
    Finalize(canary *flaggerv1.Canary) error
}

4.4 メトリクスオブザーバーインターフェース

type Observer interface {
    GetRequestSuccessRate(model flaggerv1.MetricTemplateModel) (float64, error)
    GetRequestDuration(model flaggerv1.MetricTemplateModel) (time.Duration, error)
    IsOnline() (bool, error)
}

type MetricTemplateProvider interface {
    RunQuery(query string) (float64, error)
    IsOnline() (bool, error)
}

5. カナリア分析(Canary Analysis)の仕組み

5.1 分析エンジンの概要

Flagger のカナリア分析エンジンは、デプロイメントの安全性を自動的に判定する中核機能である。分析エンジンは以下の要素で構成される:

  1. メトリクスクエリエンジン:メトリクスプロバイダーからデータを取得
  2. 閾値評価エンジン:取得したメトリクスを閾値と比較
  3. 判定ロジック:分析結果に基づくプロモーション/ロールバック判定
  4. 反復制御:分析間隔と最大反復回数の管理

5.2 分析パラメータの詳細

spec:
  analysis:
    interval: 1m        # 分析間隔
    threshold: 5         # メトリクス失敗の最大許容回数
    maxWeight: 50        # 最大トラフィック重み(パーセント)
    stepWeight: 10       # ステップごとの重み増分
    iterations: 10       # カナリア反復回数(オプション)
    mirror: false        # ミラーリング(オプション)
    mirrorWeight: 100    # ミラーリングの重み(0-100)
    match:               # マッチ条件(A/Bテスト用)
    - headers:
        x-canary:
          exact: "insider"

5.3 分析プロセスのフローチャート

分析間隔(interval)ごとの処理フロー:

┌─────────────────────┐
│   分析サイクル開始    │
└──────────┬──────────┘
           ▼
┌─────────────────────┐
│  Confirm Webhook     │──失敗──► 次サイクルまで待機
│  (type: confirm)     │
└──────────┬──────────┘
           │ 成功
           ▼
┌─────────────────────┐     ┌──────────────────────┐
│  メトリクス収集       │────►│  Prometheus/Datadog   │
│  (各メトリクスごと)   │◄────│  etc. からデータ取得   │
└──────────┬──────────┘     └──────────────────────┘
           ▼
┌─────────────────────┐
│  閾値評価            │
│  min <= value <= max │
└────┬───────────┬────┘
    OK          NG
     │           │
     ▼           ▼
┌─────────┐  ┌──────────────┐
│ 成功    │  │ 失敗カウント  │
│ カウント │  │ +1            │
│ +1      │  └──────┬───────┘
└────┬────┘         │
     │              ▼
     │         threshold超過?
     │          YES → Rollback
     │          NO  → 次サイクル待機
     ▼
  maxWeight到達 or iterations達成?
   YES → Promote
   NO  → Weight増加 (+stepWeight)

5.4 分析の判定ロジック

成功条件(プロモーション):

  • stepWeight 使用時:トラフィック重みが maxWeight に到達し、全メトリクスがパス
  • iterations 使用時:指定回数の分析サイクルが全てパス
  • stepWeights 使用時:全ステップを完了し、全メトリクスがパス

失敗条件(ロールバック):

  • メトリクス失敗回数が threshold を超過
  • Webhook がエラーを返却(type: confirm, pre-rollout, rollout)
  • カナリア Pod が正常に起動しない(CrashLoopBackOff 等)

5.5 重みステップの計算

stepWeight を使用する場合:

重みシーケンス = [stepWeight, 2*stepWeight, 3*stepWeight, ..., maxWeight]
例:stepWeight=10, maxWeight=50 → [10, 20, 30, 40, 50]

stepWeights を使用する場合:

stepWeights: [1, 2, 5, 10, 20, 30, 50, 80]
# 不均一なトラフィック増加パターン

6. メトリクス分析の詳細

6.1 ビルトインメトリクス

Request Success Rate(リクエスト成功率)

metrics:
- name: request-success-rate
  thresholdRange:
    min: 99
  interval: 1m

Istio の場合のクエリ例:

sum(rate(istio_requests_total{reporter="destination",destination_workload_namespace="test",destination_workload="podinfo-canary",response_code!~"5.*"}[1m]))
/
sum(rate(istio_requests_total{reporter="destination",destination_workload_namespace="test",destination_workload="podinfo-canary"}[1m])) * 100

Request Duration(リクエスト応答時間)

metrics:
- name: request-duration
  thresholdRange:
    max: 500
  interval: 1m

6.2 thresholdRange の詳細

  • min のみ指定:値 >= min であれば合格
  • max のみ指定:値 <= max であれば合格
  • 両方指定:min <= 値 <= max であれば合格

6.3 メトリクスプロバイダー

プロバイダー設定方法特徴
Prometheus-metrics-server フラグデフォルト。ビルトインメトリクスを自動生成
DatadogMetricTemplate CRDAPI キーによる認証
Amazon CloudWatchMetricTemplate CRDIAM ロールによる認証
New RelicMetricTemplate CRDInsights API 経由
GraphiteMetricTemplate CRDRender API 経由
DynatraceMetricTemplate CRDMetrics API v2
InfluxDBMetricTemplate CRDFlux クエリ言語
Google Cloud MonitoringMetricTemplate CRDStackdriver API
KayentaMetricTemplate CRDNetflix の ACA サービス

6.4 MetricTemplate CRD

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

テンプレート変数:{{ namespace }}, {{ target }}, {{ interval }}, {{ variables.key }}

6.5 カスタムメトリクスの Canary への適用

spec:
  analysis:
    metrics:
    - name: request-success-rate
      thresholdRange:
        min: 99
      interval: 1m
    - name: error-rate
      templateRef:
        name: error-rate
        namespace: test
      thresholdRange:
        max: 1
      interval: 1m
    - name: custom-latency
      templateRef:
        name: latency-template
      templateVariables:
        percentile: "99"
        service: "podinfo"
      thresholdRange:
        max: 200
      interval: 2m

7. Canary Result Analysis の内部動作

7.1 分析結果の構造

type CanaryAnalysisResult struct {
    MetricResults []MetricResult
    Passed        bool
    FailureReason string
    Iteration     int
    FailedChecks  int
}

type MetricResult struct {
    Name           string
    Value          float64
    ThresholdRange ThresholdRange
    Passed         bool
    Error          string
}

7.2 メトリクス評価の詳細フロー

  1. クエリ構築:ビルトイン→プロバイダー固有クエリ自動生成、カスタム→テンプレート変数展開
  2. クエリ実行:メトリクスプロバイダーにHTTPリクエスト → スカラー値の抽出
  3. 値の評価:NaN/NoData → 失敗扱い、thresholdRange との比較
  4. 結果集約:全メトリクスパス → 成功、いずれかフェイル → 失敗カウント+1

7.3 分析結果のステータス報告

status:
  phase: Progressing
  failedChecks: 2
  canaryWeight: 30
  iterations: 3
  lastAppliedSpec: "7c4b8d9f"
  lastTransitionTime: "2024-01-15T10:30:00Z"
  conditions:
  - type: Promoted
    status: "False"
    reason: Progressing
    message: "New revision detected, starting canary analysis"
  trackedConfigs:
    configMap/podinfo-config: "abc123"
    secret/podinfo-secret: "def456"

7.4 分析イベントの記録

$ kubectl describe canary podinfo -n test

Events:
  Type     Reason  Age   From     Message
  ----     ------  ----  ----     -------
  Normal   Synced  10m   flagger  New revision detected! Scaling up podinfo.test
  Normal   Synced  9m    flagger  Starting canary analysis for podinfo.test
  Normal   Synced  8m    flagger  Advance podinfo.test canary weight 10
  Warning  Synced  6m    flagger  Halt podinfo.test advancement success rate 98.5% < 99%
  Normal   Synced  3m    flagger  Advance podinfo.test canary weight 50
  Normal   Synced  2m    flagger  Copying podinfo.test template spec to podinfo-primary.test
  Normal   Synced  1m    flagger  Promotion completed! Scaling down podinfo.test

7.5 失敗時の挙動

failedChecks > threshold の場合:

  1. Pre-rollback Webhook 実行
  2. トラフィック重みを Primary: 100%, Canary: 0% に設定
  3. カナリア Deployment のスケールダウン
  4. Rollback Webhook 実行
  5. Alert 発行
  6. ステータスを "Failed" に更新

failedChecks <= threshold の場合:Halt(一時停止)→ 現在の重みを維持 → 次サイクル待機

7.6 分析結果のメトリクス公開

flagger_canary_status{name="podinfo", namespace="test"} 1
flagger_canary_weight{name="podinfo", namespace="test"} 30
flagger_canary_metric_analysis_total{name="podinfo", namespace="test", result="successful"} 15
flagger_canary_metric_analysis_total{name="podinfo", namespace="test", result="failed"} 2
flagger_canary_duration_seconds{name="podinfo", namespace="test"} 60
flagger_canary_total{namespace="test"} 3

8. カスタムメトリクスの設定

8.1 Prometheus カスタムメトリクス

エラー率の監視

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

カスタムレイテンシパーセンタイル

apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
  name: latency-percentile
  namespace: flagger-system
spec:
  provider:
    type: prometheus
    address: http://prometheus.monitoring:9090
  query: |
    histogram_quantile(0.{{ variables.percentile }},
      sum(rate(http_request_duration_seconds_bucket{namespace="{{ namespace }}",pod=~"{{ target }}-canary-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"}[{{ interval }}])) by (le)
    ) * 1000

CPU使用率

apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
  name: cpu-usage
  namespace: flagger-system
spec:
  provider:
    type: prometheus
    address: http://prometheus.monitoring:9090
  query: |
    avg(rate(container_cpu_usage_seconds_total{namespace="{{ namespace }}",pod=~"{{ target }}-canary-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"}[{{ interval }}])) * 100

8.2 Datadog メトリクス

apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
  name: dd-request-duration
  namespace: flagger-system
spec:
  provider:
    type: datadog
    address: https://api.datadoghq.com
    secretRef:
      name: datadog-api
  query: |
    avg:trace.http.request.duration{service:{{ target }}-canary,kube_namespace:{{ namespace }}}.rollup(avg, {{ interval }}).last("5m")

8.3 Amazon CloudWatch メトリクス

apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
  name: cloudwatch-error-rate
  namespace: flagger-system
spec:
  provider:
    type: cloudwatch
    region: ap-northeast-1
  query: |
    [
      {"Id": "errorRate", "Expression": "errors / requests * 100", "Label": "Error Rate"},
      {"Id": "errors", "MetricStat": {"Metric": {"Namespace": "MyApp", "MetricName": "5XXError", "Dimensions": [{"Name": "ServiceName", "Value": "{{ target }}-canary"}]}, "Period": 60, "Stat": "Sum"}, "ReturnData": false},
      {"Id": "requests", "MetricStat": {"Metric": {"Namespace": "MyApp", "MetricName": "RequestCount", "Dimensions": [{"Name": "ServiceName", "Value": "{{ target }}-canary"}]}, "Period": 60, "Stat": "Sum"}, "ReturnData": false}
    ]

8.4 New Relic メトリクス

apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
  name: newrelic-error-rate
  namespace: flagger-system
spec:
  provider:
    type: newrelic
    secretRef:
      name: newrelic-api
  query: |
    SELECT percentage(count(*), WHERE httpResponseCode >= '500')
    FROM Transaction
    WHERE appName = '{{ target }}-canary' AND namespace = '{{ namespace }}'
    SINCE {{ interval }} ago

8.5 複数メトリクスの組み合わせ

spec:
  analysis:
    interval: 1m
    threshold: 5
    maxWeight: 50
    stepWeight: 10
    metrics:
    - name: request-success-rate
      thresholdRange: { min: 99 }
      interval: 1m
    - name: request-duration
      thresholdRange: { max: 500 }
      interval: 1m
    - name: p50-latency
      templateRef: { name: latency-percentile }
      templateVariables: { percentile: "50" }
      thresholdRange: { max: 100 }
      interval: 1m
    - name: p95-latency
      templateRef: { name: latency-percentile }
      templateVariables: { percentile: "95" }
      thresholdRange: { max: 300 }
      interval: 1m
    - name: cpu-usage
      templateRef: { name: cpu-usage }
      thresholdRange: { max: 80 }
      interval: 1m
    - name: connection-errors
      templateRef: { name: connection-error-rate }
      thresholdRange: { max: 5 }
      interval: 1m

9. Webhook と連携機能

9.1 Webhook の種類

種類実行タイミング用途
confirm-rollout各分析サイクルの前デプロイメントの続行承認
pre-rolloutカナリア分析開始前テスト環境の準備
rollout各分析サイクル中負荷テスト実行
confirm-promotionプロモーション前手動承認ゲート
post-rolloutプロモーションまたはロールバック後クリーンアップ、通知
rollbackロールバック時ロールバック処理
event各イベント発生時イベント通知

9.2 負荷テスト Webhook

spec:
  analysis:
    webhooks:
    - name: load-test
      type: rollout
      url: http://flagger-loadtester.test/
      timeout: 30s
      metadata:
        type: cmd
        cmd: "hey -z 2m -q 10 -c 5 http://podinfo-canary.test:9898/"

9.3 Confirm-Rollout Webhook(承認ゲート)

webhooks:
- name: confirm-rollout
  type: confirm-rollout
  url: http://flagger-loadtester.test/gate/check

ゲート操作:

kubectl exec -n test deploy/flagger-loadtester -- curl -s -X POST http://localhost:8080/gate/open   # 開く
kubectl exec -n test deploy/flagger-loadtester -- curl -s -X POST http://localhost:8080/gate/close  # 閉じる

9.4 Pre-Rollout Webhook(スモークテスト)

webhooks:
- name: smoke-test
  type: pre-rollout
  url: http://flagger-loadtester.test/
  timeout: 15s
  metadata:
    type: bash
    cmd: "curl -s http://podinfo-canary.test:9898/api/info | grep version"

9.5 Post-Rollout / Rollback / Event Webhook

webhooks:
- name: notify-slack
  type: post-rollout
  url: http://notification-service.internal/api/notify
- name: on-rollback
  type: rollback
  url: http://incident-service.internal/api/incident
- name: event-tracker
  type: event
  url: http://event-tracker.internal/api/events

10. トラフィック管理の詳細

10.1 Istio(VirtualService)

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: podinfo
  namespace: test
spec:
  hosts: [podinfo]
  http:
  - route:
    - destination: { host: podinfo-primary }
      weight: 70
    - destination: { host: podinfo-canary }
      weight: 30

10.2 Linkerd(TrafficSplit)

apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
  name: podinfo
  namespace: test
spec:
  service: podinfo
  backends:
  - service: podinfo-primary
    weight: 700m
  - service: podinfo-canary
    weight: 300m

10.3 Kubernetes Gateway API(HTTPRoute)

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: podinfo
  namespace: test
spec:
  parentRefs:
  - name: my-gateway
    namespace: gateway-system
  rules:
  - backendRefs:
    - name: podinfo-primary
      port: 9898
      weight: 70
    - name: podinfo-canary
      port: 9898
      weight: 30

10.4 トラフィックミラーリング

spec:
  analysis:
    mirror: true
    mirrorWeight: 100
    iterations: 10

10.5 A/B テスト

spec:
  analysis:
    iterations: 10
    match:
    - headers:
        x-canary:
          exact: "insider"

11. サービスメッシュとの統合

11.1 Istio との統合

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: podinfo
  namespace: test
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: podinfo
  service:
    port: 9898
    gateways:
    - public-gateway.istio-system.svc.cluster.local
    - mesh
    hosts:
    - podinfo.example.com
    trafficPolicy:
      tls:
        mode: ISTIO_MUTUAL
    retries:
      attempts: 3
      perTryTimeout: 1s
      retryOn: "gateway-error,connect-failure,refused-stream"
  analysis:
    interval: 1m
    threshold: 5
    maxWeight: 50
    stepWeight: 10
    metrics:
    - name: request-success-rate
      thresholdRange: { min: 99 }
      interval: 1m
    - name: request-duration
      thresholdRange: { max: 500 }
      interval: 1m

11.2 Linkerd との統合

helm upgrade -i flagger flagger/flagger \
  --namespace linkerd \
  --set meshProvider=linkerd \
  --set metricsServer=http://prometheus.linkerd-viz:9090

11.3 Kubernetes Gateway API との統合

spec:
  service:
    port: 9898
    gatewayRefs:
    - name: my-gateway
      namespace: gateway-system
      group: gateway.networking.k8s.io
      kind: Gateway
      sectionName: http

12. Ingress Controller との統合

12.1 NGINX Ingress Controller

spec:
  provider: nginx
  ingressRef:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    name: podinfo

NGINX ではカナリアアノテーションで分割:nginx.ingress.kubernetes.io/canary-weight: "30"

12.2 Contour / Gloo Edge / Traefik

各プロバイダーは spec.provider フィールドで指定する(contour, gloo, traefik)。


13. アラートと通知

13.1 AlertProvider CRD

apiVersion: flagger.app/v1beta1
kind: AlertProvider
metadata:
  name: slack
  namespace: test
spec:
  type: slack
  channel: "#deployments"
  address: https://hooks.slack.com/services/xxx/yyy/zzz

サポートプロバイダー:Slack, Microsoft Teams, Discord, Rocket.Chat, Google Chat, Prometheus Alertmanager, Generic Webhook

13.2 アラートの重大度

重大度トリガー条件
infoカナリア分析の開始、進行、成功
warnメトリクス分析の一時的な失敗(Halt)
errorロールバック

14. 高度な設定パターン

14.1 ConfigMap/Secret の変更追跡

-enable-config-tracking=true フラグで有効化。Deployment の Pod テンプレートで参照されている ConfigMap/Secret が自動検出される。

14.2 HPA との連携

spec:
  autoscalerRef:
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    name: podinfo

14.3 カスタムリソースのターゲット

DaemonSet、StatefulSet(Flagger 1.33+)もサポート。

14.4 カナリア分析のスキップ・一時停止

kubectl annotate canary podinfo -n test flagger.app/skipAnalysis=true       # スキップ
kubectl annotate canary podinfo -n test flagger.app/forceRollback=true      # 強制ロールバック
kubectl annotate canary podinfo -n test flagger.app/suspend=true            # 一時停止
kubectl annotate canary podinfo -n test flagger.app/suspend=false --overwrite  # 再開

14.5 セッションアフィニティ

spec:
  service:
    trafficPolicy:
      loadBalancer:
        consistentHash:
          httpHeaderName: x-user-id

15. トラブルシューティング

15.1 よくある設定ミス

問題原因解決方法
カナリアが永遠に Progressingthreshold が小さすぎるthreshold を適切な値に増加
メトリクスが常に NaNメトリクスクエリのラベルが不正MetricTemplate のクエリを確認
トラフィックが分割されないService Mesh のサイドカーがないPod に Sidecar Injection を確認
HPA が動作しないautoscalerRef が未設定Canary CRD に autoscalerRef を追加
ConfigMap 変更が検出されないconfig-tracking が無効-enable-config-tracking=true を確認
Webhook がタイムアウトタイムアウト値が短すぎるtimeout の値を増加

15.2 デバッグ用コマンド集

kubectl get canaries --all-namespaces                    # 全カナリア一覧
kubectl get canary podinfo -n test -o jsonpath='{.status}'  # 詳細状態
kubectl describe canary podinfo -n test                   # イベント確認
kubectl logs -n flagger-system deploy/flagger -f         # コントローラーログ

16. 本番環境でのベストプラクティス

16.1 RED メソッドに基づくメトリクス選定

Rate(スループット)、Errors(エラー率)、Duration(レイテンシ)の3種類を必ず設定。

16.2 閾値設計

  • interval: 30s〜2m
  • threshold: 3〜10
  • stepWeight: 5〜20
  • 推奨 stepWeights: [1, 2, 5, 10, 20, 30, 50]

16.3 Namespace 戦略

MetricTemplate を flagger-metrics ネームスペースに共有配置し、各チームの Canary から参照する。

16.4 Flagger の高可用性

リーダー選挙を使用するため replicas=1 で十分。priorityClassName: system-cluster-critical を推奨。


17. ケーススタディ

17.1 EC サイトのマイクロサービスデプロイメント

stepWeights: [1, 2, 5, 10, 20, 30, 50] で慎重なトラフィック増加。request-success-rate >= 99.5%、request-duration <= 200ms。スモークテスト → 負荷テスト → 承認ゲート → プロモーション。所要時間約10分。

17.2 gRPC サービスの段階的リリース

grpcurl による Health Check、ghz による負荷テスト。interval: 2m、threshold: 3。

17.3 失敗シナリオとロールバック

メモリリークによるレイテンシ増加 → Halt 3回 → threshold到達 → 自動ロールバック。


18. まとめ

18.1 主要ポイント

  1. 自動化された品質ゲート:メトリクスに基づく自動判定
  2. 段階的なリスク軽減:トラフィック段階移行で影響範囲を最小化
  3. 柔軟なメトリクス設計:ビルトイン + カスタムメトリクス
  4. マルチプロバイダー対応:Istio, Linkerd, NGINX, Gateway API 等
  5. 拡張性の高い Webhook 機構:スモークテスト、負荷テスト、承認ゲート、通知

18.2 導入時のチェックリスト

  • サービスメッシュまたは Ingress Controller が正しく設定されているか
  • Prometheus(またはその他のメトリクスプロバイダー)が稼働しているか
  • メトリクスクエリが正しいデータを返すか手動で確認したか
  • 閾値が適切に設定されているか
  • 負荷テスト Webhook が設定されているか
  • アラート通知が設定されているか
  • HPA が Canary CRD で参照されているか(使用する場合)
  • ロールバック時の対応手順が文書化されているか
  • Grafana ダッシュボードでカナリア分析を監視できるか

18.3 今後の展望

  • Kubernetes Gateway API のネイティブサポート強化
  • OpenTelemetry との統合
  • AI/ML ベースの分析
  • GitOps との深い統合(Flux CD)

参考資料: