トラフィック分割
トラフィック分割は、コードを変更せずに Canary deployment、A/B testing、Blue/Green deployment を実現できる、Istio の最も強力な機能の 1 つです。
目次
- トラフィック分割の概要
- Canary deployment
- Blue/Green deployment
- A/B testing
- Progressive rollout
- トラフィックミラーリングとの併用
- 実践例
- 監視とロールバック
- トラブルシューティング
トラフィック分割の概要
トラフィック分割では、VirtualService の weight フィールドを使用して、複数の Service バージョン間にトラフィックを比率で分散します。
基本構成
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 90 # 90% of traffic
- destination:
host: reviews
subset: v2
weight: 10 # 10% of trafficCanary deployment
Canary deployment は、まず少数のユーザーにのみ新しいバージョンをデプロイして安全に検証する戦略です。Istio とともに Argo Rollouts を使用すると、自動化された段階的デプロイとメトリクスに基づく自動ロールバックを実現できます。
Argo Rollouts + Istio アーキテクチャ
Canary deployment フロー
ステップ 1: Argo Rollouts のインストール
# Install Argo Rollouts
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
# Install Argo Rollouts CLI (optional)
curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
chmod +x kubectl-argo-rollouts-linux-amd64
sudo mv kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts
# Run Argo Rollouts Dashboard
kubectl argo rollouts dashboardステップ 2: Rollout Resource の定義
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: reviews
namespace: default
spec:
replicas: 5
revisionHistoryLimit: 2
selector:
matchLabels:
app: reviews
template:
metadata:
labels:
app: reviews
istio-injection: enabled
spec:
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v2:1.17.0
ports:
- containerPort: 9080
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
# Canary Deployment Strategy
strategy:
canary:
# Traffic Control via Istio VirtualService
trafficRouting:
istio:
virtualService:
name: reviews-vsvc
routes:
- primary
destinationRule:
name: reviews-destrule
canarySubsetName: canary
stableSubsetName: stable
# Canary Steps Definition
steps:
- setWeight: 10 # 10% traffic to Canary
- pause:
duration: 2m # Wait 2 minutes
- setWeight: 25 # 25% traffic to Canary
- pause:
duration: 2m
- setWeight: 50 # 50% traffic to Canary
- pause:
duration: 2m
- setWeight: 75 # 75% traffic to Canary
- pause:
duration: 2m
# Automatic Metric Analysis
analysis:
templates:
- templateName: success-rate
- templateName: latency
startingStep: 1 # Start analysis from first step
args:
- name: service-name
value: reviewsステップ 3: Service の作成
まず、Kubernetes Service を作成します。
apiVersion: v1
kind: Service
metadata:
name: reviews
namespace: default
spec:
ports:
- port: 9080
name: http
selector:
app: reviews # Select all Pods from Rolloutステップ 4: VirtualService の定義
重要: Argo Rollouts は VirtualService を自動的に変更しません。VirtualService はあらかじめ作成しておく必要があり、Rollout は重みだけを更新するためにそれを参照します。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews-vsvc
namespace: default
spec:
hosts:
- reviews
http:
- name: primary # Route name referenced by Rollout (required)
route:
- destination:
host: reviews
subset: stable # Stable version
weight: 100
- destination:
host: reviews
subset: canary # Canary version
weight: 0要点:
http[].nameフィールドは必須です(Rollout のroutesフィールドと一致します)- Rollout が自動更新するのは、この VirtualService の
weight値だけです - stable と canary の 2 つの destination が必要です
ステップ 5: DestinationRule の定義
重要: Argo Rollouts は DestinationRule を自動的に作成しません。あらかじめ作成しておく必要があります。
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: reviews-destrule
namespace: default
spec:
host: reviews
subsets:
- name: stable
labels:
# Label automatically added by Rollout
# rollouts-pod-template-hash: <stable-hash>
- name: canary
labels:
# Label automatically added by Rollout
# rollouts-pod-template-hash: <canary-hash>要点:
- Subset 名(
stable、canary)は、Rollout のstableSubsetNameおよびcanarySubsetNameと一致する必要があります - Rollout は
rollouts-pod-template-hashラベルを Pod に自動追加します - DestinationRule の subset はこのラベルに基づいて Pod を選択します
- ラベルセレクターは空のままにします。Rollout が実行時に管理します
ステップ 6: AnalysisTemplate の定義
成功率分析
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
namespace: default
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 30s
count: 4 # 4 measurements (total 2 minutes)
successCondition: result >= 0.95 # 95% or higher success rate
failureLimit: 2 # Rollback after 2 failures
provider:
prometheus:
address: http://prometheus.istio-system:9090
query: |
sum(rate(
istio_requests_total{
destination_service_name="{{args.service-name}}",
destination_workload_namespace="default",
response_code!~"5.*"
}[2m]
))
/
sum(rate(
istio_requests_total{
destination_service_name="{{args.service-name}}",
destination_workload_namespace="default"
}[2m]
))レイテンシー分析
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: latency
namespace: default
spec:
args:
- name: service-name
metrics:
- name: latency-p95
interval: 30s
count: 4
successCondition: result <= 500 # P95 latency 500ms or less
failureLimit: 2
provider:
prometheus:
address: http://prometheus.istio-system:9090
query: |
histogram_quantile(0.95,
sum(rate(
istio_request_duration_milliseconds_bucket{
destination_service_name="{{args.service-name}}",
destination_workload_namespace="default"
}[2m]
)) by (le)
)デプロイの実行と監視
新バージョンのデプロイ
# Start Canary deployment with image update
kubectl argo rollouts set image reviews \
reviews=docker.io/istio/examples-bookinfo-reviews-v3:1.17.0
# Check Rollout status
kubectl argo rollouts get rollout reviews --watch
# Real-time dashboard
kubectl argo rollouts dashboard手動での承認/却下
# Manual approval to proceed to next step
kubectl argo rollouts promote reviews
# Abort and rollback Canary deployment
kubectl argo rollouts abort reviews
# Rollback to specific revision
kubectl argo rollouts undo reviewsデプロイ進行状況の監視
# Check Rollout status
kubectl argo rollouts status reviews
# Check analysis results
kubectl get analysisrun -w
# Check Canary vs Stable traffic distribution
kubectl get virtualservice reviews-vsvc -o yaml
# Check actual Pod status
kubectl get pods -l app=reviews --show-labels高度な設定: メトリクスベースの自動進行
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: reviews-auto
spec:
replicas: 5
strategy:
canary:
trafficRouting:
istio:
virtualService:
name: reviews-vsvc
routes:
- primary
destinationRule:
name: reviews-destrule
canarySubsetName: canary
stableSubsetName: stable
steps:
- setWeight: 10
- pause:
duration: 1m
# Automatic Analysis - Automatically proceed to next step on success
- analysis:
templates:
- templateName: success-rate
- templateName: latency
args:
- name: service-name
value: reviews
- setWeight: 25
- pause:
duration: 1m
- analysis:
templates:
- templateName: success-rate
- templateName: latency
args:
- name: service-name
value: reviews
- setWeight: 50
- pause:
duration: 1m
- analysis:
templates:
- templateName: success-rate
- templateName: latency
args:
- name: service-name
value: reviews
- setWeight: 75
- pause:
duration: 1m
- analysis:
templates:
- templateName: success-rate
- templateName: latency
args:
- name: service-name
value: reviews重要な考慮事項
1. VirtualService と DestinationRule は事前に作成する必要があります
Argo Rollouts はこれらのリソースを作成しません。Rollout をデプロイする前に作成する必要があります。
# Order is important
kubectl apply -f service.yaml
kubectl apply -f destination-rule.yaml
kubectl apply -f virtual-service.yaml
kubectl apply -f rollout.yaml2. Rollout により管理されるラベル
Argo Rollouts は次のラベルを自動的に追加・管理します。
# Labels automatically added by Rollout
rollouts-pod-template-hash: <hash> # For ReplicaSet identificationこれらのラベルは、DestinationRule における subset の選択に使用されます。
3. HTTP Route 名が必要です
VirtualService の各 HTTP route には name フィールドが必要です。
# Wrong example
http:
- route: # No name!
- destination:
host: reviews
# Correct example
http:
- name: primary # Required!
route:
- destination:
host: reviews4. Istio Injection を有効にする
Istio sidecar を Rollout Pod に inject する必要があります。
# Method 1: Namespace level
kubectl label namespace default istio-injection=enabled
# Method 2: Pod level
template:
metadata:
labels:
sidecar.istio.io/inject: "true"VirtualService Match との併用
Argo Rollouts は VirtualService の match 条件とともに使用できます。これにより、特定の条件を満たすトラフィックのみを Canary にルーティングできます。
例 1: Header ベースの Canary(社内テスター向け)
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews-vsvc
spec:
hosts:
- reviews
http:
# Priority 1: Internal testers always go to Canary
- match:
- headers:
x-canary-tester:
exact: "true"
route:
- destination:
host: reviews
subset: canary
# Priority 2: Normal traffic - Rollout manages this route's weight
- name: primary
route:
- destination:
host: reviews
subset: stable
weight: 100
- destination:
host: reviews
subset: canary
weight: 0ユースケース:
# Internal testers always access Canary version
curl -H "x-canary-tester: true" http://reviews:9080/
# Regular users are routed based on Rollout's weight
curl http://reviews:9080/例 2: リージョンベースの段階的デプロイ
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews-vsvc
spec:
hosts:
- reviews
http:
# Priority 1: Dev environment always gets latest version
- match:
- headers:
x-env:
exact: "dev"
route:
- destination:
host: reviews
subset: canary
# Priority 2: Only specific region for Canary test (e.g., Seoul)
- match:
- headers:
x-region:
exact: "ap-northeast-2"
name: seoul-traffic
route:
- destination:
host: reviews
subset: stable
weight: 100
- destination:
host: reviews
subset: canary
weight: 0
# Priority 3: Other regions stay on stable version
- name: other-regions
route:
- destination:
host: reviews
subset: stableRollout 設定:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: reviews
spec:
# ... (same as before)
strategy:
canary:
trafficRouting:
istio:
virtualService:
name: reviews-vsvc
routes:
- seoul-traffic # Only apply Canary to Seoul traffic
destinationRule:
name: reviews-destrule
canarySubsetName: canary
stableSubsetName: stable
steps:
- setWeight: 10
- pause: {duration: 2m}
- setWeight: 50
- pause: {duration: 2m}例 3: ユーザーティアベースのデプロイ
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews-vsvc
spec:
hosts:
- reviews
http:
# Priority 1: Beta program participants
- match:
- headers:
x-user-tier:
exact: "beta"
route:
- destination:
host: reviews
subset: canary
# Priority 2: Only premium users for Canary test
- match:
- headers:
x-user-tier:
exact: "premium"
name: premium-users
route:
- destination:
host: reviews
subset: stable
weight: 100
- destination:
host: reviews
subset: canary
weight: 0
# Priority 3: Free users get stable version
- name: free-users
route:
- destination:
host: reviews
subset: stable例 4: モバイルアプリのバージョンベースのデプロイ
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews-vsvc
spec:
hosts:
- reviews
http:
# Priority 1: Only latest app version users get Canary
- match:
- headers:
x-app-version:
regex: "^3\\.(1[0-9]|[2-9][0-9])\\." # 3.10.x or higher
name: latest-app-version
route:
- destination:
host: reviews
subset: stable
weight: 100
- destination:
host: reviews
subset: canary
weight: 0
# Priority 2: Legacy app only gets stable version
- name: legacy-app-version
route:
- destination:
host: reviews
subset: stable完全なデプロイ例
すべてのリソースを一度にデプロイする基本例:
---
# Service
apiVersion: v1
kind: Service
metadata:
name: reviews
spec:
ports:
- port: 9080
name: http
selector:
app: reviews
---
# DestinationRule
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: reviews-destrule
spec:
host: reviews
subsets:
- name: stable
labels: {} # Managed by Rollout
- name: canary
labels: {} # Managed by Rollout
---
# VirtualService
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews-vsvc
spec:
hosts:
- reviews
http:
- name: primary
route:
- destination:
host: reviews
subset: stable
weight: 100
- destination:
host: reviews
subset: canary
weight: 0
---
# Rollout
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: reviews
spec:
replicas: 3
selector:
matchLabels:
app: reviews
template:
metadata:
labels:
app: reviews
spec:
containers:
- name: reviews
image: istio/examples-bookinfo-reviews-v1:1.17.0
ports:
- containerPort: 9080
strategy:
canary:
trafficRouting:
istio:
virtualService:
name: reviews-vsvc
routes:
- primary
destinationRule:
name: reviews-destrule
canarySubsetName: canary
stableSubsetName: stable
steps:
- setWeight: 20
- pause: {duration: 1m}
- setWeight: 40
- pause: {duration: 1m}
- setWeight: 60
- pause: {duration: 1m}
- setWeight: 80
- pause: {duration: 1m}Match と併用する場合の考慮事項
1. Route の順序が重要です
VirtualService の HTTP route は順番に評価されます。match を持つ route は、Rollout が管理する route より前に配置する必要があります。
# Correct example
http:
- match:
- headers:
x-tester: {exact: "true"}
route:
- destination: {host: reviews, subset: canary}
- name: primary # Managed by Rollout
route:
- destination: {host: reviews, subset: stable}
weight: 100
- destination: {host: reviews, subset: canary}
weight: 0
# Wrong example - match is ignored if primary comes first
http:
- name: primary
route: [...]
- match: [...] # Never reached!
route: [...]2. Rollout は指定した Route のみを管理します
Rollout は、routes フィールドで指定された route の重みだけを変更します。
strategy:
canary:
trafficRouting:
istio:
virtualService:
name: reviews-vsvc
routes:
- primary # Only modifies this route's weight
# Other routes with match are not modified3. 複数 Route の同時管理
必要に応じて、複数の route を同時に管理できます。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews-vsvc
spec:
hosts:
- reviews
http:
# Premium users route
- match:
- headers:
x-user-tier: {exact: "premium"}
name: premium-route
route:
- destination: {host: reviews, subset: stable}
weight: 100
- destination: {host: reviews, subset: canary}
weight: 0
# Standard users route
- name: standard-route
route:
- destination: {host: reviews, subset: stable}
weight: 100
- destination: {host: reviews, subset: canary}
weight: 0
---
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: reviews
spec:
strategy:
canary:
trafficRouting:
istio:
virtualService:
name: reviews-vsvc
routes:
- premium-route # Manage both routes
- standard-route
destinationRule:
name: reviews-destrule
canarySubsetName: canary
stableSubsetName: stable
steps:
- setWeight: 10
- pause: {duration: 2m}トラブルシューティング
Rollout が Progressing 状態で停止する
# Check Rollout status
kubectl argo rollouts get rollout reviews
# Check Events
kubectl describe rollout reviews
# Common causes:
# 1. VirtualService/DestinationRule doesn't exist
kubectl get virtualservice reviews-vsvc
kubectl get destinationrule reviews-destrule
# 2. HTTP route name is wrong
kubectl get virtualservice reviews-vsvc -o yaml | grep "name:"
# 3. Istio sidecar not injected
kubectl get pods -l app=reviews -o jsonpath='{.items[*].spec.containers[*].name}'トラフィックが Canary に送信されない
# Check VirtualService weight
kubectl get virtualservice reviews-vsvc -o yaml
# Check DestinationRule subsets
kubectl get destinationrule reviews-destrule -o yaml
# Check Pod labels
kubectl get pods -l app=reviews --show-labels
# Check Envoy configuration
istioctl proxy-config routes <pod-name>Rollout のロールバック
# Rollback to previous revision
kubectl argo rollouts undo reviews
# Rollback to specific revision
kubectl argo rollouts undo reviews --to-revision=2
# Abort and rollback immediately
kubectl argo rollouts abort reviewsArgo Rollouts による Blue/Green deployment
Argo Rollouts は Blue/Green strategy もサポートしています。
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: reviews-bluegreen
spec:
replicas: 5
selector:
matchLabels:
app: reviews
template:
metadata:
labels:
app: reviews
spec:
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v2:1.17.0
ports:
- containerPort: 9080
strategy:
blueGreen:
activeService: reviews-active
previewService: reviews-preview
autoPromotionEnabled: false # Manual approval
scaleDownDelaySeconds: 30
prePromotionAnalysis:
templates:
- templateName: smoke-tests
args:
- name: service-name
value: reviews-previewBlue/Green deployment
Blue/Green deployment では、同一の本番環境を 2 つ維持し、トラフィックを即時に切り替えます。Istio とともに Argo Rollouts を使用すると、安全な切り替えと自動ロールバックを実現できます。
Argo Rollouts Blue/Green アーキテクチャ
Blue/Green deployment フロー
ステップ 1: Service の定義
Blue/Green deployment には 2 つの Service が必要です。
---
# Active Service - Production traffic
apiVersion: v1
kind: Service
metadata:
name: reviews-active
spec:
ports:
- port: 9080
name: http
selector:
app: reviews
# Rollout automatically updates selector
---
# Preview Service - Test traffic
apiVersion: v1
kind: Service
metadata:
name: reviews-preview
spec:
ports:
- port: 9080
name: http
selector:
app: reviews
# Rollout automatically updates selectorステップ 2: Istio Gateway と VirtualService
---
# Gateway
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: reviews-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- reviews.example.com
---
# VirtualService - Active Service
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews-vsvc
spec:
hosts:
- reviews.example.com
gateways:
- reviews-gateway
http:
- route:
- destination:
host: reviews-active # Route to Active Service
port:
number: 9080
---
# VirtualService - Preview Service (for testing)
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews-preview-vsvc
spec:
hosts:
- reviews-preview.example.com
gateways:
- reviews-gateway
http:
- route:
- destination:
host: reviews-preview # Route to Preview Service
port:
number: 9080ステップ 3: Rollout Resource の定義
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: reviews
spec:
replicas: 3
revisionHistoryLimit: 2
selector:
matchLabels:
app: reviews
template:
metadata:
labels:
app: reviews
spec:
containers:
- name: reviews
image: istio/examples-bookinfo-reviews-v1:1.17.0
ports:
- containerPort: 9080
strategy:
blueGreen:
# Specify Active/Preview Services
activeService: reviews-active
previewService: reviews-preview
# Auto-promotion settings
autoPromotionEnabled: false # false: manual approval, true: auto-approve
autoPromotionSeconds: 30 # Wait time for auto-promotion
# Blue environment retention time
scaleDownDelaySeconds: 30 # Delete Blue 30 seconds after switch
scaleDownDelayRevisionLimit: 2 # Keep up to 2 previous versions
# Pre-test (validate Preview before deployment)
prePromotionAnalysis:
templates:
- templateName: smoke-tests
args:
- name: service-name
value: reviews-preview
# Post-verification (validate Active after switch)
postPromotionAnalysis:
templates:
- templateName: post-promotion-tests
args:
- name: service-name
value: reviews-active
# Anti-affinity (deploy Blue/Green on different nodes)
antiAffinity:
requiredDuringSchedulingIgnoredDuringExecution: {}ステップ 4: AnalysisTemplate の定義
事前テスト(Smoke Tests)
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: smoke-tests
spec:
args:
- name: service-name
metrics:
# 1. HTTP status code check
- name: http-status
interval: 10s
count: 5
successCondition: result == 200
provider:
job:
spec:
template:
spec:
containers:
- name: curl
image: curlimages/curl:7.88.1
command:
- sh
- -c
- |
curl -s -o /dev/null -w "%{http_code}" http://{{args.service-name}}:9080/health
restartPolicy: Never
backoffLimit: 1
# 2. Basic functional test
- name: functional-test
interval: 10s
count: 3
successCondition: result == true
provider:
job:
spec:
template:
spec:
containers:
- name: test
image: appropriate/curl:latest
command:
- sh
- -c
- |
# API endpoint test
curl -f http://{{args.service-name}}:9080/api/v1/health
restartPolicy: Never
backoffLimit: 1事後検証テスト
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: post-promotion-tests
spec:
args:
- name: service-name
metrics:
# Prometheus metric-based verification
- name: error-rate
interval: 30s
count: 10
successCondition: result < 0.05 # Less than 5% error rate
provider:
prometheus:
address: http://prometheus.istio-system:9090
query: |
sum(rate(
istio_requests_total{
destination_service_name="{{args.service-name}}",
response_code=~"5.."
}[1m]
))
/
sum(rate(
istio_requests_total{
destination_service_name="{{args.service-name}}"
}[1m]
))
- name: response-time
interval: 30s
count: 10
successCondition: result < 500 # Less than 500ms
provider:
prometheus:
address: http://prometheus.istio-system:9090
query: |
histogram_quantile(0.95,
sum(rate(
istio_request_duration_milliseconds_bucket{
destination_service_name="{{args.service-name}}"
}[1m]
)) by (le)
)デプロイの実行と管理
新バージョンのデプロイ
# Start Blue/Green deployment with image update
kubectl argo rollouts set image reviews \
reviews=istio/examples-bookinfo-reviews-v2:1.17.0
# Check Rollout status
kubectl argo rollouts get rollout reviews --watch
# Test Preview environment
curl http://reviews-preview.example.com/手動承認(Promotion)
# Manually approve after pre-tests succeed
kubectl argo rollouts promote reviews
# Or approve from dashboard
kubectl argo rollouts dashboardステータスの確認
# Rollout status
kubectl argo rollouts status reviews
# Check Active/Preview Services
kubectl get svc reviews-active reviews-preview
# Check Pod status
kubectl get pods -l app=reviews --show-labels
# Check Analysis results
kubectl get analysisrunロールバック
# Immediate rollback (switch to Blue)
kubectl argo rollouts abort reviews
# Rollback to previous version
kubectl argo rollouts undo reviews
# Rollback to specific revision
kubectl argo rollouts undo reviews --to-revision=3A/B testing
A/B testing では、2 つのバージョンを同時に実行し、特定の基準に基づいてユーザーを分類して効果を測定します。
Cookie ベースの A/B testing
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: myapp-ab-test
spec:
hosts:
- myapp.example.com
http:
# Group A (cookie value "a")
- match:
- headers:
cookie:
regex: ".*ab_test=a.*"
route:
- destination:
host: myapp
subset: version-a
# Group B (cookie value "b")
- match:
- headers:
cookie:
regex: ".*ab_test=b.*"
route:
- destination:
host: myapp
subset: version-b
# New users (no cookie) - 50/50 split
- route:
- destination:
host: myapp
subset: version-a
weight: 50
- destination:
host: myapp
subset: version-b
weight: 50
headers:
response:
add:
Set-Cookie: "ab_test=a; Max-Age=2592000; Path=/"Header ベースの A/B testing
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: myapp-ab-header
spec:
hosts:
- myapp
http:
# Mobile users -> Version B (new mobile UI)
- match:
- headers:
user-agent:
regex: ".*Mobile.*"
route:
- destination:
host: myapp
subset: version-b
# Premium users -> Version B (new features)
- match:
- headers:
x-user-tier:
exact: "premium"
route:
- destination:
host: myapp
subset: version-b
# Regular users -> Version A
- route:
- destination:
host: myapp
subset: version-aGeo ベースの A/B testing
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: myapp-ab-geo
spec:
hosts:
- myapp
http:
# Test new version only in specific regions
- match:
- headers:
x-country-code:
regex: "US|CA" # USA, Canada
route:
- destination:
host: myapp
subset: version-b
weight: 50
- destination:
host: myapp
subset: version-a
weight: 50
# Other regions get existing version
- route:
- destination:
host: myapp
subset: version-aProgressive rollout
Progressive rollout は、時間の経過とともにトラフィック比率を自動的に増加させます。Argo Rollouts の Canary strategy を使用すると、自動化された段階的デプロイを実現できます。
手動 Progressive rollout
#!/bin/bash
# progressive-rollout.sh
SERVICE="myapp"
NAMESPACE="default"
INTERVAL=300 # 5 minutes
# Traffic ratio array
WEIGHTS=(0 10 25 50 75 100)
for i in "${!WEIGHTS[@]}"; do
weight=${WEIGHTS[$i]}
prev_weight=$((100 - weight))
echo "[$i/${#WEIGHTS[@]}] Shifting traffic: v1=$prev_weight%, v2=$weight%"
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: ${SERVICE}
namespace: ${NAMESPACE}
spec:
hosts:
- ${SERVICE}
http:
- route:
- destination:
host: ${SERVICE}
subset: v1
weight: ${prev_weight}
- destination:
host: ${SERVICE}
subset: v2
weight: ${weight}
EOF
if [ $weight -lt 100 ]; then
echo "Waiting ${INTERVAL} seconds before next step..."
sleep $INTERVAL
# Check metrics
echo "Checking metrics..."
ERROR_RATE=$(kubectl exec -n ${NAMESPACE} -c istio-proxy \
$(kubectl get pod -n ${NAMESPACE} -l app=${SERVICE},version=v2 -o jsonpath='{.items[0].metadata.name}') -- \
curl -s localhost:15000/stats/prometheus | \
grep 'istio_requests_total{response_code="500"}' | \
awk '{print $2}')
if [ "$ERROR_RATE" != "" ] && [ "$ERROR_RATE" -gt 5 ]; then
echo "ERROR: High error rate detected ($ERROR_RATE errors). Rolling back!"
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: ${SERVICE}
namespace: ${NAMESPACE}
spec:
hosts:
- ${SERVICE}
http:
- route:
- destination:
host: ${SERVICE}
subset: v1
weight: 100
EOF
exit 1
fi
fi
done
echo "Progressive rollout completed successfully!"トラフィックミラーリングとの併用
トラフィック分割とミラーリングを組み合わせることで、より安全なデプロイを実現できます。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: myapp-canary-with-mirror
spec:
hosts:
- myapp
http:
- route:
# Main traffic: 90% v1, 10% v2
- destination:
host: myapp
subset: v1
weight: 90
- destination:
host: myapp
subset: v2
weight: 10
# Mirroring: duplicate all traffic to v3 (ignore response)
mirror:
host: myapp
subset: v3
mirrorPercentage:
value: 100実践例
例 1: ユーザーセグメントベースのデプロイ
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: myapp-segmented-rollout
spec:
hosts:
- myapp.example.com
http:
# Internal employees - use new version first
- match:
- headers:
x-employee:
exact: "true"
route:
- destination:
host: myapp
subset: v2
# Beta testers - next to use new version
- match:
- headers:
x-beta-tester:
exact: "true"
route:
- destination:
host: myapp
subset: v2
# VIP customers - Canary 50%
- match:
- headers:
x-user-tier:
exact: "vip"
route:
- destination:
host: myapp
subset: v1
weight: 50
- destination:
host: myapp
subset: v2
weight: 50
# Regular customers - Canary 10%
- route:
- destination:
host: myapp
subset: v1
weight: 90
- destination:
host: myapp
subset: v2
weight: 10例 2: 時間ベースのデプロイ
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: myapp-time-based
spec:
hosts:
- myapp
http:
# Korea daytime (KST 09:00-18:00) - stable version
- match:
- headers:
x-country-code:
exact: "KR"
x-hour:
regex: "0[9]|1[0-7]" # 09-17 hours
route:
- destination:
host: myapp
subset: v1
# Korea nighttime - Canary test
- match:
- headers:
x-country-code:
exact: "KR"
route:
- destination:
host: myapp
subset: v1
weight: 80
- destination:
host: myapp
subset: v2
weight: 20
# Other regions
- route:
- destination:
host: myapp
subset: v1例 3: Microservice Chain Canary
# Frontend Canary
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: frontend-canary
spec:
hosts:
- frontend
http:
- route:
- destination:
host: frontend
subset: v1
weight: 90
- destination:
host: frontend
subset: v2
weight: 10
---
# Backend Canary (only used by Frontend v2)
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-canary
spec:
hosts:
- backend
http:
# Only requests from Frontend v2 go to Backend v2
- match:
- sourceLabels:
app: frontend
version: v2
route:
- destination:
host: backend
subset: v2
# Rest go to Backend v1
- route:
- destination:
host: backend
subset: v1監視とロールバック
Prometheus クエリ
# Requests per version
sum(rate(istio_requests_total{destination_service="myapp.default.svc.cluster.local"}[5m])) by (destination_version)
# Error rate per version
sum(rate(istio_requests_total{destination_service="myapp.default.svc.cluster.local",response_code=~"5.."}[5m])) by (destination_version)
/
sum(rate(istio_requests_total{destination_service="myapp.default.svc.cluster.local"}[5m])) by (destination_version)
# Latency per version (P95)
histogram_quantile(0.95, sum(rate(istio_request_duration_milliseconds_bucket{destination_service="myapp.default.svc.cluster.local"}[5m])) by (destination_version, le))
# Traffic split ratio
sum(rate(istio_requests_total{destination_service="myapp.default.svc.cluster.local"}[5m])) by (destination_version)
/
sum(rate(istio_requests_total{destination_service="myapp.default.svc.cluster.local"}[5m]))自動ロールバックスクリプト
#!/bin/bash
# auto-rollback.sh
SERVICE="myapp"
NAMESPACE="default"
ERROR_THRESHOLD=5 # 5% error rate threshold
LATENCY_THRESHOLD=1000 # 1 second latency threshold
# Collect Canary version metrics
POD=$(kubectl get pod -n ${NAMESPACE} -l app=${SERVICE},version=v2 -o jsonpath='{.items[0].metadata.name}')
# Check error rate
ERROR_RATE=$(kubectl exec -n ${NAMESPACE} -c istio-proxy ${POD} -- \
curl -s localhost:15000/stats/prometheus | \
grep 'istio_requests_total{response_code="500"}' | \
awk '{sum+=$2} END {print sum}')
TOTAL_REQUESTS=$(kubectl exec -n ${NAMESPACE} -c istio-proxy ${POD} -- \
curl -s localhost:15000/stats/prometheus | \
grep 'istio_requests_total' | \
grep -v 'response_code' | \
awk '{sum+=$2} END {print sum}')
if [ "$TOTAL_REQUESTS" -gt 0 ]; then
ERROR_PERCENTAGE=$(echo "scale=2; ($ERROR_RATE / $TOTAL_REQUESTS) * 100" | bc)
if (( $(echo "$ERROR_PERCENTAGE > $ERROR_THRESHOLD" | bc -l) )); then
echo "ERROR: Error rate ${ERROR_PERCENTAGE}% exceeds threshold ${ERROR_THRESHOLD}%"
echo "Rolling back to v1..."
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: ${SERVICE}
namespace: ${NAMESPACE}
spec:
hosts:
- ${SERVICE}
http:
- route:
- destination:
host: ${SERVICE}
subset: v1
weight: 100
EOF
# Send notification
curl -X POST https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK \
-H 'Content-Type: application/json' \
-d "{\"text\":\"Warning: ${SERVICE} Canary rollback triggered! Error rate: ${ERROR_PERCENTAGE}%\"}"
exit 1
fi
fi
echo "Canary metrics within acceptable range"トラブルシューティング
トラフィック分割が機能しない
# 1. Check DestinationRule
kubectl get destinationrule -A
kubectl describe destinationrule <name> -n <namespace>
# 2. Check subset labels
kubectl get pods -n <namespace> --show-labels
# 3. Check VirtualService configuration
istioctl proxy-config routes <pod-name> -n <namespace> -o json
# 4. Check actual traffic distribution
kubectl exec -n <namespace> <pod-name> -c istio-proxy -- \
curl -s localhost:15000/clusters | grep <service-name>Weight が想定どおりに動作しない
# Check Envoy cluster weights
istioctl proxy-config clusters <pod-name> -n <namespace> --fqdn <service-fqdn> -o json
# Check endpoint status
kubectl get endpoints -n <namespace> <service-name> -o yaml
# Check Pod ready status
kubectl get pods -n <namespace> -l version=v2ベストプラクティス
1. 段階的ロールアウト
# Good example: Gradual increase
# 5% -> 10% -> 25% -> 50% -> 100%
# Bad example: Sudden increase
# 5% -> 100%2. ロールバック計画を準備する
# Prepare rollback YAML file in advance
cat > rollback-v1.yaml <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- route:
- destination:
host: myapp
subset: v1
weight: 100
EOF
# Rollback command
kubectl apply -f rollback-v1.yaml3. 監視は不可欠です
- Golden Signals の監視: Latency、Traffic、Errors、Saturation
- SLO ベースの判断: 目標 SLO を満たさない場合は自動ロールバック
- リアルタイムアラート: Slack、PagerDuty などを使用して通知を設定します
4. テストの自動化
Argo Rollouts の AnalysisTemplate を使用して、自動テストと検証を実装します。
# AnalysisTemplate for automated testing and verification
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 1m
count: 10
successCondition: result >= 0.95
failureLimit: 3
provider:
prometheus:
address: http://prometheus.istio-system:9090
query: |
sum(rate(
istio_requests_total{
destination_service_name="{{args.service-name}}",
response_code!~"5.*"
}[1m]
))
/
sum(rate(
istio_requests_total{
destination_service_name="{{args.service-name}}"
}[1m]
))
---
# Using AnalysisTemplate in Rollout
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: myapp
spec:
strategy:
canary:
steps:
- setWeight: 10
- pause: {duration: 1m}
- analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: myapp5. ドキュメント化
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: myapp-canary
annotations:
description: "Canary deployment for myapp v2"
owner: "platform-team"
rollout-date: "2025-11-24"
rollout-plan: "5% -> 10% -> 25% -> 50% -> 100%"
monitoring-dashboard: "https://grafana.example.com/d/canary"
spec:
# ...