背景と理由:Kubernetesエコシステムにおけるサービスメッシュの採用
Kubernetes上のマイクロサービスアーキテクチャは急速に成長しており、その成長に伴い、スケールに関するおなじみの課題も生じていました。
数十の相互依存するサービスにわたるトラフィック管理、堅牢なセキュリティの確保、包括的な可観測性の実現は、すぐに大きな運用上の負担となりました。リトライロジック、サーキットブレーカー、セキュアな通信のための相互TLS(mTLS)、エンドツーエンドのリクエストトレースといった機能の実装は複雑であることが判明しました。これらは多くの場合、広範なアプリケーションレベルのコード変更やカスタムインフラストラクチャを要求し、開発者の時間を浪費していました。
まさにここでサービスメッシュが威力を発揮します。サービス間の通信を管理するためだけに特化したインフラストラクチャ層を提供します。この層は、基盤となる複雑さの多くを抽象化し、開発者がネットワークの悩みに頭を悩ませる代わりに、ビジネスロジックに集中できるようにします。さらに、トラフィック管理、ポリシー適用、テレメトリデータ収集のための強力な機能も提供します。
数あるサービスメッシュの選択肢の中で、Istioはすぐに最有力候補となりました。なぜか?その包括的な機能セット、拡張性、そして堅牢なコミュニティサポートにより、容易な選択となりました。Istioは、Envoyプロキシサイドカーをアプリケーションコンテナと並行して直接注入することで機能します。これらのプロキシは、すべてのネットワーク通信を傍受し、Istioのコントロールプレーンで定義されたポリシーを適用します。
これらの複雑さと永遠のように格闘した後、私は重要な真実に気づきました。サービスメッシュの機能を習得することは、必須ではなく、不可欠なものでした。私の実体験から、これは今日の真剣なDevOpsプラクティショナーやクラウドエンジニアにとって、核となるスキルであると言えます。
私たちにとって、Istioは過去6ヶ月間でKubernetes上のマイクロサービスを管理し、スケーリングする方法を完全に変革しました。私たちは、常に問題のトラブルシューティングを行っていた状態から、明確なポリシーで環境を積極的に制御する状態へと移行しました。
インストール:クラスターでIstioを起動して実行する
既存のKubernetesクラスターにIstioをデプロイするのは通常簡単ですが、選択したインストールプロファイルについて慎重に検討する必要があります。開始する前に、kubectlがクラスターにアクセスできるように設定されていることを確認してください。また、istioctlよりもhelmでインストールを管理したい場合は、helmも必要かもしれません。
ステップ1:Istioのダウンロード
まず、Istioリリースをダウンロードします。常に公式のIstioドキュメントで利用可能な最も安定したバージョンを確認してください。
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.x.x # ダウンロードしたバージョンに置き換えてください(例:istio-1.20.0)
export PATH=$PWD/bin:$PATH
このコマンドはIstioパッケージを簡単にダウンロードして抽出し、istioctlクライアントをPATHに追加します。基本的に、istioctlはIstioに関するすべての主要なコマンドラインツールになります。
Istioはいくつかの構成プロファイルを提供しており、それぞれ異なる環境やユースケースに合わせて調整されています。本番環境では、defaultプロファイルが通常、機能と効率的なリソース使用の堅実なバランスを提供します。調査や開発段階であれば、demoプロファイルで十分な場合が多いです。本番デプロイメントには、defaultを選択しました。
istioctl install --set profile=default --verify
このコマンドを実行すると、インストールが開始されます。これにより、すべての必須Custom Resource Definitions(CRD)が設定され、IstiodのようなIstioのコントロールプレーンコンポーネントがデプロイされ、イングレスゲートウェイが構成されます。重要なのは、--verifyフラグがインストールの成功を確認し、すべてのコアコンポーネントが稼働していることを保証することです。
ステップ3:インストールの検証
インストールコマンドが完了したら、すべてのIstioコントロールプレーンコンポーネントがistio-systemネームスペース内でアクティブに稼働していることを確認することが不可欠です。
kubectl get ns istio-system
kubectl get pods -n istio-system
istio-systemがネームスペースとしてリストされているはずです。重要なのは、その中のistiodやistio-ingressgatewayのようなすべてのPodがRunningステータスを表示していることです。
構成:サービスをメッシュに組み込む
Istioがインストールされたので、既存のサービスを統合する時が来ました。ここでの主な目標は、EnvoyプロキシサイドカーをアプリケーションPodに注入することです。幸いなことに、Istioは、インジェクション用にラベル付けした名前空間内にデプロイされたすべてのPodにこれらのサイドカーを自動的に注入できます。
ステップ1:Istioインジェクション用に名前空間にラベルを付ける
特定の名前空間内のすべての*新しい*Podに対して自動サイドカーインジェクションを有効にするには、単にラベルを付ける必要があります。たとえば、アプリケーションがdefault名前空間にある場合、次のようにします。
kubectl label namespace default istio-injection=enabled --overwrite
--overwriteフラグは、名前空間にすでにistio-injectionラベルがある場合に不可欠です。これは*新しい*Podにのみ適用されることに注意してください。既存のデプロイメントがある場合、サイドカーが正しく注入されるように再起動する必要があります。
kubectl rollout restart deployment -n default # または特定のデプロイメント名
ステップ2:サンプルアプリケーション(例:Bookinfo)をデプロイする
Istioが実際に動作するのを見るために、そのよく知られたBookinfoアプリケーションをデプロイします。このサンプルアプリは複数のマイクロサービスを特徴とし、多様な通信パターンを見事に示しています。これらのサービスをデプロイすることから始めましょう。
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -n default
現在のPodを見てみましょう。各Bookinfoサービスについて、Podごとに2つのコンテナがあるはずです。アプリケーションコンテナと、新しく注入されたEnvoyサイドカーです。
kubectl get pods -n default
ステップ3:ゲートウェイでアプリケーションを公開する
クラスターの外部からBookinfoアプリケーションにアクセスするには、GatewayとVirtual Serviceという2つの重要なIstioコンポーネントが必要です。Gatewayはメッシュのすべてのインバウンドおよびアウトバウンドトラフィックを処理します。一方、Virtual Serviceはトラフィックをサービスにルーティングする方法を決定します。
# samples/bookinfo/networking/bookinfo-gateway.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway # Istioのデフォルトイングレスゲートウェイを使用
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml -n default
次に、アプリケーションにアクセスするためのイングレスIPとポートを見つける必要があります。これらの詳細は、お使いのKubernetes環境によって異なることに注意してください。
export INGRESS_HOST=$(kubectl get svc istio-ingressgateway -n istio-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl get svc istio-ingressgateway -n istio-system -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
echo "Bookinfoアプリケーションは、http://$GATEWAY_URL/productpage でアクセスできるようになりました"
ステップ4:トラフィック管理 – A/Bテストまたはカナリアデプロイメント
Istioは、その高度なトラフィック管理機能で真価を発揮します。数ヶ月間の手動ルーティング調整に耐えた後、A/BテストやカナリアリリースにIstioのVirtualServicesとDestinationRulesを採用することは、画期的なことだと感じました。早速トラフィックを設定しましょう。reviews:v1に50%、残りの50%をreviews:v3(星評価を含むバージョン)にルーティングします。
# reviews-v1-v3-route.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 50
- destination:
host: reviews
subset: v3
weight: 50
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
kubectl apply -f reviews-v1-v3-route.yaml -n default
この設定では、まずDestinationRuleオブジェクトを定義します。これらは、reviewsサービスのversionラベルから派生した名前付きサブセット(v1、v2、v3など)を作成します。その後、VirtualServiceが引き継ぎ、指定した重みに従ってこれらのサブセット間でトラフィックをルーティングします。
ステップ5:セキュリティ強化のための相互TLS(mTLS)の有効化
いかなる環境においても、セキュリティは最重要です。Istioは、サービス全体でのmTLSの実装を信じられないほど簡単にします。すべてのサービス間通信を自動的に暗号化および認証します。私たちのチームにとって、これは全体のセキュリティ体制を強化するための重要な機能となりました。
# default-mtls.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT
kubectl apply -f default-mtls.yaml
このPeerAuthenticationポリシーは、istio-system名前空間に適用されると、メッシュ内のすべてのサービスに厳格な相互TLS(STRICT mTLS)の使用を強制します。Istioは証明書の発行とローテーションを積極的に処理し、内部通信のセキュリティを確保するための運用負担を劇的に軽減します。
検証と監視:メッシュの洞察を得る
Istioから得られた最も直接的な利点の一つは、可観測性の劇的な向上でした。トラフィックをネイティブに監視し、トレースを追跡し、サービス間の依存関係を視覚化する能力は、複雑なマイクロサービス環境をデバッグし、理解する方法を真に変革しました。
ステップ1:Istioダッシュボードへのアクセス
Istioは、Kiali、Prometheus、Grafanaなどの人気のある可観測性ツールとスムーズに統合されます。インストールプロファイルによっては、これらがすでにデプロイされているか、別途インストールする必要がある場合があります。defaultプロファイルの場合、通常istioctlを介してそれらにアクセスできます。
istioctl dashboard kiali
istioctl dashboard grafana
istioctl dashboard prometheus
- Kiali: サービスメッシュの可観測性を提供する包括的なコンソールです。メッシュのトポロジを視覚化し、トラフィックフローを理解し、サービスの健全性を分析できます。
- Grafana: Prometheusによって収集されたメトリクスを使用して、リッチでカスタマイズ可能なダッシュボードを作成するのに最適です。
- Prometheus: これは、EnvoyプロキシとIstioコントロールプレーンの両方からメトリクスを収集するための不可欠な基盤として機能します。
ステップ2:Jaegerによるリクエストのトレース
分散トレースは、マイクロサービスのデバッグにとって絶対に不可欠です。IstioはJaeger(またはZipkin)と自動的に統合し、リクエストがサービスを通過する際のエンドツーエンドのトレースを提供します。Jaegerダッシュボードを簡単に起動できます。
istioctl dashboard jaeger
Bookinfo製品ページを更新するなど、アプリケーションにリクエストを送信することで、Jaegerにトレースが即座に表示されます。これらのトレースは、異なるサービス間での各リクエストの遅延とパスを明らかにし、パフォーマンスのボトルネックを簡単に特定するのに役立ちます。
ステップ3:トラフィックルートとポリシー適用を監視する
それでは、Kialiダッシュボードに戻り、グラフビューに移動しましょう。Bookinfoアプリケーションを更新すると、トラフィックフローが視覚的に表示されます。reviews VirtualServiceを構成して、v1とv3の間でトラフィックを50/50に分割したため、Kialiはこの分布を明確に視覚的に確認できます。個々のサービスや接続をクリックすると、詳細なメトリクス、トレース、適用されたポリシーを表示できます。
export INGRESS_HOST=$(kubectl get svc istio-ingressgateway -n istio-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl get svc istio-ingressgateway -n istio-system -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
for i in $(seq 1 100); do curl -s -o /dev/null -w "%{http_code}" http://$GATEAY_URL/productpage; done
このコマンドの実行中に、reviewsサービスのKialiグラフを観察してください。サービスのv1とv3バージョンに流れるリクエストがほぼ均等に分割されていることがわかるはずです。これにより、トラフィック管理構成が完全にアクティブであり、期待どおりに機能していることが確認されます。
6ヶ月間の本番運用を経て、IstioはKubernetesスタック内で不可欠なレイヤーであることが明確に証明されました。手動で実装するには信じられないほど困難で、リソース集約的となるトラフィック制御、セキュリティ、可観測性に関する重要な機能を提供します。学習曲線は確かにありますが、複雑なマイクロサービスを管理する上で得られる運用上のメリットは計り知れず、どのチームにとっても真に変革をもたらすものです。

