はじめに:なぜService Meshが必要なのか?
マイクロサービスアーキテクチャが普及するにつれ、数十から数百のサービスがネットワークを通じて通信する環境が一般的になりました。この複雑なサービス間通信で、以下のような問題が繰り返し発生します。
セキュリティの課題: サービス間通信が暗号化されていないと、内部ネットワークでも盗聴が可能です。各サービスでTLSを個別に実装し、証明書を管理するのは膨大な運用負荷です。
可観測性(Observability)の欠如: リクエストが複数のサービスを経由する際、どこでレイテンシが発生しているか、どのサービスがエラーを返しているかを把握するのが困難です。
トラフィック制御の難しさ: カナリアデプロイ、A/Bテスト、サーキットブレーカーなどの高度なトラフィック管理をアプリケーションコードに直接実装する必要があります。
Service Meshはこれらすべての問題をインフラレイヤーで解決します。アプリケーションコードを一行も変更せずに、セキュリティ/可観測性/トラフィック制御をネットワークレベルで透過的に追加できます。
1. Service Meshアーキテクチャ
Service Meshは大きく2つのプレーン(plane)で構成されます。
1.1 データプレーン(Data Plane)
データプレーンは実際のサービストラフィックを処理するプロキシの集合です。各サービスPodにサイドカーとしてデプロイされ、すべてのインバウンド/アウトバウンドトラフィックをインターセプトします。
┌─────────────────────────────────────────────┐
│ Pod │
│ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Application │◄──►│ Sidecar Proxy │ │
│ │ Container │ │ (Envoy/linkerd2) │ │
│ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────┘
サイドカープロキシの主な役割:
- すべてのトラフィックを透過的にインターセプト(iptablesルールを活用)
- mTLS暗号化/復号化の実行
- ロードバランシング(ラウンドロビン、最小接続数など)
- メトリクス収集と分散トレーシングヘッダーの伝播
- リトライ、タイムアウト、サーキットブレーキングの適用
1.2 コントロールプレーン(Control Plane)
コントロールプレーンはデータプレーンのプロキシを中央で管理・設定します。
Istioのコントロールプレーン(Istiod):
# Istiodが管理する主な機能
- サービスディスカバリ: Kubernetes APIからサービス一覧を同期
- 設定配布: VirtualService, DestinationRuleをEnvoy設定に変換
- 証明書管理: mTLS用証明書の発行/更新(内蔵CA)
- ポリシー適用: AuthorizationPolicy, PeerAuthenticationの配布
Linkerdのコントロールプレーン:
# Linkerdコントロールプレーンコンポーネント
- destination: サービスディスカバリ + ポリシー配布
- identity: mTLS証明書発行(trust anchor基盤)
- proxy-injector: Pod作成時のサイドカー自動注入
- heartbeat: テレメトリ収集
2. Istio深掘り
2.1 Istioアーキテクチャ概要
Istioは最も機能が豊富なService Meshです。Google、IBM、Lyftが共同開発し、現在CNCFの卒業プロジェクトです。
# Istioインストール(istioctl)
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.24.0
export PATH=$PWD/bin:$PATH
# プロファイルベースのインストール
istioctl install --set profile=demo -y
# ネームスペースにサイドカー自動注入を有効化
kubectl label namespace default istio-injection=enabled
2.2 Envoyサイドカープロキシ
Istioのデータプレーンは Envoy プロキシを使用します。EnvoyはC++で書かれた高性能L4/L7プロキシです。
# Envoyの主要機能
- HTTP/1.1, HTTP/2, gRPCサポート
- 自動リトライとサーキットブレーキング
- 動的設定更新(xDS API)
- 豊富なメトリクスとトレーシング
- WebAssembly(Wasm)拡張サポート
- ホットリスタート(graceful restart)
メモリオーバーヘッドはPod当たり約40-100MBで、CPUオーバーヘッドはリクエストあたり数ミリ秒レベルです。
2.3 VirtualService
VirtualServiceはIstioでトラフィックルーティングルールを定義する中核リソースです。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews
http:
# カナリアデプロイ: 90% v1, 10% v2
- route:
- destination:
host: reviews
subset: v1
weight: 90
- destination:
host: reviews
subset: v2
weight: 10
timeout: 5s
retries:
attempts: 3
perTryTimeout: 2s
retryOn: 5xx,reset,connect-failure
2.4 DestinationRule
DestinationRuleはルーティング決定後のトラフィックに適用するポリシーを定義します。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews-destination
spec:
host: reviews
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
h2UpgradePolicy: DEFAULT
http1MaxPendingRequests: 100
http2MaxRequests: 1000
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
loadBalancer:
simple: LEAST_REQUEST
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
2.5 Gateway
Istio Gatewayはメッシュ外部から入ってくるトラフィックを管理します。
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: bookinfo-cert
hosts:
- "bookinfo.example.com"
2.6 PeerAuthentication
PeerAuthenticationはサービス間のmTLSポリシーを定義します。
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
# メッシュ全体にSTRICT mTLSを適用
mtls:
mode: STRICT
---
# 特定のネームスペースにPERMISSIVEモード
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: legacy-compat
namespace: legacy-apps
spec:
mtls:
mode: PERMISSIVE
2.7 AuthorizationPolicy
AuthorizationPolicyはサービス間のアクセス制御を定義します。
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: reviews-viewer
namespace: default
spec:
selector:
matchLabels:
app: reviews
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/productpage"]
to:
- operation:
methods: ["GET"]
paths: ["/reviews/*"]
3. Linkerd深掘り
3.1 Linkerdアーキテクチャ概要
Linkerdは軽量さとシンプルさを追求するService Meshです。Buoyantが開発し、CNCFの卒業プロジェクトです。
# Linkerd CLIインストール
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | sh
export PATH=$HOME/.linkerd2/bin:$PATH
# 事前チェック
linkerd check --pre
# インストール
linkerd install --crds | kubectl apply -f -
linkerd install | kubectl apply -f -
# 検証
linkerd check
# Viz拡張(ダッシュボード + メトリクス)
linkerd viz install | kubectl apply -f -
3.2 linkerd2-proxy: Rustで書かれたマイクロプロキシ
Linkerdの主要な差別化要因はデータプレーンプロキシです。linkerd2-proxyはRustで書かれており、以下の利点があります。
パフォーマンス比較(linkerd2-proxy vs Envoy)
========================================
メモリ使用量: ~20MB vs ~50-100MB
P99レイテンシ: ~1ms追加 vs ~2-5ms追加
バイナリサイズ: ~13MB vs ~50MB
セキュリティ: Rustのメモリ安全性保証
機能範囲: Service Mesh専用 vs 汎用プロキシ
linkerd2-proxyはService Meshに必要な機能のみを実装することで軽量化を実現しています。Envoyのような汎用プロキシではないため、Wasm拡張などの機能はありませんが、コア機能では優れた性能を発揮します。
3.3 ServiceProfile
LinkerdのServiceProfileはサービスごとのルーティングと可観測性設定を定義します。
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
name: webapp.default.svc.cluster.local
namespace: default
spec:
routes:
- name: GET /api/users
condition:
method: GET
pathRegex: /api/users
responseClasses:
- condition:
status:
min: 500
max: 599
isFailure: true
- name: POST /api/orders
condition:
method: POST
pathRegex: /api/orders
isRetryable: true
timeout: 10s
3.4 TrafficSplit(SMI)
LinkerdはSMI(Service Mesh Interface)標準を使用してトラフィック分割を実装します。
apiVersion: split.smi-spec.io/v1alpha4
kind: TrafficSplit
metadata:
name: webapp-split
namespace: default
spec:
service: webapp
backends:
- service: webapp-v1
weight: 900
- service: webapp-v2
weight: 100
3.5 Linkerdマルチクラスター
Linkerdはマルチクラスター通信をネイティブでサポートしています。
# マルチクラスター拡張のインストール
linkerd multicluster install | kubectl apply -f -
# リモートクラスターの接続
linkerd multicluster link --cluster-name=west \
--api-server-address="https://west.example.com:6443" | \
kubectl apply -f -
# サービスミラーリングの確認
linkerd multicluster gateways
4. Istio vs Linkerd 詳細比較
| 比較項目 | Istio | Linkerd |
|---|---|---|
| データプレーンプロキシ | Envoy (C++) | linkerd2-proxy (Rust) |
| メモリオーバーヘッド(Pod当たり) | 50-100MB | 10-20MB |
| P99レイテンシ追加 | 2-5ms | 0.5-1ms |
| インストール複雑度 | 高い(様々なプロファイル) | 低い(単一コマンド) |
| CRD数 | 50以上 | 10以下 |
| 学習曲線 | 急峻 | 緩やか |
| トラフィック管理 | 非常に豊富(VirtualService) | 基本的(ServiceProfile) |
| セキュリティポリシー | 詳細なRBAC(AuthorizationPolicy) | 基本的なmTLS + Server/Authorization |
| プロトコルサポート | HTTP, gRPC, TCP, WebSocket | HTTP, gRPC, TCP |
| Wasm拡張 | サポート | 非サポート |
| マルチクラスター | サポート(複雑) | サポート(比較的シンプル) |
| Ambient Mesh | サポート(サイドカーなしモード) | 該当なし |
| Gateway API | 完全サポート | 部分サポート |
| コミュニティ規模 | 非常に大きい(CNCF卒業) | 大きい(CNCF卒業) |
| 運用複雑度 | 高い | 低い |
| 適した環境 | 大規模、複雑なポリシー | 小中規模、シンプルさ重視 |
選択基準のまとめ
Istioを選ぶべき場合:
- 詳細なトラフィック管理が必要(重み付きルーティング、フォールトインジェクション、トラフィックミラーリング)
- 複雑なセキュリティポリシーが必要(JWT検証、外部認可)
- Wasmベースの拡張プラグインが必要
- Ambient Mesh(サイドカーなしモード)を使用したい
Linkerdを選ぶべき場合:
- リソースオーバーヘッドを最小化したい
- 迅速な導入とシンプルな運用を望む
- コア機能(mTLS、メトリクス、リトライ)で十分
- 運用チームの規模が小さい
5. mTLS(相互TLS)
5.1 mTLSの仕組み
Service MeshにおけるmTLSはサービス間通信を自動的に暗号化します。
サービスA(クライアント) サービスB(サーバー)
| |
|-- ClientHello -----------> |
|<- ServerHello + サーバー証明書 |
|-- クライアント証明書 -------> |
|<- 証明書検証完了 ----------- |
| |
|<=== 暗号化通信 ============>|
通常のTLSとの違い: mTLSでは双方が証明書を提示・検証するため、サーバーもクライアントの身元を確認できます。
5.2 SPIFFE IDフレームワーク
IstioとLinkerdの両方がSPIFFE(Secure Production Identity Framework For Everyone)標準を使用します。
SPIFFE ID形式:
spiffe://cluster.local/ns/NAMESPACE/sa/SERVICE_ACCOUNT
例:
spiffe://cluster.local/ns/production/sa/frontend
spiffe://cluster.local/ns/production/sa/backend-api
SPIFFE IDはKubernetesのServiceAccountにマッピングされ、Podの身元をネットワークレベルで証明します。
5.3 証明書の自動ローテーション
# Istio: 証明書有効期間の設定(MeshConfig)
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
defaultConfig:
# ワークロード証明書のデフォルトは24時間
# proxyMetadataでカスタマイズ可能
certificates: []
values:
pilot:
env:
# 最大証明書有効期間
MAX_WORKLOAD_CERT_TTL: "48h"
# デフォルト証明書有効期間
DEFAULT_WORKLOAD_CERT_TTL: "24h"
Linkerdの証明書管理:
# Trust anchor作成(10年間有効)
step certificate create root.linkerd.cluster.local ca.crt ca.key \
--profile root-ca --no-password --insecure --not-after=87600h
# Issuer証明書作成(48時間有効、自動更新)
step certificate create identity.linkerd.cluster.local issuer.crt issuer.key \
--profile intermediate-ca --not-after=48h --no-password --insecure \
--ca ca.crt --ca-key ca.key
# 証明書でインストール
linkerd install \
--identity-trust-anchors-file ca.crt \
--identity-issuer-certificate-file issuer.crt \
--identity-issuer-key-file issuer.key | kubectl apply -f -
6. トラフィック管理
6.1 カナリアリリース
# Istio - 段階的カナリアデプロイ
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
x-canary-user:
exact: "true"
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
weight: 95
- destination:
host: reviews
subset: v2
weight: 5
Flaggerによる自動カナリア:
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: reviews
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: reviews
service:
port: 9080
analysis:
interval: 1m
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
thresholdRange:
min: 99
interval: 1m
- name: request-duration
thresholdRange:
max: 500
interval: 1m
6.2 トラフィックミラーリング(シャドートラフィック)
本番トラフィックのコピーを新バージョンに送信し、実環境での動作を検証します。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews-mirror
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
mirror:
host: reviews
subset: v2
mirrorPercentage:
value: 100.0
ミラーリングの主な特性:
- ミラーされたトラフィックのレスポンスは破棄(クライアントに影響なし)
Hostヘッダーに-shadowサフィックスが追加- 新バージョンのパフォーマンスとエラー率を実トラフィックで検証可能
6.3 フォールトインジェクション
意図的に障害を注入してシステムの復元力をテストします。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: ratings-fault
spec:
hosts:
- ratings
http:
- fault:
delay:
percentage:
value: 10
fixedDelay: 5s
abort:
percentage:
value: 5
httpStatus: 503
route:
- destination:
host: ratings
6.4 サーキットブレーキング
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews-circuit-breaker
spec:
host: reviews
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
http:
http1MaxPendingRequests: 100
http2MaxRequests: 100
maxRequestsPerConnection: 10
outlierDetection:
consecutive5xxErrors: 3
interval: 10s
baseEjectionTime: 30s
maxEjectionPercent: 30
minHealthPercent: 70
6.5 リトライとタイムアウト
# Istio
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews-retry
spec:
hosts:
- reviews
http:
- timeout: 10s
retries:
attempts: 3
perTryTimeout: 3s
retryOn: 5xx,reset,connect-failure,retriable-4xx
route:
- destination:
host: reviews
# Linkerd ServiceProfile
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
name: reviews.default.svc.cluster.local
spec:
routes:
- name: GET /reviews
condition:
method: GET
pathRegex: /reviews/.*
isRetryable: true
timeout: 10s
7. Observability(可観測性)
7.1 メトリクス(Prometheus)
Service Meshは以下のメトリクスを自動収集します。
ゴールデンシグナル(Golden Signals)
================================
1. レイテンシ: リクエスト処理時間
2. トラフィック: 秒あたりリクエスト数
3. エラー率: 失敗したリクエストの割合
4. 飽和度: リソース使用率
Istio主要メトリクス:
- istio_requests_total: 総リクエスト数(ソース、宛先、レスポンスコード別)
- istio_request_duration_milliseconds: リクエスト所要時間
- istio_request_bytes / istio_response_bytes: リクエスト/レスポンスサイズ
Linkerd主要メトリクス:
- request_total: 総リクエスト数
- response_latency_ms: レスポンスレイテンシ
- tcp_open_total: TCP接続数
# Prometheusスクレイプ設定(Istio)
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
data:
prometheus.yml: |
scrape_configs:
- job_name: 'envoy-stats'
metrics_path: /stats/prometheus
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
7.2 分散トレーシング(Jaeger / Zipkin)
Service Meshはトレーシングヘッダーを自動的に伝播し、リクエストの全経路を追跡します。
# Istioテレメトリ設定
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
tracing:
- providers:
- name: jaeger
randomSamplingPercentage: 10
customTags:
environment:
literal:
value: "production"
重要: アプリケーションは以下のヘッダーを伝播する必要があります(自動生成はされますが、伝播はアプリケーションの責任です)。
伝播すべきトレーシングヘッダー:
- x-request-id
- x-b3-traceid
- x-b3-spanid
- x-b3-parentspanid
- x-b3-sampled
- x-b3-flags
- traceparent (W3C Trace Context)
- tracestate
7.3 Kialiダッシュボード
KialiはIstio専用の可観測性ダッシュボードです。
# Kialiインストール
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.24/samples/addons/kiali.yaml
# ダッシュボードアクセス
istioctl dashboard kiali
Kialiの主な機能:
- サービストポロジーグラフの可視化
- リアルタイムトラフィックフロー監視
- Istio設定の検証とエラー検出
- 分散トレーシング統合
- メトリクスベースのヘルスステータス表示
7.4 Grafanaダッシュボード
# Grafana + 事前構成済みダッシュボードのインストール
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.24/samples/addons/grafana.yaml
# ダッシュボードアクセス
istioctl dashboard grafana
主なダッシュボード:
- Mesh Dashboard: メッシュ全体のトラフィック概要
- Service Dashboard: 個別サービスメトリクス
- Workload Dashboard: ワークロード別詳細情報
- Performance Dashboard: P50/P90/P99レイテンシ
8. Kubernetes Gateway API
8.1 Gateway APIとは
Kubernetes Gateway APIは既存のIngressを置き換える次世代トラフィック管理標準です。ロールベースの設計でインフラ/クラスター/アプリケーション管理者の責任を明確に分離します。
# GatewayClass: インフラ管理者が定義
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio
spec:
controllerName: istio.io/gateway-controller
---
# Gateway: クラスター管理者が定義
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
gatewayClassName: istio
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: bookinfo-tls
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
expose: "true"
---
# HTTPRoute: アプリケーション開発者が定義
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: bookinfo-route
spec:
parentRefs:
- name: bookinfo-gateway
hostnames:
- "bookinfo.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /reviews
backendRefs:
- name: reviews
port: 9080
weight: 90
- name: reviews-v2
port: 9080
weight: 10
8.2 Istio Gateway vs Kubernetes Gateway API
従来のIstioアプローチ:
Gateway + VirtualService + DestinationRule
Kubernetes Gateway APIアプローチ:
GatewayClass + Gateway + HTTPRoute
利点:
- 標準化されたAPI(実装間の移植性)
- ロールベースのアクセス制御
- より良いネームスペース分離
- Istio, Linkerd, Ciliumなどで同じAPIを使用可能
9. Ambient Mesh
9.1 サイドカーの限界
従来のサイドカーアプローチの問題点:
- Pod当たり50-100MBの追加メモリ
- すべてのリクエストにプロキシホップ追加(レイテンシ)
- サイドカー注入のためのPod再起動が必要
- リソースのオーバープロビジョニング
9.2 Ambient Meshアーキテクチャ
IstioのAmbient Meshはサイドカーなしでサービスメッシュを実装する新しいモードです。
従来のサイドカーモード:
+--------------+ +--------------+
| App + Envoy |--->| App + Envoy |
+--------------+ +--------------+
Ambient Meshモード:
+--------------+ +--------------+
| App | | App |
+------+-------+ +-------+------+
| |
+------+--------------------+------+ <-- ztunnel(ノード当たり1つ、L4)
+------------------+---------------+
|
+------+------+ <-- waypointプロキシ(オプション、L7)
| Waypoint |
+-------------+
ztunnel (Zero Trust Tunnel):
- ノード当たり1つのDaemonSetとして実行
- L4機能のみを担当: mTLS、基本認証
- Rustで記述、非常に軽量
- Pod再起動不要
Waypointプロキシ:
- L7機能が必要な場合にのみデプロイ
- ネームスペースまたはサービス単位でデプロイ可能
- Envoyベース、完全なL7機能を提供
# AmbientモードでIstioインストール
istioctl install --set profile=ambient -y
# ネームスペースをAmbientメッシュに追加
kubectl label namespace default istio.io/dataplane-mode=ambient
# Waypointプロキシのデプロイ(L7機能が必要な場合)
istioctl waypoint apply --namespace default --name reviews-waypoint
9.3 Ambient Meshの利点
リソース削減比較(100 Podクラスター基準):
========================================
サイドカーモード Ambientモード
メモリ: 5-10GB追加 200-500MB追加
CPU: かなりのオーバーヘッド 最小限のオーバーヘッド
運用: サイドカー管理 ztunnel DaemonSetのみ管理
アップグレード: Pod再起動必要 ztunnelローリングアップデート
10. セキュリティ深掘り
10.1 RBAC(ロールベースのアクセス制御)
# ネームスペースレベルの拒否ポリシー
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: production
spec:
# ルールが空の場合、すべてのリクエストを拒否
{}
---
# 特定のサービスのみ許可
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-frontend-to-api
namespace: production
spec:
selector:
matchLabels:
app: api-server
action: ALLOW
rules:
- from:
- source:
namespaces: ["production"]
principals: ["cluster.local/ns/production/sa/frontend"]
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/v1/*"]
when:
- key: request.headers[x-api-version]
values: ["v1", "v2"]
10.2 JWT検証
# RequestAuthentication: JWT検証の定義
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: jwt-auth
namespace: production
spec:
selector:
matchLabels:
app: api-server
jwtRules:
- issuer: "https://auth.example.com"
jwksUri: "https://auth.example.com/.well-known/jwks.json"
forwardOriginalToken: true
outputPayloadToHeader: "x-jwt-payload"
---
# JWTクレームに基づく認可
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-jwt
namespace: production
spec:
selector:
matchLabels:
app: api-server
action: ALLOW
rules:
- from:
- source:
requestPrincipals: ["https://auth.example.com/*"]
when:
- key: request.auth.claims[role]
values: ["admin", "editor"]
10.3 外部認可(External Authorization)
# 外部認可サービス連携
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: ext-authz
namespace: production
spec:
selector:
matchLabels:
app: api-server
action: CUSTOM
provider:
name: "opa-ext-authz"
rules:
- to:
- operation:
paths: ["/admin/*"]
# MeshConfigに外部認可プロバイダーを登録
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
extensionProviders:
- name: "opa-ext-authz"
envoyExtAuthzGrpc:
service: "opa.opa-system.svc.cluster.local"
port: 9191
includeRequestBodyInCheck:
maxRequestBytes: 1024
11. 本番運用ベストプラクティス
11.1 リソース制限の設定
# Istioサイドカーリソース制限
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
defaultConfig:
concurrency: 2
values:
global:
proxy:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
11.2 段階的ロールアウト戦略
# ステップ1: PERMISSIVE mTLS(既存トラフィックを許可)
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: PERMISSIVE
EOF
# ステップ2: メトリクス監視(mTLSトラフィック比率を確認)
# istio_requests_totalメトリクスでconnection_security_policyを確認
# ステップ3: STRICT mTLSへ切り替え
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: STRICT
EOF
11.3 デバッグツール
# Istioプロキシステータス確認
istioctl proxy-status
# Envoy設定ダンプ
istioctl proxy-config all POD_NAME -o json
# ルーティングルール確認
istioctl proxy-config route POD_NAME
# クラスター設定確認
istioctl proxy-config cluster POD_NAME
# 分析ツール(設定エラー検出)
istioctl analyze --all-namespaces
# Linkerd診断
linkerd check
linkerd diagnostics proxy-metrics POD_NAME
linkerd viz stat deploy
linkerd viz top deploy/webapp
linkerd viz tap deploy/webapp
11.4 Horizontal Pod Autoscaler連携
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: reviews-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: reviews
minReplicas: 3
maxReplicas: 20
metrics:
- type: Pods
pods:
metric:
name: istio_requests_per_second
target:
type: AverageValue
averageValue: "100"
- type: Pods
pods:
metric:
name: istio_request_duration_milliseconds_p99
target:
type: AverageValue
averageValue: "500"
11.5 アップグレード戦略
# Istioカナリアアップグレード
# 1. 新バージョンのコントロールプレーンをインストール(リビジョンベース)
istioctl install --set revision=1-24-0
# 2. ネームスペースラベル変更で段階的に切り替え
kubectl label namespace default istio.io/rev=1-24-0 --overwrite
# 3. Pod再起動で新プロキシを適用
kubectl rollout restart deployment -n default
# 4. 旧バージョンの削除
istioctl uninstall --revision 1-23-0
12. Service Meshを使うべきでない場合
Service Meshは強力ですが、すべての環境に適しているわけではありません。
使うべきでない状況:
-
サービス数が少ない場合: 5つ以下のサービスなら、Service Meshの複雑性がメリットを上回る可能性があります。
-
チームがKubernetesに不慣れな場合: Service MeshはKubernetesの上に追加される複雑性レイヤーです。
-
リソースが極端に制限されている場合: サイドカープロキシのメモリ/CPUオーバーヘッドを許容できない時。
-
極端な低レイテンシが求められる場合: マイクロ秒単位のレイテンシが重要な高頻度取引(HFT)のような環境。
代替手段の検討:
シンプルなmTLSのみ: cert-manager + サービス自体のTLS
基本的な可観測性: OpenTelemetryの直接計装
シンプルなロードバランシング: Kubernetes Service (ClusterIP)
イングレスのみ: NGINX Ingress ControllerまたはTraefik
ネットワークポリシー: Kubernetes NetworkPolicyまたはCilium
クイズ
Q1: Service Meshのデータプレーンとコントロールプレーンの役割を説明してください。
データプレーン: サイドカープロキシの集合で、実際のサービストラフィックをインターセプトして処理します。mTLS暗号化、ロードバランシング、メトリクス収集、リトライ/タイムアウトなどを実行します。IstioはEnvoy、Linkerdはlinkerd2-proxyを使用します。
コントロールプレーン: データプレーンのプロキシを中央で管理・設定します。サービスディスカバリ、証明書発行、ポリシー配布を担当します。IstioはIstiod、Linkerdはdestination/identity/proxy-injectorコンポーネントで構成されます。
Q2: mTLSと通常のTLSの主な違いは何ですか?
通常のTLSではクライアントのみがサーバーの証明書を検証します。mTLS(相互TLS)では双方が証明書を提示・検証します。
- クライアントがサーバーの証明書を検証(通常のTLSと同じ)
- サーバーもクライアントの証明書を検証(mTLSの追加ステップ)
- これによりサービス間の双方向身元確認が可能
- SPIFFE標準を使用してサービスの身元をKubernetes ServiceAccountにマッピング
Q3: IstioのAmbient Meshが解決する問題とアーキテクチャを説明してください。
解決する問題: 従来のサイドカー方式はPod当たり50-100MBのメモリオーバーヘッド、サイドカー注入のためのPod再起動が必要、すべてのリクエストにプロキシホップが追加されるなどの問題があります。
アーキテクチャ:
- ztunnel: ノード当たり1つのDaemonSetとして実行されるL4プロキシ。Rustで記述され非常に軽量で、mTLSと基本認証のみを担当します。
- Waypointプロキシ: L7機能が必要な場合にのみ選択的にデプロイ。EnvoyベースでVirtualService、トラフィック管理など完全なL7機能を提供します。
100 Podクラスター基準でメモリ使用量が5-10GB(サイドカー)から200-500MB(Ambient)に大幅削減されます。
Q4: IstioとLinkerdのどちらをどのような状況で選ぶべきですか?
Istioを選ぶべき場合:
- 詳細なトラフィック管理が必要(重み付きルーティング、フォールトインジェクション、ミラーリング)
- 複雑なセキュリティポリシー(JWT検証、外部認可、RBAC)
- Wasm拡張プラグインが必要
- Ambient Mesh(サイドカーなしモード)使用
Linkerdを選ぶべき場合:
- リソースオーバーヘッドの最小化(Pod当たり10-20MB)
- 迅速な導入とシンプルな運用
- コア機能(mTLS、メトリクス、リトライ)で十分
- 小規模運用チーム
Q5: Service Meshを導入すべきでない状況はいつですか?
- 5つ以下のサービス: 複雑性がメリットを上回ります
- チームがKubernetesに不慣れ: Service Meshはさらなる複雑性レイヤーです
- 極端なリソース制限: サイドカーのメモリ/CPUオーバーヘッドを許容できない
- 極端な低レイテンシ要件: マイクロ秒単位のレイテンシが重要な環境(HFTなど)
代替手段: cert-manager(mTLS)、OpenTelemetry(可観測性)、Kubernetes NetworkPolicy(ネットワークセキュリティ)、NGINX Ingress(イングレス)
参考資料
현재 단락 (1/817)
マイクロサービスアーキテクチャが普及するにつれ、数十から数百のサービスがネットワークを通じて通信する環境が一般的になりました。この複雑なサービス間通信で、以下のような問題が繰り返し発生します。