Contents
Istio の基本概念とアーキテクチャ
Istio は Kubernetes 上で動作するサービスメッシュで、マイクロサービス間の通信を 統一的に制御 しながら可観測性やセキュリティ機能を提供します。データプレーンは Envoy が担い、制御プレーンは istiod(旧 Pilot)が設定配信・サービスディスカバリを行います。本節では各コンポーネントの役割と、Mixer が Telemetry と Policy に分離された現状について整理します。
Envoy – サイドカー型データプレーン
Envoy は各 Pod にサイドカーとして注入され、インバウンド・アウトバウンドすべてのトラフィックをプロキシします。TLS 終端、リクエスト/レスポンスの観測、ヘッダー操作、フェイルオーバーなど、データプレーンに必要な機能はすべて Envoy が実装しています。
istiod(旧 Pilot) – 制御プレーンの中核
istiod は CRD(VirtualService・DestinationRule など)を解析し、XDS API を通じて Envoy にリアルタイムで設定情報を配信します。加えて、Telemetry API と AuthorizationPolicy の評価ロジックも統合され、ポリシーやメトリクスの処理は istiod が担当します。
Telemetry(旧 Mixer) – 分散されたテレメトリ機構
Mixer は 1.5 系まで単体コンポーネントとして提供されましたが、現在は Telemetry 機能が Envoy と istiod に分散 しています。Envoy がローカルでアクセスログやサイドカー統計情報を収集し、istiod が集約・転送先(Prometheus や Stackdriver 等)へプッシュします。そのため、Mixer を別途デプロイする必要はなくなりました。
Istio の現行アーキテクチャは「Envoy + istiod」のみで完結し、旧 Mixer に相当する機能はすでに内部に統合されています。
VirtualService と DestinationRule の概要と構成要素
VirtualService と DestinationRule は Istio が提供する トラフィック制御の宣言的設定 です。本節では両リソースの主要フィールドを解説し、実際に使用する際のベストプラクティスを示します。
VirtualService の主要フィールドとルーティングロジック
VirtualService は「トラフィックはどこへ送るか」を定義します。以下に典型的な構成要素をまとめました。
- hosts – 対象となる Service 名(FQDN でも可)。
- http / tcp – プロトコル別に配列で記述し、
route,mirror,fault,retryなどのサブフィールドを組み合わせます。 - route.destination.subset – DestinationRule の subset 名を参照し、バージョン単位の振り分けが可能です。
- weight – 複数の destination がある場合にトラフィック比率(0〜100)で指定します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews-vs spec: hosts: - reviews http: - route: - destination: host: reviews subset: v1 # デフォルトバージョン weight: 100 |
DestinationRule と subset によるバージョン管理
DestinationRule は「どのインスタンスを指すか」を決め、subset ごとにラベルセレクタや接続ポリシー(タイムアウト・回路遮断)を付与します。
- host – 対象 Service 名。
- subsets –
nameとlabelsの組み合わせでバージョンやロールを定義。 - trafficPolicy – subset 単位でリトライやタイムアウトなどのポリシーを設定できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: reviews-dr spec: host: reviews subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 # カナリア対象の新バージョン |
VirtualService が「どこへ送るか」、DestinationRule が「どのインスタンスに届くか」を明確に分離することで、トラフィックシフトを安全・柔軟に実施できます。
Weight ベースで実現するトラフィックシフト手順
Weight パラメータを段階的に変更しながら新バージョンへ流入させる方法を解説します。ここでは 0 % → 100 % を 5 段階(20 % 刻み)でロールアウトする例を示し、環境依存の sed/yq に代わる汎用的な手順も併せて紹介します。
初期設定と段階的シフトの考え方
まずは v2 の weight を 0 % とした VirtualService を作成し、DestinationRule は一度だけ適用します。その後は kubectl patch(JSONPatch)や istioctl experimental replace で weight を上書きすることで段階的にシフトできます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# reviews-vs.yaml (初回適用:v2 へ 0%) apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews-vs spec: hosts: - reviews http: - route: - destination: host: reviews subset: v1 weight: 100 - destination: host: reviews subset: v2 # カナリア対象 weight: 0 # 後述のコマンドで増加させる |
| ステップ | v2 の weight |
推奨更新方法 |
|---|---|---|
| 1 | 0 % | kubectl apply -f reviews-vs.yaml(初回) |
| 2 | 20 % | kubectl patch virtualservice reviews-vs --type=json -p='[{"op":"replace","path":"/spec/http/0/route/1/weight","value":20}]' |
| 3 | 40 % | 同上(value を 40 に変更) |
| 4 | 60 % | 同上(value を 60 に変更) |
| 5 | 80 % | 同上(value を 80 に変更) |
| 6 | 100 % | 同上(value を 100 に変更) |
ポイント
-kubectl patchは JSONPatch 形式で対象フィールドだけを書き換えるため、YAML 全体を手動で編集する必要がなく、どのシェル環境でも同一のコマンドで実行できます。
- パス/spec/http/0/route/1/weightは「最初の http ルート配列の 2 番目(v2)の weight」を指します。VirtualService の構造が変わった場合はkubectl get virtualservice reviews-vs -o yamlで確認してください。
安全に適用するための検証コマンド
設定変更前に構文エラーや互換性問題をチェックし、障害リスクを低減させます。
|
1 2 3 4 5 6 7 8 9 |
# 1. YAML のスキーマ検証(istioctl が推奨) istioctl analyze -f reviews-vs.yaml # 2. 実際にクラスタへ適用する前のドライラン kubectl apply --dry-run=client -f reviews-vs.yaml # 3. パッチ適用後の差分確認(オプション) kubectl get virtualservice reviews-vs -o yaml | diff -u <(cat reviews-vs.yaml) - |
検証を通過したら
kubectl applyまたはkubectl patchを実行し、段階的シフトを進めます。
モニタリング・障害検知と自動ロールバック
トラフィックシフト中は エラーレート と レイテンシ の変化をリアルタイムで監視し、閾値超過時に即座に weight を 0 % に戻す仕組みが不可欠です。本節では Prometheus/Grafana/Kiali を用いた可視化と、シンプルな自動ロールバックスクリプトの実装例を示します。
Prometheus / Grafana / Kiali で取得できる指標
| 指標 | 説明 | 推奨 PromQL |
|---|---|---|
istio_requests_total |
リクエスト総数(ステータス別にラベル付) | sum(rate(istio_requests_total{destination_service="reviews"}[1m])) |
| エラー率 | 5xx 系レスポンスの割合 | sum(rate(istio_requests_total{destination_service="reviews",response_code=~"5.."}[1m])) / sum(rate(istio_requests_total{destination_service="reviews"}[1m])) |
| レイテンシ(95 パーセンタイル) | 応答時間の上位 5 % | histogram_quantile(0.95, sum(rate(istio_request_duration_seconds_bucket{destination_service="reviews"}[1m])) by (le)) |
- Grafana:公式 Istio Service Dashboard をインポートすれば、v2 subset のトラフィック比率・エラー率・レイテンシが一目で把握できます。
- Kiali:サービスマップ上にルーティング割合を可視化し、クリックで該当 VirtualService へジャンプできるため、障害発生時の原因特定が迅速です。
自動ロールバックの実装例(bash + curl)
以下は Prometheus の HTTP API をポーリングし、閾値を超えたら kubectl patch で weight を 0 % に戻すスクリプトです。CronJob または外部監視エージェントから実行できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#!/usr/bin/env bash # ------------------------------------------------- # カナリアリリースの自動ロールバックスクリプト # - エラー率 > 2% もしくは 95th パーセンタイルレイテンシ > 500ms のときに weight=0 にリセット # ------------------------------------------------- PROM_URL="http://prometheus.monitoring.svc:9090/api/v1/query" THRESH_ERR=0.02 # 2% THRESH_LAT=0.5 # 0.5 秒 while true; do # エラー率取得 ERR=$(curl -s "${PROM_URL}?query=sum(rate(istio_requests_total{destination_service=\"reviews\",response_code=~\"5..\"}[1m]))/sum(rate(istio_requests_total{destination_service=\"reviews\"}[1m]))" | jq -r '.data.result[0].value[1]') # 95th レイテンシ取得 LAT=$(curl -s "${PROM_URL}?query=histogram_quantile(0.95, sum(rate(istio_request_duration_seconds_bucket{destination_service=\"reviews\"}[1m])) by (le))" | jq -r '.data.result[0].value[1]') # 閾値判定 if (( $(echo "$ERR > $THRESH_ERR" | bc -l) )) || (( $(echo "$LAT > $THRESH_LAT" | bc -l) )); then echo "$(date +%T) : 閾値超過検知 (error=$ERR, latency=${LAT}s)。weight=0 にロールバックします。" kubectl patch virtualservice reviews-vs --type=json \ -p='[{"op":"replace","path":"/spec/http/0/route/1/weight","value":0}]' else echo "$(date +%T) : 正常 (error=$ERR, latency=${LAT}s)。" fi sleep 30 # 30 秒ごとにチェック done |
CronJob 定義例(Kubernetes)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
apiVersion: batch/v1 kind: CronJob metadata: name: canary-rollback spec: schedule: "*/1 * * * *" # 毎分実行 jobTemplate: spec: template: spec: containers: - name: rollback image: bitnami/kubectl:latest # kubectl が入ったイメージ command: ["/bin/bash","/scripts/rollback.sh"] volumeMounts: - name: script mountPath: /scripts restartPolicy: OnFailure volumes: - name: script configMap: name: rollback-script # 上記シェルを格納した ConfigMap |
このように Prometheus の指標と
kubectl patchを組み合わせるだけで、障害発生時の自動ロールバックが実装できます。
ベストプラクティスと CI/CD パイプラインへの統合
安全なカナリアリリースを継続的に行うためには リトライ・タイムアウト・CircuitBreaker の設定と、GitOps/CI ツールでの自動化が鍵となります。本節では推奨設定例と、Argo CD と Tekton を用いたデプロイパイプラインを紹介します。
リトライ・タイムアウト・CircuitBreaker の推奨設定
| フィールド | 推奨値(例) | 効果 |
|---|---|---|
retries.attempts |
3 | 一時的な失敗を自動再試行 |
retries.perTryTimeout |
2s | 各リトライの最大待機時間 |
timeout (HTTP) |
5s | 全体リクエストの上限 |
outlierDetection.consecutive5xxErrors |
5 | 5xx エラーが連続したインスタンスを除外 |
outlierDetection.interval |
10s | 判定間隔 |
outlierDetection.baseEjectionTime |
30s | 除外期間 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews-vs spec: hosts: - reviews http: - route: - destination: host: reviews subset: v2 weight: 20 retries: attempts: 3 perTryTimeout: 2s timeout: 5s outlierDetection: consecutive5xxErrors: 5 interval: 10s baseEjectionTime: 30s |
GitOps と Tekton でカナリアデプロイを自動化
Argo CD(GitOps)
Argo CD がリポジトリの差分を検知すると自動的に kubectl apply を実行します。以下は reviews/ ディレクトリ配下にある VirtualService と DestinationRule を管理する ApplicationSet の例です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: istio-canary spec: generators: - git: repoURL: https://github.com/your-org/istio-manifests.git revision: HEAD directories: - path: reviews template: metadata: name: '{{path.basename}}' spec: project: default source: repoURL: "{{repoURL}}" targetRevision: "{{revision}}" path: "{{path}}" destination: server: https://kubernetes.default.svc namespace: prod syncPolicy: automated: prune: true selfHeal: true |
Tekton Pipeline(CI 側)
Tekton のタスクで kubectl と yq(または jq)を組み合わせ、段階的に weight を上げるジョブを作成します。以下は「20 % → 40 % → … → 100 %」まで自動シフトするパイプライン例です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
apiVersion: tekton.dev/v1beta1 kind: Pipeline metadata: name: canary-deploy spec: tasks: - name: apply-dr taskRef: name: kubectl-apply params: - name: yaml value: reviews-dr.yaml - name: shift-weight runAfter: [apply-dr] taskSpec: steps: - name: shift image: bitnami/kubectl:latest script: | #!/usr/bin/env bash for w in 20 40 60 80 100; do echo "Setting weight to ${w}%" kubectl patch virtualservice reviews-vs --type=json \ -p='[{"op":"replace","path":"/spec/http/0/route/1/weight","value":'"${w}"'}]' # 監視ツールが安定を確認できるように待機 sleep 30 done |
上記の構成により、コード変更 → Git にマージ → Argo CD が自動デプロイ → Tekton が段階的シフトとロールバック監視まで一連のフローが 完全に自動化 されます。
まとめ
- Istio のコアは Envoy + istiod(Pilot) で構成され、旧 Mixer に相当する機能は Telemetry と Policy がそれぞれ Envoy・istiod に分散しています。
- VirtualService が「トラフィックの行き先」、DestinationRule が「バックエンドインスタンス」を定義し、
weightで段階的にシフトできる点がカナリアリリースの鍵です。 kubectl patch(JSONPatch)を用いた 汎用的な weight 更新手順 とistioctl analyzeによる事前検証で、環境依存性を排除しつつ安全にロールアウトできます。- Prometheus / Grafana / Kiali を活用したリアルタイム指標取得と、閾値超過時の自動ロールバックスクリプトにより、障害時の影響範囲を最小化します。
- リトライ・タイムアウト・CircuitBreaker のベストプラクティス と、Argo CD/Tekton を組み合わせた GitOps パイプラインで、手作業ミスを防ぎつつ継続的なカナリアデプロイが実現できます。
これらの手順と設定を体系化すれば、Kubernetes 上の Istio 環境でも 安全・高速・自動化 されたトラフィックシフトが可能となり、サービス品質を保ったまま新機能やバージョンアップを本番に展開できるようになります。