ローカルの Kubernetes 環境(kind)を使って、Istio のサービスメッシュ機能を検証してみました。公式の Bookinfo チュートリアルをベースにしています。
※ この記事について
Istio には充実した公式チュートリアル* が存在しますが、本記事は「まずは手っ取り早く、ローカル環境でサービスメッシュの機能と全体像を体験したい!」という方向けの内容です。
本記事は構成・執筆を Gemini に行ってもらい、筆者がレビュー・加筆しています。
本記事では、Sidecar モードでの構築・検証手順を解説します。
はじめに:用語の整理
ハンズオンに入る前に、今回登場する主役たちを簡単に整理しておきます。
サービスメッシュとは?
マイクロサービスアーキテクチャにおいて、「サービス(Pod)同士の通信」を専門に管理するインフラ層のことです。
アプリのコードの中に「通信のリトライ処理」や「通信の暗号化」「メトリクス出力」などを書くのは大変です。そこで、各アプリのコンテナの横に「サイドカー」と呼ばれるプロキシを置き、すべての通信をそこ経由にすることで、ネットワークの制御をプロキシに委譲する仕組みです。
Istio* とは?
現在最もスタンダードとなっているサービスメッシュのツールです。
Kubernetes 上で動く Pod に対して、自動的に Envoy という高性能なプロキシをサイドカーとして注入し、それらを一元管理するための強力なコントロールプレーンを提供します。

