自己紹介
千葉工業大学大学院 情報科学研究科 情報科学専攻 修士1年の井上 裕介と申します.
大学では主にメタヒューリスティクスに関する最適化アルゴリズムの研究に従事しております.
2023 年のサマーインターンから引き続き Sreake 事業部にて技術調査を行っております.
はじめに
サービスメッシュは,マイクロサービスアーキテクチャにおいて欠かせない通信管理の仕組みとして進化を続けています.
その代表的なソリューションである Istio は,2017年以降多くのユーザに利用されてきました.
2024年に Google Cloud は,従来の Anthos Service Mesh のサービス名を Cloud Service Mesh に変更し,提供を開始しました.
マネージドサービスメッシュの登場により,サービスメッシュの管理はこれまで以上にシンプルになる可能性が出てきました.
本稿では,Istio と Cloud Service Mesh の違いを掘り下げながら,特に「マネージドな」サービスメッシュにおける管理の簡素化やメリットについて詳しく解説します.
前提知識
ではまず最初に,サービスメッシュとは何かについて解説し,Cloud Service Mesh について紹介します.
サービスメッシュ
マイクロサービスアーキテクチャにおいて,各サービスは独立して動作し,サービス間は API を用いて互いに通信しながら機能します.
ここで,マイクロサービスにおけるサービスの内容には,主に次の2つに分類されます.
- 機能ロジック (Functional Logic):
アプリケーションが提供する「機能」を実現するための処理や実装 - 非機能ロジック (Non-functional Logic):
アプリケーションの「品質」を保証するために必要な処理や実装
マイクロサービスの開発について,図:マイクロサービスの実装 a. を例にとって解説します.

アプリケーション開発者がマイクロサービスを開発する際,最も意識して開発すべき対象は機能ロジックです.
しかし,図のマイクロサービスでは,非機能ロジックであるトラフィック管理がひとつのサービスに内包されています.
ビジネスロジックと非機能ロジックが混在するマイクロサービスでは,次のような問題が発生します.
- 多言語対応の複雑さ:
マイクロサービスの開発言語が多様なため,言語ごとに非機能ロジックのライブラリを開発する必要がある - 特定のライブラリへの依存:
マイクロサービスの特定のレイヤーの実装が,共有ライブラリに強く依存する - 責任範囲の曖昧さ:
機能ロジックと非機能ロジックの境界が曖昧になり,開発チーム間での分業がしにくい状況
このような問題は,ビジネスロジックの開発速度を低下を招き,エンジニアの開発体験を悪化させます.
そこでサービスメッシュの出番です.
サービスメッシュ (Service Mesh) は,マイクロサービス同士のトラフィックを管理するための仕組みです.
CNCF (Cloud Native Computing Foundation) では,サービスメッシュを次のように説明しています.
サービスメッシュは,サービス間のトラフィック(つまり通信)を管理します.これにより,プラットフォームチームは,コードを変更することなく,クラスター内で実行されるすべてのサービスに信頼性,可観測性,セキュリティ機能を均一に追加できるようになります.
< 中略 >
サービスメッシュは,アプリコードに触れることなく,プラットフォームレイヤー上のすべてのサービスに信頼性,可観測性,セキュリティ機能を均一に追加します.あらゆるプログラミング言語と互換性があるため,開発チームはビジネスロジックの作成に集中できます.
引用: https://landscape.cncf.io/guide#orchestration-management–service-mesh
サービスメッシュは,主に次のような非機能ロジックを各マイクロサービスに対して横断的に配布します.
- L4/L7 トラフィック管理
- 証明書管理
- 認証認可
- テレメトリー作成
- ブラックボックステスト
- 回復性管理
サービスメッシュでは,各サービスにサイドカープロキシ (Sidecar proxy) と呼ばれる仲介役を配置し,サービス間の通信を制御・監視します.
このとき,プロキシはサービスに対して外付け機能として実装されます.
これはサイドカーモデル (Sidecar model) と呼ばれ,多くのサービスメッシュで採用されている実装方法です.
非機能ロジックのサイドカーと機能ロジックのビジネスロジックとは互いに独立しており,アプリケーション領域とインフラ領域のそれぞれのロジックを切り離すことができます.
図:マイクロサービスの実装 b. のように,サービスメッシュの導入後,マイクロサービスのビジネスロジックと非機能ロジックとを,コンテナという境界で明確に分業することができるようになりました.
これにより,アプリケーション担当はビジネスロジックの開発に集中できるようになり,インフラ担当はビジネスロジックに干渉することなく,安全に非機能ロジックの保守運用を行えるようになります.
これは,チーム全体の開発速度を向上させ,結果サービス全体のアジリティを向上することが期待されています.
Cloud Service Mesh
概要
Cloud Service Mesh は Istio を拡張した Google Cloud のマネージドサービスメッシュです.
Google Cloud の Compute Engine と Google Kubernetes Engine (GKE) Enterprise 環境の両方と,Google Cloud 外部との連携に対応しています.
Istio をベースとしながら,サービスメッシュの導入に伴う管理・監視・セキュリティの複雑さを軽減し,CloudNative な環境でより簡単に運用できるのが特徴です.
Cloud Service Mesh は,トラフィック管理やメッシュ テレメトリー,サービス間の通信の保護などのサービス提供を簡素化して,運用チームと開発チームのためにトイルを軽減します.Google のフルマネージド サービス メッシュを使用すると,複雑な環境を管理し,マイクロサービスのあらゆるメリットを享受できます.
引用: https://cloud.google.com/service-mesh/docs/overview?hl=ja#what_is
マネージドなサービスメッシュとは
Cloud Service Mesh は「マネージドなサービスメッシュ」という用語と共に紹介されています.
マネージドなサービスメッシュとは,一体どのようなものでしょうか.
Google Cloud が紹介する「マネージド」とは,サービスメッシュの運用に伴う管理作業をクラウド事業者が肩代わりする形のサービスを指します.
Cloud Service Mesh では,以下の点が管理されています.
- コントロールプレーンの運用管理 (インストール・アップグレード・パッチ適用)
- 監視,メトリクスの統合 (Cloud Monitoring, Logging, Trace)
- IAM との統合によるセキュリティ強化
- マルチクラウド・ハイブリッド環境での利用
複雑な運用になりがちな Istio の管理のほとんどを Google Cloud が負担するため,インフラエンジニアや SRE チームの作業負担を削減することが期待されます.
また,GKE Enterprise 環境では以前から asmcli
を用いて Anthos Service Mesh を手動でインストールすることで,Google Cloud が提供する機能との連携が可能でした.
Cloud Service Mesh では,GKE Autopilot (以降 Autopilot) によるクラスタ作成時に,自動で Anthos Service Mesh のインストールを行なってくれます.
これにより,マイクロサービスアプリケーションのデプロイ,サービスメッシュのオートスケーリングなどの複雑な作業が,IaC や CI/CD パイプラインに簡潔に組み込まれます.
アーキテクチャ
Cloud Service Mesh は Istio API ではなく Google Cloud API を使用します.
この API は Mesh
, Gateway
, Route
という3つの主要なリソースで構成されています.
Mesh
リソース:istio-proxy
とプロキシレス gRPC クライアントのサービス間トラフィックの管理とセキュリティ構成に使用される (East-West サービス間トラフィック)istio-proxy
とプロキシレス gRPC クライアントは,Mesh
リソースの名前で識別されるサービスメッシュに結合することで,Cloud Service Mesh から構成を受け取るGateway
リソース:
Istio Ingress Gatewayとして機能するistio-proxy
のトラフィック管理とセキュリティ構成に使用され,外部クライアントがサービスメッシュに接続可能となる (North-South サービス間トラフィック)Route
リソースによって参照され,対応するGateway
構成に含まれるルートが追加されるRoute
リソース:HTTPRoute
,GRPCRoute
,TCPRoute
,TLSRoute
の4種類があり,サービスにルーティングを設定するために使用される これらのRoute
リソースは,1つ以上のMesh
リソースまたはGateway
リソースを参照し,対応する構成にルートを追加するRoute
リソースは,ルーティングの最終的な宛先として1つ以上のバックエンドサービスリソース (MIG (Management Instance Group), NEG (Network Endpoint Group)) を参照する形で作成される

