EKS Service Mesh 入門ハンズオン

Istio によるサービス間通信の制御・mTLS・トラフィック管理・Kiali 可視化を EKS で体験する

Amazon EKS Istio Envoy mTLS Kiali CLI 操作 上級 所要時間 120〜150 分 v1.0

📋 概要

Service Mesh はマイクロサービス間の通信を管理するインフラレイヤーです。各サービスのサイドカーとして Envoy プロキシを自動注入し、アプリコードを変更せずにトラフィック制御・相互 TLS・可観測性を実現します。

このハンズオンでは CNCF Graduated プロジェクトの Istio を EKS 上にインストールし、Bookinfo サンプルアプリを通じてサービスメッシュの主要機能を体験します。

ℹ️ なぜ Istio を選択したか(Linkerd との比較)

Linkerd は軽量で EKS への導入が容易ですが、このハンズオンでは以下の理由から Istio を採用しています。

  • トラフィック管理(VirtualService / DestinationRule)の表現力が高い
  • Bookinfo という公式のデモアプリが充実しており、学習体験が豊富
  • mTLS・Fault Injection・Circuit Breaker を宣言的 YAML で設定できる
  • Kiali という専用の可視化ツールが提供されている
  • Enterprise 採用率が高く、実務での利用シーンが多い

シンプルな mTLS と基本的なトラフィック管理が目的であれば Linkerd も優れた選択肢です。

項目内容
対象ツールAmazon EKS、Istio 1.24+、Envoy、Kiali、Jaeger(Istio アドオン)
主な学習内容サイドカー注入・mTLS 確認・トラフィック分割・Fault Injection・Kiali 可視化
所要時間120〜150 分
難易度★★★★☆(上級者向け)
前提知識Kubernetes の基本操作・YAML の読み書き・TLS の基本概念
費用目安約 4〜8 USD(EKS クラスター + t3.large × 3 ノード)

🏗️ アーキテクチャ

Service Mesh の Data Plane と Control Plane

Control Plane(istio-system namespace)
istiod — パイロット(トラフィックルール)・Citadel(証明書)・ギャラリー(設定)を統合管理
↓ xDS API(Envoy 設定配布)
Data Plane(各アプリ Pod)
アプリコンテナ + Envoy サイドカープロキシ(istio-proxy)
すべてのイン/アウト通信は Envoy を経由する
↕ mTLS でサービス間通信を暗号化
Istio Ingress Gateway
外部からのトラフィックをクラスター内のサービスにルーティング

Bookinfo サンプルアプリの構成

サービス役割バージョン
productpageフロントエンド(Python)v1
details書籍詳細 API(Ruby)v1
reviewsレビュー API(Java)v1(星なし)/ v2(黒星)/ v3(赤星)
ratings評価スコア API(Node.js)v1

reviews サービスが 3 バージョン存在し、トラフィック分割の体験に使います。

✅ 前提条件

⚠️ リソース要件に注意

Istio の Control Plane(istiod)と Ingress/Egress Gateway が起動します。最小 t3.medium × 3 台、推奨 t3.large × 3 台です。

⚠️ 費用について

t3.large × 3 ノードの EKS クラスターは 1 時間あたり約 $0.50 かかります。ハンズオン終了後は必ずクリーンアップしてください。

☸️ ステップ 1 ― EKS クラスターの準備

1-1. EKS クラスターの作成
eksctl create cluster \
  --name mesh-handson \
  --version 1.33 \
  --region ap-northeast-1 \
  --nodegroup-name workers \
  --node-type t3.large \
  --nodes 3 \
  --managed
1-2. クラスター接続確認
kubectl get nodes
# 3 ノードが Ready であることを確認
✅ 確認ポイント

3 つのノードがすべて Ready 状態で表示されれば次のステップに進めます。

🕸️ ステップ 2 ― Istio のインストール

istioctl を使って Istio をインストールします。

2-1. istioctl のダウンロードとインストール
# 最新の安定版をダウンロード
curl -L https://istio.io/downloadIstio | sh -

# ダウンロードされたディレクトリに移動(バージョン番号は実際のものに合わせる)
cd istio-1.24.*/
export PATH=$PWD/bin:$PATH