(引用:https://istio.io/latest/blog/2019/data-plane-setup/)
Kiali* とは?
Istio が構築したサービスメッシュ内の通信状況を可視化するダッシュボード画面です。
「どの Pod からどの Pod へ、何%のエラー率で、何ミリ秒かかって通信しているか」を、リアルタイムにトポロジーマップとして描画してくれます。
前提条件とセットアップ
以下のツールが利用可能な状態からスタートします。
dockerkindkubectlistioctl
まずはローカルの kind クラスターに Istio を導入し、サンプルアプリ(Bookinfo)をデプロイします。
# 1. kind でクラスターを作成
kind create cluster --name istio-tutorial
# 2. Istio のインストール
istioctl install --set profile=default -y
# 3. default ネームスペースへのサイドカー自動注入を有効化
kubectl label namespace default istio-injection=enabled
# 4. Bookinfo アプリケーションのデプロイ
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/bookinfo/platform/kube/bookinfo.yaml
istio-injection=enabled というラベルにより、このネームスペース内に新しく作られるすべての Pod に対して、強制的に Istio のプロキシ(Envoy)がサイドカーとして注入されます。これが「Sidecar モード」と呼ばれる所以です。
Step 1: クラスター外部からのアクセスを許可する(Gateway 設定)
まずはデプロイしたアプリにブラウザからアクセスできるようにします。
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/bookinfo/networking/bookinfo-gateway.yaml
kind 環境の場合、LoadBalancer が使えないためポートフォワードでアクセスします。別のターミナルを開き、以下を実行しっぱなしにします。
kubectl port-forward svc/istio-ingressgateway -n istio-system 8080:80
これでブラウザから http://localhost:8080/productpage にアクセスできるようになります。リロードすると、右側のレビュー部分の星の色(赤、黒、星なし)がランダムに変わります。
※ ここで、bookinfo-gateway.yaml で Gateway と VirtualService というリソースをデプロイしました。
- Gateway:ポートやプロトコル(HTTP/HTTPS)など、「どうやってトラフィックをクラスターに受け入れるか」という入り口を定義します。
- VirtualService:「受け入れた通信をどこへ、どういう条件で流すか」という高度なルーティング(重み付け、ヘッダー判定など)を担当します。
外部からアクセスするだけなら標準の Ingress でも可能ですが、Ingress では管理が難しくなるカナリアリリースやフォールトインジェクションのような高度な制御を、シンプルかつ柔軟に設定できるのが Istio の強みです。
Step 2: Kiali でサービスメッシュを可視化する
Istio の醍醐味であるトラフィックの可視化を行います。Kiali と Prometheus をインストールします。
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/kiali.yaml
Kiali ダッシュボードを開きます。
istioctl dashboard kiali
左側メニューの一番上にある [Graph] をクリックし、[Namespace] でサンプルアプリが動いている default にチェックを入れます。
[Display] でグラフ上に表示する情報をカスタマイズできます。今回は、以下の項目にチェックを入れてみました。
- Traffic Distribution: 通信の分岐割合(%)が線の上に数字で表示されるようになります。
- Response Time: 通信にかかっているレイテンシがリアルタイムに表示されるようになります。
- Security: 通信が自動暗号化(mTLS)されていることを示す「鍵マーク」が線の上に表示されます。
- Traffic Animation: トラフィックの流れをアニメーション化します。
Kiali グラフの見方
Kiali のグラフには、Kubernetes や Istio のコンポーネントを視覚的に区別するための図形やバッジが配置されています。主な記号の意味は以下の通りです。
- 三角: Kubernetes の Service(アクセスの窓口・ロードバランサー)。
- 四角: 実際に動いている Workload / Pod(バージョンの実体)。トラフィックが必ず「Service」を通ってから、背後の「Workload」へ流れていく様子がトレースできます。
-
NS: Namespace の略。このノードがどのネームスペースに属しているかを示しています(今回は
defaultやistio-system)。 -
A: Application の略。Kubernetes のマニフェストで付与された
appラベルを元に、Istio が「これは 1つのアプリのまとまりだ」と認識してグルーピングしてくれています。
Kiali のグラフに表示されるデータは、以下のような連携で収集されています。
- 計測: 全ての通信は istio-proxy (Envoy) を通過するため、Envoy が自動でレスポンスタイムやステータスコードを記録。
-
収集: 各 Pod の Envoy が
/stats/prometheusエンドポイントを公開し、Prometheus がそれをスクレイプ。 - 描画: Kiali は Prometheus に対して PromQL を投げ、データを引っ張ってきてトポロジーグラフを描画。
Step 3: トラフィックルーティング(特定バージョンへの固定)
現状均等に分散されている reviews サービスへの通信を、一時的に v1(星なし)に固定します。
# バージョン(サブセット)の定義を登録
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/bookinfo/networking/destination-rule-all.yaml
# トラフィックを100% v1へ流すルールを適用
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/bookinfo/networking/virtual-service-all-v1.yaml
ここで適用しているのは以下の2つの Istio カスタムリソース(CRD)です。
- DestinationRule: 「v1, v2, v3が存在する」という宛先のカタログを定義。
- VirtualService: 「reviews 宛ての通信は100% v1に送る」という交通整理のルール。
適用後、何度ブラウザをリロードしても星が表示されない(v1)状態になります。
Kiali での確認ポイント
マニフェスト適用後、Kiali のグラフは自動で以下のように変化します。
- 線の固定: それまで reviews の Service から v1, v2, v3 の Workload へランダムに伸びていた矢印が消え、v1 の四角に向かって1本だけの線が伸びる状態に固定されます。
- トラフィックの完全遮断: v2 や v3 の四角ノードは、トラフィックが全く流れなくなるため、グラフ上から線が消え、しばらくするとノード自体も非表示になります。
Istioの VirtualService が、Service に届いた通信を裏側でコントロールしている様子が視覚的に確認できます。
Step 4: カナリアリリース(重み付けルーティング)
次に、新バージョンである v3(赤い星)を安全にリリースすることを想定し、v1 と v3 を「50%ずつ」の割合でユーザーに見せるカナリアリリースを実施します。
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
アプリケーションのコードや Pod 数は一切変更せず、サービスメッシュの設定を更新する(VirtualService の weight: 50 指定)だけで、A/B テストのようなルーティングが実現します。
Kiali での確認ポイント
トラフィックをループさせた状態でグラフを観察すると、以下の変化が起きます。
- 線の二股分岐: reviews の Service から、v1 と v3 の 2つの Workload に向かって線が二股に分岐します。v2 には線は伸びません。
- パーセンテージの表示: 事前に Display 設定で有効にした「Traffic Distribution」の効果により、分岐したそれぞれの線の上に 「50% / 50%」 という数値がリアルタイムに表示されます。(※実際の通信状況によって 48% と 52% のように多少のブレが発生することがあります)
Step 5: フォールトインジェクション(意図的な遅延の注入)
マイクロサービス運用において、特定のバックエンドが遅延した際にシステム全体にどう影響するかをテストします。今回は「特定のユーザーだけレスポンスが遅い」という障害を意図的に注入し、システムに隠れたバグがないかを確認します。
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/bookinfo/networking/virtual-service-ratings-test-delay.yaml
これは「HTTP リクエストのヘッダーに end-user: jason が含まれる場合のみ、最下流の ratings サービスの手前で 7秒の遅延(fixedDelay)を発生させる」という VirtualService の設定です。
実際に障害が発生したユーザーの画面がどうなるかを確認します。
- ブラウザで http://localhost:8080/productpage にアクセスします。
- 画面右上の [Sign in] をクリックします。
- User Nameに
jasonと入力し、Password は空のままでログインします。 - ログイン後、ページをリロードします。
- ページの読み込みに長い時間(約6秒)がかかり、最終的に画面右側のレビュー部分に「Ratings service is currently unavailable」というエラーメッセージが表示されます。
Bookinfo のソースコードを見ると、各サービスには以下のタイムアウトがハードコードされています。
- productpage(Python)は、reviews の応答を 3秒 しか待ちません(失敗すると1回だけリトライするため、合計 約6秒 で諦めます)。
- reviews(Java)は、ratings の応答を 10秒 待つ設定になっています。
今回、Istio の機能で ratings に 7秒 の遅延を注入しました。
その結果、reviews は 7秒間大人しく待とうとしますが、大元の productpage が 6秒で先にタイムアウトして通信を切断してしまったのです。
マイクロサービスでは、このように「各チームがバラバラのタイムアウト値を実装してしまう」という事故がよく起きます。Istio のフォールトインジェクションを使えば、インフラ層から意図的に遅延を発生させてこのような隠れたバグを炙り出すことができます。
発展
今回のチュートリアルは、すべての Pod に Envoy を同居させる Sidecar モードで検証しました。しかし現在は、Ambient モード という新しいアーキテクチャが存在しています。
Sidecar モードは、「すべての Pod にプロキシが乗るためリソース(CPU/メモリ)消費が激しい」「プロキシの更新時にアプリの再起動が伴う」といった課題がありました。
Ambient モードでは Pod へのサイドカー注入をやめ、L4(TCP ベースの暗号化やルーティング)を担当する軽量な「ztunnel」と、L7(HTT Pベースの高度なルーティングやフォールトインジェクション)を担当する「Waypoint Proxy」の2層構造にすることで、アプリとインフラを完全に分離・軽量化しています。
※ちなみに、Ambient モードを試す場合は istio-injection=enabled の代わりに istio.io/dataplane-mode=ambient というラベルを付与します。
おわりに
今回は、ローカル環境で Istio を構築し、Kiali による可視化から高度なルーティング、フォールトインジェクションまで、サービスメッシュの基礎を一通り体験しました。インフラ層でネットワーク制御を完結できる Istio の魅力が伝わっていれば幸いです。