Istio 単体では, istio-init
コンテナや istio-cni
ノードエージェントがトラフィックリダイレクトの役割を担っていました.
Cloud Service Mesh では,Mesh
リソースや Gateway
リソースを使用することで,関連するすべてのトラフィックが自動的にインターセプトされ,トラフィックは istio-proxy
によって処理されます.
Route
リソースは宛先情報に基づいてルーティングし,最終的に NEG が指定するエンドポイントへトラフィックが転送されます.

引用: https://cloud.google.com/service-mesh/docs/service-routing/service-routing-overview?hl=ja#use-cases
Cloud Service Mesh では,Istio が担う一部の役割は Google Cloud のマネージドサービスとして統合され,サービスメッシュをより透過的に提供していると考えられます.
では,NEG とは一体どのようなバックエンドサービスリソースなのでしょうか.
引用: https://cloud.google.com/kubernetes-engine/docs/how-to/standalone-neg?hl=ja#overview
Google Cloud の VPC (Virtual Private Cloud) ネットワークでは,Kubernetes リソースに対して Network Endpoint を割り当てます.
プロビジョニングされたすべての Pod には Network Endpoint というオブジェクトが付与され,Pod を管理する Service には Network Endpoint Group (NEG) というオブジェクトが付与されます.
こうすることで,Pod や Service を Google Cloud のリソースとして扱うことが可能となります.
NEG は Google Cloud の VPC ネットワークで次の役割を担います.
- トラフィックのバックエンドエンドポイント
- コンテナネイティブなロードバランシングのサポート
- FQND ベースのサービスディスカバリ
NEG は,インターセプトされた後のトラフィックが最終的にどこにルーティングされるかを定義するバックエンドとして機能します.
このように,Mesh
と Gateway
がトラフィックのインターセプトと大まかなスコープを定義し,Route
が具体的なルーティングポリシーを,そして NEG がそのルーティングの具体的な終点を提供することで,Cloud Service Mesh は高度なトラフィック管理機能を実現しています.
マネージドコントロールプレーンにてサービスディスカバリを行なっているため,管理者は Pod にサイドカーが注入されていることを気にするだけで良いのです.
※ 本稿では簡単のため Zonal NEG, Internet NEG, Standalone NEG を分別せずに説明しました.より詳細な解説は参考資料 7,参考資料 8及び参考資料 9を参照して下さい.
次章では実際に GKE Enterprise 環境で Cloud Service Mesh を構築してみましょう.
Cloud Service Mesh のプロビジョニングと動作確認
ここからは,Cloud Service Mesh コントロールプレーンを GKE のクラスタにインストールしていきます.
Cloud Service Mesh をクラスタにインストールするには,まず表 1のロールがついていることを確認しましょう.
ここではロールの付与に関しては紹介を省きますので,こちらで詳細を確認してください.
ロール名 | ロール ID | 付与する場所 | 説明 |
---|---|---|---|
GKE Hub 管理者 | roles/gkehub.admin | Fleet Project | GKE Hub と関連リソースに対する完全アクセス権. |
Service Usage 管理者 | roles/serviceusage.serviceUsageAdmin | Fleet Project | サービス状態の有効化,無効化,検査,オペレーションの検査,ユーザ プロジェクトの割り当てと請求の利用が可能な権限. |
CA サービス管理者 β版 | roles/privateca.admin | Fleet Project | すべての CA サービスのリソースへの完全アクセス権. |
Cloud Service Mesh の環境構築に使用するソフトウェアについて,表 2に掲載するものを使用しました.
OS | macOS Sequoia 15.5 arm64 |
Shell (zsh) | 5.9 |
gcloud | Google Cloud SDK 524.0.0 bq 2.1.17 core 2025.05.23 gcloud-crc32c 1.0.0 gke-gcloud-auth-plugin 0.5.10 gsutil 5.34 |
kubectl | Client Version: v1.33.1 Kustomize Version: v5.6.0 Server Version: v1.32.4-gke.1106006 |
istioctl | client version: 1.26.0 |
本稿の検証は以下の GitHub リポジトリを使用して進めていきます.
セットアップ
検証を行う前準備として,gcloud などのツールのインストールや環境変数の定義を行います.
本稿で使用する GitHub のリポジトリをクローンし,ディレクトリへ移動
csm-env.sh
を実行して環境変数の設定を行う
sudo chmod +x csm-env.sh
./csm-env.sh
source asmcli.env
環境変数名 | 概要 |
---|---|
FLEET_PROJECT_ID | Fleet 登録先の GCP プロジェクト ID |
FLEET_PROJECT_NUMBER | 上記 Fleet プロジェクトのプロジェクト番号 |
CLUSTER_PROJECT_ID | GKE クラスタを作成する GCP プロジェクト ID (例: csm-bookinfo ) |
NETWORK_PROJECT_ID | ネットワーク (VPC) を所有する GCP プロジェクト ID |
FIREWALL | ファイアウォール名.<NETWORK_PROJECT_ID>-fw という形式で定義 |
REGION | GKE クラスタのリージョン (例:asia-northeast1 ) |
LOCATION | GKE クラスタのロケーション (例:asia-northeast1-a ) |
CONTEXT | kubectl や asmcli 用の GKE クラスタのコンテキスト名 |
HPATH | ASM 関連ファイルで使う Docker ホームパス |
OUTPUT_DIR | 出力ファイルの保存先ディレクトリ |
CREDENTIAL_PATH | GCP 認証情報ファイルのパス |
CLOUD_DNS_ID | Cloud DNS ゾーンの ID |
DESCRIPTION | DNS ゾーンの説明 |
プロジェクト ID $FLEET_PROJECT_ID
の認証を行い,Google アカウントでログイン
gcloud auth login --project $FLEET_PROJECT_ID
gcloud
CLI にインストールされているコンポーネントの更新を行う
gcloud components update
Google Cloud CLI をセットアップ
gcloud components install gke-gcloud-auth-plugin
~/.zshrc
に以下の項目を追加し更新
export PATH=$PATH:~/google-cloud-sdk/bin source ~/.zshrc
インストールの確認
gke-gcloud-auth-plugin --version
結果
Kubernetes v1.28.2-alpha+000000000000000000000000000
これで準備が整いました.
次章ではクラスタの作成を行います.
Cloud Service Mesh 有効なクラスタの作成
ここからは Cloud Service Mesh コントロールプレーンがインストールされたクラスタを作成していきます.
csm
ディレクトリへ移動する
mesh.yaml
ファイルを作成する
echo "management: automatic" > mesh.yaml
Cloud Service Mesh のフリート機能を有効にする
gcloud container fleet mesh enable --project $FLEET_PROJECT_ID \
--fleet-default-member-config mesh.yaml
結果
Waiting for Feature Service Mesh to be created...done.
クラスタの作成を行う
gcloud container clusters create-auto $CLUSTER_PROJECT_ID \
--fleet-project $FLEET_PROJECT_ID \
--location $REGION
クラスタの作成が完了したら作成されたクラスタを確認する
gcloud container clusters list
結果(NUM_NODES が空なのは Autopilot の仕様)
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
<CLUSTER_PROJECT_ID> asia-northeast1 1.32.4-gke.0000000 XXX.XXX.XXX.XXX e2-small 1.32.4-gke.0000000 RUNNING
kubectl
が作成したクラスタを参照するようにクレデンシャルを取得する
gcloud container clusters get-credentials $CLUSTER_PROJECT_ID \
--location $REGION \
--project $FLEET_PROJECT_ID
クラスタの起動を確認
kubectl config current-context
結果
gke_<FLEET_PROJECT_ID>_<REGION>_<CLUSTER_PROJECT_ID>
次のコマンドを実行してクラスタの Workload Identity プール を一覧取得し,Workload Identity 連携が有効になったことを確認する
gcloud container clusters describe $CLUSTER_PROJECT_ID \
--location $REGION \
--format="value(workloadIdentityConfig.workloadPool)"
以下の値が返ってくれば有効である
<FLEET_PROJECT_ID>.svc.id.goog
クラスタがフリートに登録されていることを確認する
gcloud container fleet memberships list --project $FLEET_PROJECT_ID
結果
NAME UNIQUE_ID LOCATION
<CLUSTER_PROJECT_ID> 00000000-0000-0000-0000-000000000000 <REGION>
Cluster の Mesh API を有効化
gcloud services enable mesh.googleapis.com --project $FLEET_PROJECT_ID
ローカルからコントロールプレーンがプロビジョニングされていることを確認する
gcloud container fleet mesh describe --project $FLEET_PROJECT_ID
以下のような出力が表示される
~~~
membershipSpecs:
projects/000000000000/locations/asia-northeast1/memberships/csm-bookinfo:
mesh:
management: MANAGEMENT_AUTOMATIC
origin:
type: FLEET
membershipStates:
projects/000000000000/locations/asia-northeast1/memberships/csm-bookinfo:
servicemesh:
~~~
controlPlaneManagement:
details:
- code: REVISION_READY
details: 'Ready: asm-managed'
implementation: TRAFFIC_DIRECTOR
state: ACTIVE
dataPlaneManagement:
details:
- code: OK
details: Service is running.
state: ACTIVE
state:
code: OK
description: 'Revision ready for use: asm-managed.'
~~~
membershipStates
の implementation
を確認すると TRAFFIC_DIRECTOR
と書かれている
https://cloud.google.com/service-mesh/docs/check-control-plane-implementation?hl=ja
Web コンソールを開き,クラスタから $CLUSTER_PROJECT_ID
を選択し,機能欄の一番下の項目を確認する
プロビジョニング済み
とあれば成功

