Flagger
Flagger Canary(カナリア結果分析)完全ガイド
目次
- はじめに
- Flagger の概要とアーキテクチャ
- カナリアデプロイメントの基本概念
- Flagger のコアコンポーネント
- カナリア分析(Canary Analysis)の仕組み
- メトリクス分析の詳細
- Canary Result Analysis の内部動作
- カスタムメトリクスの設定
- Webhook と連携機能
- トラフィック管理の詳細
- サービスメッシュとの統合
- Ingress Controller との統合
- アラートと通知
- 高度な設定パターン
- トラブルシューティング
- 本番環境でのベストプラクティス
- ケーススタディ
- まとめ
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 の基本的な動作フローは以下の通りである:
- 変更検出:Flagger コントローラーが Deployment/DaemonSet の変更(コンテナイメージ、環境変数など)を検出する
- カナリアインスタンス作成:新バージョンのカナリアデプロイメントを作成する
- トラフィック段階的移行:設定に基づいてトラフィックを段階的にカナリアに移行する
- メトリクス分析:各ステップでメトリクスを収集・分析し、閾値を評価する
- プロモーション/ロールバック:分析結果に基づいてプロモーション(昇格)またはロールバックを実行する
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 カナリア分析のライフサイクル
カナリアリリースは以下のステータスで遷移する:
| ステータス | 説明 |
|---|---|
Initialized | Flagger がリソースの初期化を完了。カナリア分析待機状態 |
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 のカナリア分析エンジンは、デプロイメントの安全性を自動的に判定する中核機能である。分析エンジンは以下の要素で構成される:
- メトリクスクエリエンジン:メトリクスプロバイダーからデータを取得
- 閾値評価エンジン:取得したメトリクスを閾値と比較
- 判定ロジック:分析結果に基づくプロモーション/ロールバック判定
- 反復制御:分析間隔と最大反復回数の管理
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 フラグ | デフォルト。ビルトインメトリクスを自動生成 |
| Datadog | MetricTemplate CRD | API キーによる認証 |
| Amazon CloudWatch | MetricTemplate CRD | IAM ロールによる認証 |
| New Relic | MetricTemplate CRD | Insights API 経由 |
| Graphite | MetricTemplate CRD | Render API 経由 |
| Dynatrace | MetricTemplate CRD | Metrics API v2 |
| InfluxDB | MetricTemplate CRD | Flux クエリ言語 |
| Google Cloud Monitoring | MetricTemplate CRD | Stackdriver API |
| Kayenta | MetricTemplate CRD | Netflix の 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 メトリクス評価の詳細フロー
- クエリ構築:ビルトイン→プロバイダー固有クエリ自動生成、カスタム→テンプレート変数展開
- クエリ実行:メトリクスプロバイダーにHTTPリクエスト → スカラー値の抽出
- 値の評価:NaN/NoData → 失敗扱い、thresholdRange との比較
- 結果集約:全メトリクスパス → 成功、いずれかフェイル → 失敗カウント+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 の場合:
- Pre-rollback Webhook 実行
- トラフィック重みを Primary: 100%, Canary: 0% に設定
- カナリア Deployment のスケールダウン
- Rollback Webhook 実行
- Alert 発行
- ステータスを "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 よくある設定ミス
| 問題 | 原因 | 解決方法 |
|---|---|---|
| カナリアが永遠に Progressing | threshold が小さすぎる | 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 主要ポイント
- 自動化された品質ゲート:メトリクスに基づく自動判定
- 段階的なリスク軽減:トラフィック段階移行で影響範囲を最小化
- 柔軟なメトリクス設計:ビルトイン + カスタムメトリクス
- マルチプロバイダー対応:Istio, Linkerd, NGINX, Gateway API 等
- 拡張性の高い Webhook 機構:スモークテスト、負荷テスト、承認ゲート、通知
18.2 導入時のチェックリスト
- サービスメッシュまたは Ingress Controller が正しく設定されているか
- Prometheus(またはその他のメトリクスプロバイダー)が稼働しているか
- メトリクスクエリが正しいデータを返すか手動で確認したか
- 閾値が適切に設定されているか
- 負荷テスト Webhook が設定されているか
- アラート通知が設定されているか
- HPA が Canary CRD で参照されているか(使用する場合)
- ロールバック時の対応手順が文書化されているか
- Grafana ダッシュボードでカナリア分析を監視できるか
18.3 今後の展望
- Kubernetes Gateway API のネイティブサポート強化
- OpenTelemetry との統合
- AI/ML ベースの分析
- GitOps との深い統合(Flux CD)
参考資料:
- Flagger 公式ドキュメント: https://docs.flagger.app/
- Flux プロジェクト: https://fluxcd.io/
- Flagger GitHub リポジトリ: https://github.com/fluxcd/flagger
- プログレッシブデリバリー概論: https://www.weave.works/blog/progressive-delivery
- Kubernetes Gateway API: https://gateway-api.sigs.k8s.io/