# バージョン確認
istioctl version --remote=false
ℹ️ Windows の場合
# PowerShell
$ISTIO_VERSION = "1.24.3"
Invoke-WebRequest -Uri "https://github.com/istio/istio/releases/download/$ISTIO_VERSION/istioctl-$ISTIO_VERSION-win-amd64.zip" -OutFile "istioctl.zip"
Expand-Archive -Path "istioctl.zip" -DestinationPath "."
$env:PATH = "$PWD;" + $env:PATH
2-2. Istio をデモプロファイルでインストール

demo プロファイルはすべての機能(Ingress/Egress Gateway 含む)を含み、学習目的に最適です。

istioctl install --set profile=demo -y

インストールに 3〜5 分かかります。

2-3. Istio コンポーネントの起動確認
kubectl get pods -n istio-system

以下の Pod が Running になるのを確認します。

  • istiod-xxx(Control Plane)
  • istio-ingressgateway-xxx(Ingress Gateway)
  • istio-egressgateway-xxx(Egress Gateway)
2-4. Istio アドオン(Kiali・Prometheus・Grafana・Jaeger)のインストール
kubectl apply -f samples/addons/kiali.yaml
kubectl apply -f samples/addons/prometheus.yaml
kubectl apply -f samples/addons/grafana.yaml
kubectl apply -f samples/addons/jaeger.yaml

# 起動待ち
kubectl rollout status deployment/kiali -n istio-system --timeout=120s
✅ 確認ポイント

kubectl get pods -n istio-system ですべての Pod が Running になれば成功です。

📦 ステップ 3 ― Bookinfo サンプルアプリのデプロイ

3-1. default namespace にサイドカー自動注入を有効化
kubectl label namespace default istio-injection=enabled
kubectl get namespace default --show-labels
3-2. Bookinfo アプリのデプロイ
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
3-3. Gateway と VirtualService の作成
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
3-4. DestinationRule の作成(サブセット定義)
kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
3-5. Ingress Gateway の外部 IP を取得
kubectl get svc istio-ingressgateway -n istio-system

EXTERNAL-IP の値が払い出されるまで 1〜2 分待ちます(EKS が NLB/ELB を作成します)。

# EXTERNAL-IP を変数に保存
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway \
  -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
echo "http://$INGRESS_HOST/productpage"
3-6. アプリへのアクセス確認

ブラウザで http://<EXTERNAL-IP>/productpage を開きます。Bookinfo の商品詳細ページが表示されます。

何度かリロードすると reviews セクションの星の表示が変わります(v1: 星なし / v2: 黒星 / v3: 赤星)。

✅ 確認ポイント

Bookinfo の productpage が表示され、リロードのたびに reviews のバージョンが変わることを確認できれば成功です。

🔍 ステップ 4 ― サイドカー注入の確認

4-1. Pod のコンテナ数を確認
kubectl get pods

各 Pod が 2/2(アプリコンテナ + Envoy サイドカー)になっていることを確認します。

NAME                              READY   STATUS    RESTARTS   AGE
details-v1-xxx                    2/2     Running   0          3m
productpage-v1-xxx                2/2     Running   0          3m
ratings-v1-xxx                    2/2     Running   0          3m
reviews-v1-xxx                    2/2     Running   0          3m
reviews-v2-xxx                    2/2     Running   0          3m
reviews-v3-xxx                    2/2     Running   0          3m
4-2. サイドカーコンテナの詳細確認
kubectl describe pod -l app=productpage | grep -A5 "Containers:"

istio-proxy(Envoy)コンテナが含まれていることを確認します。

4-3. Envoy が通信を仲介していることを確認
# istioctl でポッドのプロキシ設定を確認
istioctl proxy-config cluster \
  $(kubectl get pod -l app=productpage -o jsonpath='{.items[0].metadata.name}') | head -20
✅ 確認ポイント

すべての Bookinfo Pod が 2/2 で起動し、istio-proxy コンテナが含まれていれば Envoy サイドカーが正常に注入されています。

🔗 ステップ 5 ― サービス間通信の確認

5-1. アプリに継続的にリクエストを送信
for i in $(seq 1 30); do
  curl -s "http://$INGRESS_HOST/productpage" -o /dev/null -w "%{http_code}\n"
  sleep 1
done
5-2. istioctl でサービス間の通信状態を確認
istioctl proxy-status

すべての Pod の CDSLDSRDSEDSSYNCED であることを確認します。これは Istio Control Plane から Envoy への設定配布が完了していることを意味します。

✅ 確認ポイント

すべての Pod が SYNCED 状態で表示されれば、Istio がサービス間通信を管理できています。