これで Cloud Service Mesh が有効なクラスタの用意が完了しました.
Istio Ingress Gateway のインストール
最後に外部からサービスメッシュへアクセスするために Istio Ingress Gateway をクラスタにデプロイする必要があります.
csm
ディレクトリで引き続き作業
以下のコマンドで istio-system
Namespace を作成
kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: istio-system
annotations:
mesh.cloud.google.com/proxy: '{"managed":"true"}'
labels:
istio-injection: enabled
EOF
anthos-service-mesh-packages リポジトリをクローンする
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages.git
istio-system
Namespace に Istio Ingress Gateway をデプロイする
kubectl apply -n istio-system -f ./anthos-service-mesh-packages/samples/gateways/istio-ingressgateway
istio-ingressgateway
が istio-system
Namespace に正常に適用され istio=ingressgateway
ラベルがあるかを確認
kubectl get pod -n istio-system -l istio=ingressgateway --show-labels | grep "istio=ingressgateway"
結果
3つの Pod が作成されており,STATUS
が Running
であることを確認する
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-0000000000-00000 1/1 Running 0 2m40s
istio-ingressgateway-1111111111-11111 1/1 Running 0 2m41s
istio-ingressgateway-2222222222-22222 1/1 Running 0 2m41s
istio-ingressgateway
Service に EXTERNAL-IP
が割り振られているか確認
kubectl get svc -n istio-system
結果
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer XXX.XXX.XXX.XXX XXX.XXX.XXX.XXX 15021:30242/TCP,80:32325/TCP,443:31116/TCP 12m
これで通常の Istio を用いた Kubernetes クラスタと,ほぼ同様のサービスメッシュ環境が構築できました.
次章では,実際にマイクロサービスアプリケーションをデプロイしてみましょう.
サンプルアプリ Bookinfo のインストール
ここからは,Istio が提供するサンプルアプリ Bookinfo Application をクラスタにデプロイします.
引用: https://istio.io/latest/docs/examples/bookinfo/
Bookinfo で提供されるマイクロサービスは以下の通りです.
- productpage:
details と reviews マイクロサービスを呼び出して,ページに情報を入力する- details:
書籍情報が含まれる - reviews:
書評が含まれます.また,ratings マイクロサービスを呼び出す - ratings:
書評に伴う書籍ランキング情報が含まれる
- details:
reviews のマイクロサービスには次の 3 つのバージョンがある
- Reviews v1:
ratings サービスを呼び出さない - Reviews v2:
ratings サービスを呼び出し,各評価を 1~5 個の黒色の星で表示 - Reviews v3:
ratings サービスを呼び出し,各評価を 1~5 個のオレンジ色の星で表示
本章の目標は,ブラウザ上のダッシュボードからマイクロサービスのトラフィックを確認することとします.
では早速アプリケーションのデプロイを行っていきましょう.
bookinfo
ディレクトリへ移動する
デフォルトのインジェクションラベルを Namespace に適用する
kubectl label namespace default istio.io/rev- istio-injection=enabled --overwrite
istio-injection
ラベルがついた Namespace を確認
kubectl get ns --show-labels -l="istio-injection"
結果
NAME STATUS AGE LABELS
default Active 35m istio-injection=enabled,kubernetes.io/metadata.name=default
istio-system Active 31m istio-injection=enabled,kubernetes.io/metadata.name=istio-system
最新版の Istio をダウンロードする 本稿では istio-1.26.0
環境で検証を行う ※ バージョンを指定する場合は ISTIO_VERSION=<version number> sh -
と記述する
curl -L https://istio.io/downloadIstio | sh -
以下のコマンドを実行して Bookinfo アプリをデプロイする
kubectl apply -f ./istio-*/samples/bookinfo/platform/kube/bookinfo.yaml
アプリケーションがデプロイできたか確認する
kubectl get pods,services
結果
NAME READY STATUS RESTARTS AGE
pod/details-v1-84766dc95b-k6h2h 2/2 Running 0 53s
pod/productpage-v1-77549cbd67-bmlgk 2/2 Running 0 50s
pod/ratings-v1-b68c7d664-n9xdq 2/2 Running 0 53s
pod/reviews-v1-cd8d4db96-7rhdv 2/2 Running 0 52s
pod/reviews-v2-759fd6876d-8bq9h 2/2 Running 0 51s
pod/reviews-v3-f98496d4-d6mdn 2/2 Running 0 51s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/details ClusterIP XXX.XXX.XXX.XXX <none> 9080/TCP 55s
service/kubernetes ClusterIP XXX.XXX.XXX.XXX <none> 443/TCP 35m
service/productpage ClusterIP XXX.XXX.XXX.XXX <none> 9080/TCP 51s
service/ratings ClusterIP XXX.XXX.XXX.XXX <none> 9080/TCP 55s
service/reviews ClusterIP XXX.XXX.XXX.XXX <none> 9080/TCP 53s
ClusterIP の DNS 解決とサービスメッシュ通信が成功しているかを Ratings Pod から確認
kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"
結果
<title>Simple Bookstore App</title>
bookinfo-gateway.yaml
に以下の変更を加える
apiVersion: networking.istio.io/v1beta1 # <- v1 から v1beta1 へ変更
kind: Gateway
metadata:
name: bookinfo-gateway
namespace: default # <- default Namespace を追加
spec:
~~~
servers:
- port:
number: 80 # <- 8080 から 80 へ変更
~~~
---
apiVersion: networking.istio.io/v1beta1 # <- v1 から v1beta1 へ変更
kind: VirtualService
metadata:
name: bookinfo
namespace: default # <- default Namespace を追加
~~~
apiVersion
をv1
からv1beta1
に変更metadata.namespace.default
を追加- Gateway マニフェストの
spec.servers.port.number
を 8080 から 80 へ変更
※ 2025年7月現在, Cloud Service Mesh のコントロールプレーンである Traffic Director の API バージョンはv1beta1
までしか対応しておりません.
https://cloud.google.com/service-mesh/docs/supported-features-managed?hl=ja#sidecar
Bookinfo アプリの Gateway をデプロイする
kubectl apply -f ./istio-*/samples/bookinfo/networking/bookinfo-gateway.yaml
Gateway と Virtual Service の確認
kubectl get gw,virtualservice
結果
NAME AGE
gateway.networking.istio.io/bookinfo-gateway 60s
NAME GATEWAYS HOSTS AGE
virtualservice.networking.istio.io/bookinfo ["bookinfo-gateway"] ["*"] 60s
これでクラスタの作成からサンプルアプリ Bookinfo のデプロイまでが完了しました.
Cloud Service Meshの動作確認
続いて,Bookinfo アプリを使って Cloud Service Mesh の動作確認を行なっていきましょう.
ターミナルから Bookinfo へリクエストを発生させ,サービスメッシュのトラフィックを Google Cloud のサービスメッシュダッシュボードから様子を確認できます.
Bookinfo アプリケーションにアクセスする
アプリケーションへのアクセス方法について解説します.
INGRESS_HOST
とGATEWAY_URL
にそれぞれ値を代入する
export INGRESS_HOST=$(kubectl get svc istio-ingressgateway -n istio-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export GATEWAY_URL=$INGRESS_HOST:80
echo "http://${GATEWAY_URL}/productpage"
Bookinfo アプリにリクエストを送信 ※ 更新に1分程度かかるため,繋がらない場合は少し待ってから再度実行してください
curl -I "http://${GATEWAY_URL}/productpage"
結果
HTTP/1.1 200 OK
server: istio-envoy
date: Mon, 02 Jun 2025 09:21:08 GMT
content-type: text/html; charset=utf-8
content-length: 15072
vary: Cookie
x-envoy-upstream-service-time: 226
http://<GATEWAY_URL>/productpage
にブラウザからアクセスする

通常の Bookinfo は v1
, v2
, v3
の3つのサービスが同時にデプロイされている バージョンの差異は Book Reviews の星を確認することで判別できる
v1
: 星が表示されないv2
: 黒い星が表示されるv3
: オレンジ色の星が表示される
一旦お疲れ様でした 🙌
順調に進んでいれば,ブラウザからクラスタにデプロイした Bookinfo アプリケーションへ到達できたかと思います.
では,サービスメッシュの状態を Google Cloud のダッシュボードから確認してみましょう.
可視化したサービスメッシュのトラフィックの様子を確認する
ここからは,Google Cloud のマネージドサービスメッシュが提供する機能について紹介していきます.
また,本稿では簡単な検証として次の項目を行います.
- すべてのマイクロサービスのトラフィックを確認する
- DestinationRule を追加し,加重ルーティングが行われる様子を確認する
では,検証に入っていきます.
1秒間隔で Bookinfo にローカルからリクエストを送信する
while :; do curl -s "http://${GATEWAY_URL}/productpage" | grep -o "<title>.*</title>"; sleep 1; done
ブラウザでサービスメッシュのダッシュボードを開き,トラフィックの様子を確認する

サービスのノードにカーソルをホバーするとエッジの統計情報を表示できる

さらにノードをホバー中に Expand
タブをクリックすることで Deployment
, Pod
までノードの詳細を展開できる

トポロジのノードをクリックすると,リストビューに詳細カードが表示される

より詳細な情報はリストビューの ダッシュボードに移動
から確認できる ここでは productpage
の詳細を確認する
概要
概要
について確認すると以下のような画面に遷移する

連携サービス
連携サービス
ではトポロジ指標を表示し,サービス間の送受信アクセスによる通信の暗号化などをリスト化して表示される
- 緑色: mTLS による暗号通信が行われている
- 黄色: 暗号化 (mTLS) と平文の混在
- 赤色: 平文による通信が行われている

1秒あたりのリクエスト数

エラー率

レイテンシ (50%, 95%, 99%)

指標
指標
ではリクエストなどのデータを時系列チャートで確認できる

インフラストラクチャ
インフラストラクチャ
ではインスタンスのメトリクスなどを時系列チャートで確認できる

トラフィック
トラフィック
では各サービス間通信におけるトラフィックの指標やサービスの詳細を確認できる

その他
セキュリティ
は 連携サービス
と同様のページが表示される
リソース
では対象の Service に関係するリソース (クラスタ,Gateway etc) の設定ファイルを参照できる
トラフィックルーティング
Bookinfo には Istio が提供する機能をテストできるいくつかのタスクが提供されています.
ここではタスクの一つであるリクエストルーティングを行い,トラフィックの様子を確認します.
⚠️ 以下で使用するすべてのマニフェストについて,apiVersion: networking.istio.io/v1
とある部分を apiVersion: networking.istio.io/v1beta1
に変更してから実行して下さい.
アプリケーションへのルートルールを設定し,各サービスのバージョンを指定する
kubectl apply -f ./istio-*/samples/bookinfo/networking/destination-rule-all.yaml
DestinationRule 設定を確認する
kubectl get destinationrules
結果
NAME HOST AGE
details details 17s
productpage productpage 19s
ratings ratings 18s
reviews reviews 18s
サービスへのアクセスを v1
のみに制限する
kubectl apply -f ./istio-*/samples/bookinfo/networking/virtual-service-all-v1.yaml
ダッシュボードからトポロジを確認する
v1
Service に 100% トラフィックが送信されていることが確認できる

トラフィック
から確認すると,v1
Service にアクセスが集中している様子がよくわかる

DestinationRule を削除する
kubectl delete -f ./istio-*/samples/bookinfo/networking/virtual-service-all-v1.yaml
このように,DestinationRule を定義することで Cloud Service Mesh 環境でも Istio と同様にアプリケーションへの加重ルーティングを手軽に行うことができ,その様子をダッシュボード上から確認することができました.
クリーンアップ
使い終わった不要なクラスタは削除しましょう.
csm
ディレクトリにてアプリケーションを削除する
kubectl delete -f ./istio-*/samples/bookinfo/networking/destination-rule-all.yaml
kubectl delete -f ./istio-*/samples/bookinfo/platform/kube/bookinfo.yaml
kubectl delete -f ./istio-*/samples/bookinfo/networking/bookinfo-gateway.yaml
csm-handson
ディレクトリへ戻り,クラスタを削除する
gcloud container clusters delete $CLUSTER_PROJECT_ID --location $REGION
csm-handson
ディレクトリで検証で使用した環境変数を削除する
source ./csm-env.sh -cleanup
Cloud Service Mesh の仕様と使用する際の勘所について
お疲れ様でした! 👏
ここまで,Cloud Service Mesh を前提としたクラスタの構築からテスト用のアプリケーションのデプロイまで,一通りの検証を行いました.
この章では,私が Cloud Service Mesh を調査する過程で遭遇した疑問や,使用する際の課題について紹介します.
Istio データプレーンと Traffic Director コントロールプレーンによるマネージドなサービスメッシュの構成
Istio 環境において, istio-init
コンテナの主な役割は,Pod 内のネットワークトラフィック (インバウンドおよびアウトバウンド) を Envoy サイドカープロキシにリダイレクトするための iptables ルールを設定することでした.
これには,Pod が NET_ADMIN
や NET_RAW
といった特権的な Kubernetes RBAC 権限を持つ必要があります.

引用: https://istio.io/latest/docs/setup/additional-setup/cni/
istio-cni
ノードエージェントは, istio-init
コンテナが特権を有するため,これを回避するために提案された後発のプラグインであり,主に Pod のトラフィックを istio-proxy
に流すために iptables のセットアップなどを行います.
istio-cni
ノードエージェントは,各 Kubernetes ノード上で特権を持つ単一の DaemonSet として動作し,Pod ごとに特権コンテナをデプロイするのではなく,ノードレベルで chained CNI プラグインをインストールします.
このプラグインが,Pod のネットワークセットアップフェーズで iptables ルールを設定し,トラフィックを istio-proxy
にリダイレクトします.
これにより,ユーザやワークロードが特権を持つ必要がなくなります.
しかし,GKE Autopilot 環境では Autopilot による管理により,kube-system
などに対する管理者側の操作を一切禁止しています.
これにより,一部のシステムコールを使用する CRD (Custom Resource Definitions) のインストールを妨害してきます.
ここで一つ疑問になるのが,「一体 GKE Enterprise 環境の Pod はどのように通信を行なっているのか」です.
なぜなら, istio-cni
ノードエージェントが存在しないということは, iptables の設定は行われません.
これは非常に奇妙な状況であることが分かります.
この奇妙なルーティングの正体は,冒頭で紹介した Google Cloud の NEG が関係しています.
NEG は Google Cloud の VPC ネットワークにおいて,バックエンドエンドポイントとして機能します.
Google Cloud では Pod に紐づいたエンドポイントの管理を NEG が担うことで,インスタンスの iptables を介さずにマネージドなルーテイングを提供することができます.

引用: https://cloud.google.com/blog/products/containers-kubernetes/container-native-load-balancing-on-gke-now-generally-available?hl=en
Cloud Service Mesh では, Istio のデータプレーンによって実現していた Envoy によるルーティング機能が,NEG などの Google Cloud のネイティブコンポーネントとして統合されています.
具体的には,Istio カスタムリソースである Gateway , VirtualService , DestinationRule が主体となって istio-proxy
(Envoy) の設定の抽象化とロードバランシングを提供します.

Google Cloud が提供するコントロールプレーンには Traffic Director と istiod
があり,すべての istio-proxy
を制御し,サービスメッシュ全体のプロキシの管理・監視から証明書の管理などを担います.
Traffic Director は NEG を介して Pod をエンドポイントとして抽象化し,サイドカープロキシにルーティングに関する情報を配布することで,高度なルーティングを可能にしています.
以下の表 4は, Istio API と Google Cloud API ,それぞれが Cloud Service Mesh で利用可能な機能について比較を行なったものです.
項目 | Istio API リソース | Google Cloud API リソース | 範囲 | 割り当てと上限 | 上限 |
---|---|---|---|---|---|
トラフィック ルーティング | VirtualService | HTTPRouteTCPRouteTLSRoute | グローバル | HTTPRoute の割り当てTCPRoute の割り当てTLSRoute の割り当て | サービスポートごとに 1 つ,Istio VirtualService HTTPRoute,TCPRoute,TLSRoute ごとに 1 つ. |
サービス表現(ルート / ポリシー アタッチメント用) | ServiceServiceEntry | BackendService | グローバル | BackendService の割り当て | サービスポートごとに 1 つ(Istio ServiceEntry を含む). |
ワークロードのプロパティ(IP:port,ローカリティなど) | ServiceServiceEntry | NetworkEndpointGroup | ゾーン | NetworkEndpointGroup の割り当て | サービスポート,ゾーンごとに 1 つ.リージョン GKE クラスタでは,クラスタのノードが少なくとも 1 つあるすべてのゾーンに,特定のサービスポートの NetworkEndpointGroup が作成されます. |
ワークロードの健全性のモニタリング | サービス | HealthCheck | グローバル | HealthCheck の割り当て | GKE クラスタごとに 1 つ. |
ワークロード ポリシーの接続ポイント | PeerAuthenticationAuthorizationPolicyRequestAuthentication EnvoyFilter | EndpointPolicy | グローバル | EndpointPolicy の割り当て | サービスポートとワークロード ポリシーごとに 1 つ. |
認証 | PeerAuthentication | ClientTlsPolicyServerTlsPolicy | グローバル | ClientTlsPolicy の割り当てServerTlsPolicy の割り当て | サービスポートごとに 1 つの ClientTlsPolicy.TLS Gateway ごとに 1 つの ServerTlsPolicy. |
承認 | AuthorizationPolicy | HttpFilter | グローバル | HttpFilter の割り当て | Istio AuthorizationPolicy ごとに 1 つ. |
ゲートウェイ | ゲートウェイ | ゲートウェイ | グローバル | Gateway の割り当て | Istio Gateway サーバーポートごとに 1 つ. |
トラフィック分散ポリシー | GCPTrafficDistributionPolicy | ServiceLbPolicy | グローバル | ServiceLbPolicy の割り当て | GCPTrafficDistributionPolicy ごとに 1 つ. |
引用: https://cloud.google.com/service-mesh/docs/understand-api-resources?hl=ja#my-heading
この表から, Istio API と Google Cloud API は一対一に対応した API が存在し, Google Cloud では Traffic Director によってサービスメッシュを実現しています.
では, Traffic Director によって管理される istio-proxy
を確認してみましょう.
動作中の ratings-v1
Pod をキルし,Deployment により再度 Pod がデプロイされたことを確認する
kubectl delete pod ratings-v1-000000000-00000 -n default
kubectl get pods | grep "ratings-v1"
結果
pod "ratings-v1-000000000-00000" deleted
ratings-v1-111111111-11111 0/2 PodInitializing 0 6s
Pod の Events ログを確認する
kubectl describe pod/ratings-v1-111111111-11111 | grep "Events" -A 20
結果
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal LoadBalancerNegNotReady 1m36s neg-readiness-reflector Unable to determine the pod's node name.
Normal Scheduled 1m36s gke.io/optimize-utilization-scheduler Successfully assigned default/ratings-v1-xxxxxxxx-xxxx4 to gk3-<CLUSTER_PROJECT_ID>-nap-xxxxxxxx-xxxxxxxx-xxxx
Normal LoadBalancerNegNotReady 1m36s (x2 over 7m36s) neg-readiness-reflector Waiting for pod to become healthy in at least one of the NEG(s): [k8s1-xxxxxxxx-default-ratings-9080-xxxxxxxx]
Normal Pulled 1m35s kubelet Container image "gcr.io/gke-release/asm/proxyv2:1.20.8-asm.33-distroless" already present on machine
Normal Created 1m35s kubelet Created container: istio-validation
Normal Started 1m35s kubelet Started container istio-validation
Normal Pulled 1m34s kubelet Container image "docker.io/istio/examples-bookinfo-ratings-v1:1.20.3" already present on machine
Normal Created 1m34s kubelet Created container: ratings
Normal Started 1m34s kubelet Started container ratings
Normal Pulled 1m34s kubelet Container image "gcr.io/gke-release/asm/proxyv2:1.20.8-asm.33-distroless" already present on machine
Normal Created 1m34s kubelet Created container: istio-proxy
Normal Started 1m34s kubelet Started container istio-proxy
Warning Unhealthy 1m33s kubelet Readiness probe failed: Get "http://xxx.xxx.xxx.xxx:15021/healthz/ready": dial tcp xxx.xxx.xxx.xxx:15021: connect: connection refused
Normal LoadBalancerNegWithoutHealthCheck 1m31s neg-readiness-reflector Pod is in NEG "Key{\"k8s1-xxxxxxxx-default-ratings-9080-xxxxxxxx\", zone: \"asia-northeast1-c\"}". NEG is not attached to any BackendService with health checking. Marking condition "cloud.google.com/load-balancer-neg-ready" to True.
出力結果から, istio-proxy
と istio-validation
の存在が確認され, Traffic Director によってサイドカーのプロビジョニングが行われたことがわかります.
Events ログの内容を詳しく見てみましょう.
はじめに ratings-v1
Pod が起動すると,その Pod の IP アドレスとポートが,対応する NEG にエンドポイントとして動的に登録されます.
このとき, neg-readiness-reflector
は作成された Pod を監視対象として認識します.
次に neg-readiness-reflector
は, Pod のコンテナ (この場合はratings
とistio-proxy
) が起動し,Kubernetes の Readiness Probe が成功するのを待ちます.
そして, Pod の Readiness Probe が成功すると, neg-readiness-reflector
は Pod に対して cloud.google.com/load-balancer-neg-ready
Condition を True
に設定します.
このことから,Traffic Director は一部の Istio データプレーンと連携し,サービスメッシュの構成には Cloud API を使用して Cloud Service Mesh を構成していることがわかるかと思います.
サービスメッシュの Gateway として Istio Ingress Gateway を使用する場合の注意点
サービスメッシュにアクセスするには Gateway を必要とします.
Istio サービスメッシュに外部からアクセスする主要な方法は次の2種類があります.
Gateway API は動的なインフラストラクチャの展開と高度なトラフィックルーティングを提供する API のグループです.
今回は Gateway API は使用しませんでしたが,付録にて Gateway API を使用した Gateway のデプロイ方法が記載しています.
では Istio Ingress Gateway をデプロイする方法について見ていきましょう.
デプロイする手段はは主に二通りの方法があります.
- Anthos Service Mesh リポジトリを使用する
istioctl
を使用する
まず,Anthos Service Mesh のリポジトリからデプロイする方法についてです.
本稿では Anthos Service Mesh のリポジトリをローカルのワークスペースにクローンし,kubectl
コマンドを使用して istio-system
Namespace に適用しました.
本来は asmcli
コマンドを使用して Anthos Service Mesh をクラスタにインストールした際に,ローカルにリポジトリがクローンされます.
しかし,手動で行なった場合も問題なくクローンからの Gateway のデプロイが可能です.
もう一つの方法として,istioctl
を使ってデプロイする方法があります.
おそらくほとんどの方は Istio をクラスタにインストールした際,自動的に istio-system
Namespace に istio-ingressgateway
がデプロイされていた,という場合が多いのではないでしょうか.
しかし,この方法で Autopilot 環境にインストールしようとすると,前述の通り Autopilot の制限によりうまくいきません ( istioctl
を使用したデプロイ方法については付録に記載しています).
仮にインストールに成功したとしても,公式の想定では istiod
はクラスタに存在せず,代わりに Traffic Director がコントロールプレーンとして動作するため,ダッシュボード上に Service が表示されないなどの不具合が生じます.
なお,6月時点での公式ドキュメントの紹介では Istio Ingress Gateway に関して特に言及がありませんでした.
しかし,7月11日の更新にて,公式ドキュメントに Istio Ingress Gateway のデプロイに関するページが追加されました.
サンプルアプリの Gateway のデプロイ方法について紹介されているので,本稿と合わせて読んでみてください.
まとめ
本稿では, Cloud Service Mesh の基本的な構築方法について解説しました.
istioctl
や asmcli
などを一切使わずにサービスメッシュを構築可能であり,その手軽さが魅力的でした.
一方で,通常の Istio ベースの環境とは大きく異なる点がいくつか存在し,仕様の違いを理解するのに時間が必要でした.
Autopilot の登場により, Anthos Service Mesh を手動インストールする作業から解放されたことは喜ばしい反面, Anthos Service Mesh で可能だった柔軟な設定が Autopilot により制限されてしまったのは非常に残念です.
また,Istio のデータプレーンをそのまま使用することができるため,既存のサービスメッシュの移行作業がスムーズに実行可能でした.
一方で, 対応しているコントロールプレーンの API バージョンが v1beta1
までしか対応していない点や, Istio が提供する Traffic Policy や DNS Proxy といった一部の機能が Traffic Director では未実装である点が,不便と感じました.
これらの機能が今後どのようにサポートされていくのか注目です.
必要な最低限のモニタリングツールや GUI は Google Cloud がダッシュボード上で提供してくれるため,サービスメッシュの導入の敷居はそこまで高くないという印象でした.
次回は「実践編」ということで,Istio が得意とするトラフィック管理により注目し,Cloud Service Mesh 上でのルーティング制御について動作検証を行います.
その教材として,日本最大級の CloudNative 関係のテックカンファレンス「CloudNative Days」の実行委員会が提供する「一日で学ぶクラウドネイティブ技術実践ハンズオン」の Chapter Istio の内容を Cloud Service Mesh で再現したいと思います.
付録
Gateway API を使用したサービスメッシュへの接続
「テストアプリ Bookinfo のインストール.9」にて,Istio Ingress Gateway ではなく gateway-api/bookinfo-gateway.yaml
を使用する
kubectl apply -f ./istio-*/samples/bookinfo/gateway-api/bookinfo-gateway.yaml
INGRESS_HOST
と GATEWAY_URL
にそれぞれ値を代入する
export INGRESS_HOST=$(kubectl get gtw bookinfo-gateway -o jsonpath='{.status.addresses[0].value}')
export GATEWAY_URL=$INGRESS_HOST:80
echo "http://${GATEWAY_URL}/productpage"
バックエンドサービスの3つのバージョンを定義する
kubectl apply -f ./istio-*/samples/bookinfo/platform/kube/bookinfo-versions.yaml
Autopilot 環境で Istio ベースのサービスメッシュを構築したい場合
Autopilot 環境下では,`istio-cni のインストールができないため,基本的には Anthos Service Mesh (旧 Traffic Director) での動作を基本とします.
しかし,セキュリティリスクの観点から非推奨ではありますが,istioctl
を使用してインストールする方法があるため,簡単に紹介します.
Cloud Service Mesh のフリート機能を有効にした後,クラスタの作成を行う
gcloud container clusters create-auto $CLUSTER_PROJECT_ID \
--fleet-project $FLEET_PROJECT_ID \
--location $REGION \
--workload-policies=allow-net-admin
※ --workload-policies=allow-net-admin
は GKE バージョン 1.27 以降のクラスタに適応される.セキュリティ機能の一つである NET_ADMIN
capability の許可を行う.要するに特権コンテナの作成を許可する操作である (参考資料 11を参照).
クラスタ作成後は「Cloud Service Mesh 有効なクラスタの作成」を通常通り最後まで行う 「Istio Ingress Gateway のインストール」へは進まず,以下の通りに進める
istioctl
を使用して istiod
と istio-ingressgateway
をクラスタにインストールする
⚠️ GKE Autopilot 環境では kube-system
の変更が禁止されており,istio-cni
の ConfigMap
の更新が行えない.そのため,istio-cni
のインストールを禁止することでインストール失敗を回避している.
istioctl install -n istio-system -y -f - <<EOF
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: istio-operator
namespace: istio-system
spec:
profile: default
components:
cni:
enabled: false
ingressGateways:
- name: istio-ingressgateway
enabled: true
EOF
結果
✔ Istio core installed ⛵️
✔ Istiod installed 🧠
✔ Ingress gateways installed 🛬
✔ Installation complete
※ Mutating Webhook Configuration
によるインストール失敗の場合 新しいリビジョンやタグへの切り替えに失敗しているため,以下のコマンドで Admission Webhook オブジェクトを削除してから再度インストールする必要がある
kubectl delete mutatingwebhookconfiguration istio-revision-tag-default
これで Istio のインストールは完了です.
前述の通り特権コンテナを許可しているため,ご使用の際はセキュリティに十分注意して下さい.
参考資料
- Cloud Service Mesh 概要
- 【Istio⛵️】サービスメッシュの登場経緯とIstioサイドカーインジェクションの仕組み
- GKE でマネージド Cloud Service Mesh コントロール プレーンをプロビジョニングする
- Bookinfo サンプルのデプロイ
- Google Kubernetes Engine に Anthos Service Mesh をインストールする
- Cloud Service Mesh サービス ルーティング API の概要
- ゾーン ネットワーク エンドポイント グループの概要
- インターネット ネットワーク エンドポイント グループを使用した Cloud Service Mesh
- スタンドアロン NEG によるコンテナ ネイティブのロード バランシング
- Cloud Service Mesh サービス ルーティング API の概要
- GKE Autopilot のセキュリティ対策
- 【Istio⛵️】Istioによって抽象化されるEnvoyのHTTPSリクエスト処理の仕組み
- Istio | Request Routing