🔐 ステップ 6 ― mTLS(相互 TLS)の確認と有効化

Istio はデフォルトで PERMISSIVE モード(mTLS と平文の両方を受け入れ)で動作します。STRICT モードに変更してサービス間通信をすべて暗号化します。

6-1. 現在の mTLS ステータスを確認
istioctl authn tls-check \
  $(kubectl get pod -l app=productpage -o jsonpath='{.items[0].metadata.name}')

現在は PERMISSIVE または AUTO モードのため、mTLS と平文の両方が通過します。

6-2. STRICT mTLS を有効化
kubectl apply -f - <<'EOF'
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: default
spec:
  mtls:
    mode: STRICT
EOF
6-3. mTLS 有効化を確認
istioctl authn tls-check \
  $(kubectl get pod -l app=productpage -o jsonpath='{.items[0].metadata.name}')

モードが STRICT に変わり、すべての通信が mTLS で暗号化されていることを確認します。

6-4. 平文通信が拒否されることを確認
# サイドカーなしの Pod から平文で通信を試みる
kubectl run test-curl --image=curlimages/curl --restart=Never -- \
  curl -s http://productpage:9080/productpage
kubectl logs test-curl
# mTLS STRICT モードでは接続が拒否される
✅ 確認ポイント

istioctl authn tls-check でモードが STRICT になり、サイドカーなし Pod からの平文通信が拒否されれば mTLS が正常に機能しています。

⚖️ ステップ 7 ― トラフィック分割(Canary デプロイ)

reviews サービスへのトラフィックをバージョン別に重み付けして振り分けます。

7-1. v1 に 100% ルーティング(安定版固定)
kubectl apply -f - <<'EOF'
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 100
EOF

ブラウザで productpage を何度リロードしても、reviews が常に v1(星なし)になります。

7-2. v1:v3 = 80:20 のカナリアルーティング
kubectl apply -f - <<'EOF'
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 80
    - destination:
        host: reviews
        subset: v3
      weight: 20
EOF

productpage を 10 回リロードすると、約 2 回(20%)が v3(赤星)になります。

7-3. v3 に 100% 移行(カナリア完了)
kubectl apply -f - <<'EOF'
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v3
      weight: 100
EOF
✅ 確認ポイント

重み付けを変えることで、productpage のリロード結果が期待通りの割合で v1/v3 に分散されれば成功です。アプリコードは一切変更せずにトラフィック制御ができています。

💥 ステップ 8 ― 障害注入(Fault Injection)とリトライ/タイムアウト

Istio の Fault Injection を使って、意図的に遅延やエラーを発生させ、アプリの耐障害性を確認します。

8-1. ratings サービスに遅延を注入

ratings サービスへのリクエストの 50% に 7 秒の遅延を注入します。

kubectl apply -f - <<'EOF'
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        percentage:
          value: 50
        fixedDelay: 7s
    route:
    - destination:
        host: ratings
        subset: v1
EOF

productpage を開くと、約 50% の確率で 7 秒後に ratings が「Ratings service is currently unavailable」と表示されます。

8-2. reviews にタイムアウトを設定

reviews が ratings を呼び出す際のタイムアウトを 0.5 秒に設定します(遅延 7 秒 > タイムアウト 0.5 秒なので必ずタイムアウトする)。

kubectl apply -f - <<'EOF'
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v2
    timeout: 0.5s
EOF
8-3. リトライポリシーの設定

遅延を削除し、代わりにエラーレスポンスへのリトライを設定します。

# まず遅延と timeout を削除
kubectl delete virtualservice ratings
kubectl delete virtualservice reviews

# エラー注入(HTTP 500)を 100% で設定し、3 回リトライする
kubectl apply -f - <<'EOF'
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - fault:
      abort:
        percentage:
          value: 100
        httpStatus: 500
    retries:
      attempts: 3
      perTryTimeout: 2s
    route:
    - destination:
        host: ratings
        subset: v1
EOF
8-4. 後始末(Fault Injection の削除)
kubectl delete virtualservice ratings
kubectl delete virtualservice reviews
✅ 確認ポイント

遅延注入でページの応答が遅くなり、タイムアウト設定でエラーメッセージが表示されることを確認できれば、Fault Injection の動作を理解できています。

📊 ステップ 9 ― Kiali でサービスメッシュを可視化

Kiali は Istio 専用のオブザーバビリティダッシュボードです。サービス間の通信グラフ・メトリクス・設定状態を一画面で確認できます。

9-1. Kiali ダッシュボードを開く
istioctl dashboard kiali

ブラウザが自動で開きます(http://localhost:20001)。または別ターミナルで以下を実行します。

kubectl port-forward -n istio-system svc/kiali 20001:20001
9-2. トラフィックグラフを確認

左メニューの 「Graph」 をクリックします。

  • Namespace に default を選択
  • Traffic(リクエスト数/秒)・Error Rate・Response Time がグラフに表示される
  • サービス間の通信経路が矢印で可視化される
  • 赤い矢印 = エラーが発生しているサービス間の通信
9-3. サービスの詳細を確認

グラフのノード(サービス)をクリックすると、右パネルにそのサービスの詳細メトリクス(RPS・レイテンシ・エラー率)が表示されます。

9-4. Istio Config の検証

左メニューの 「Istio Config」 から VirtualService・DestinationRule などの設定の整合性(Validation)を確認できます。設定ミスがあれば赤いアイコンで警告されます。

9-5. Grafana と Jaeger の確認
# Grafana(Istio アドオン)
istioctl dashboard grafana

# Jaeger(Istio アドオン)
istioctl dashboard jaeger

Grafana では Istio Service Dashboard・Istio Workload Dashboard でサービスレベルのメトリクスが確認できます。

✅ 確認ポイント

Kiali のグラフで Bookinfo サービス間の通信が矢印で表示され、各サービスの RPS・エラー率・レイテンシが確認できれば成功です。

💡 学習ポイント

Service Mesh が解決する課題

課題Istio による解決
サービス間の平文通信(盗聴リスク)PeerAuthentication + mTLS STRICT で自動暗号化
特定バージョンのカナリアリリースVirtualService + weight でコードなしにトラフィック分割
ダウンストリームの障害による連鎖障害タイムアウト・リトライ・Circuit Breaker で保護
サービス間通信の可視化困難Kiali で通信グラフをリアルタイム表示

主要な Istio カスタムリソース

CRD役割
VirtualServiceトラフィックルーティング・Fault Injection重み付きルーティング・タイムアウト
DestinationRuleサービスのサブセット定義・接続プール設定v1/v2/v3 のサブセット定義
PeerAuthenticationmTLS ポリシー設定STRICT / PERMISSIVE
AuthorizationPolicyL4/L7 のアクセス制御特定 SA からのみ許可
Gateway外部トラフィックのエントリポイント設定Ingress Gateway のホスト・ポート設定

次のステップ

🧹 クリーンアップ

ハンズオン完了後は以下の順序でリソースを削除してください。

⚠️ EKS クラスターと ELB は放置すると費用が発生します

Istio Ingress Gateway に作成された ELB(ロードバランサー)も課金対象です。必ずクリーンアップを実施してください。

1. Bookinfo アプリの削除
kubectl delete -f samples/bookinfo/platform/kube/bookinfo.yaml
kubectl delete -f samples/bookinfo/networking/bookinfo-gateway.yaml
kubectl delete -f samples/bookinfo/networking/destination-rule-all.yaml
2. PeerAuthentication・VirtualService の削除(残っている場合)
kubectl delete peerauthentication default
kubectl delete virtualservice reviews ratings 2>/dev/null; true
3. Istio アドオンの削除
kubectl delete -f samples/addons/kiali.yaml
kubectl delete -f samples/addons/prometheus.yaml
kubectl delete -f samples/addons/grafana.yaml
kubectl delete -f samples/addons/jaeger.yaml
4. Istio のアンインストール
istioctl uninstall --purge -y
kubectl delete namespace istio-system
5. namespace ラベルの削除
kubectl label namespace default istio-injection-
6. test-curl Pod の削除(作成した場合)
kubectl delete pod test-curl --ignore-not-found
7. EKS クラスターの削除
eksctl delete cluster --name mesh-handson --region ap-northeast-1

ELB の削除を含めて 10〜15 分かかります。CloudFormation コンソールでスタックが消えたことを確認してください。

✅ クリーンアップ完了チェックリスト
  • ☐ Bookinfo アプリが削除された
  • ☐ PeerAuthentication・VirtualService が削除された
  • ☐ Istio アドオンが削除された
  • ☐ istio-system namespace が削除された
  • ☐ EKS クラスターが削除された
  • ☐ EC2 コンソールで ELB(ロードバランサー)が削除されていること
  • ☐ CloudFormation スタックが消えていること