- Published on
Service Mesh 完全解剖 — Envoy、Istio、Linkerd、Cilium eBPF、Ambient Mesh、xDS/mTLS まで
- Authors

- Name
- Youngju Kim
- @fjvbn20031
はじめに — 「Service Mesh は答えか流行か」
2017 年頃「マイクロサービスをやるなら Service Mesh は必須」という空気があった。2021 年には「Sidecar 1 つにつき 100MB のメモリ、非効率では?」という声が出始め、2023〜2024 年には Istio Ambient Mesh と Cilium の Sidecar-less メッシュが本格登場した。
8 年間で何が起きたのか。本稿では:
- なぜ Service Mesh が必要だったのか
- Envoy の動作原理 — Listener、Filter、Cluster、xDS
- Istio の Control Plane — istiod の役割
- mTLS が自動で機能する仕組み
- Ambient Mesh — Sidecar のない Istio
- Cilium eBPF — カーネルで処理される L7
- Linkerd の Rust Sidecar — 簡潔さの哲学
- 現場での選定基準
1. なぜ Service Mesh が生まれたか
モノリスを 100 個のマイクロサービスに分割すると発生する問題:
- リトライ — 何回、どんなバックオフで?
- タイムアウト — どれだけ待つ?
- サーキットブレーカー — 失敗が続けば早く失敗する
- ロードバランシング — ラウンドロビン? Least request?
- トラフィック分割 — 新バージョンに 10% だけ流す
- mTLS — 認証と暗号化
- 可観測性 — trace ID、遅延ヒストグラム
- 認証認可 — どのサービスが呼べるか
2015〜2017 年は各言語のライブラリ (Netflix Hystrix、Ribbon、Eureka) で解決していた。しかし Go、Python、Node が加わると言語ごとに実装が必要になり、アップグレードには全サービス再デプロイが必要だった。
解答: ネットワークプロキシへ外注
A→B が HTTP/gRPC なら、間にプロキシを挟めば言語に依存せず機能追加できる。2016 年 Lyft が Envoy を OSS 化し、2017 年 Google と IBM が Envoy を Data Plane とする Istio を作った。
2. Envoy — モダンネットワークプロキシの標準
なぜ Envoy か
- C++ 実装 — nginx のように高速だがモダン設計
- HTTP/2 と gRPC ネイティブ
- 動的設定 (xDS) — 再起動なしで変更
- 強力な可観測性 — 統計、ログ、trace が標準
- フィルタチェーン — WASM や Lua で拡張可能
4 つの中核概念
┌─────────────────────────────────────────────────┐
│ Envoy │
│ │
│ ┌─────────┐ ┌──────────────┐ ┌────────┐ │
│ │Listener │ -> │ Filter Chain │ -> │ Cluster│ │
│ └─────────┘ └──────────────┘ └────────┘ │
└─────────────────────────────────────────────────┘
- Listener — 待受ポート (L4)
- Filter Chain — 接続に対する処理
- Cluster — 送信先 (上流サービスの IP:Port)
- Endpoint — Cluster 内の実 IP
フィルタを差し込むことで WAF、Rate Limit、JWT 検証を追加可能。
xDS API — 動的設定の核
Envoy は 5 つのディスカバリサービスから設定を受け取る:
- LDS (Listener)、RDS (Route)、CDS (Cluster)、EDS (Endpoint)、SDS (Secret)
これらを束ねた ADS (Aggregated Discovery Service) を gRPC ストリームで Control Plane から受信する。変更は無停止で反映され、Kubernetes Service や Deployment の変化が即時に伝わる。
3. Istio — 最も広く使われる Service Mesh
Istio 1.0 の複雑性
2018 年の Istio 1.0 は 4 コンポーネント (Pilot、Mixer、Citadel、Galley)。Mixer がリクエスト毎に gRPC 呼び出しを受けて性能ボトルネックになり、1.5 で削除され、機能は Envoy の WASM フィルタへ統合された。
現在の Istio: istiod 1 つ
┌──────────────────────────────────┐
│ istiod │
│ Pilot (xDS) + Citadel + Galley │
└─────────────┬────────────────────┘
│ xDS
▼
Envoy Sidecar
(Pod ごとに 1 つ)
Sidecar 注入の仕組み
Mutating Admission Webhook を使う。
istio-injection=enabledラベルが付いた namespace に Pod を作成- API Server が Istio の Webhook を呼び出す
- Webhook が
istio-proxySidecar コンテナを注入 istio-initinitContainer も追加して iptables ルールを挿入
iptables ルール:
すべての outbound → REDIRECT to 127.0.0.1:15001 (Envoy)
すべての inbound → REDIRECT to 127.0.0.1:15006 (Envoy)
アプリは自分で通信していると思っているが、iptables が透過的に Envoy へ転送する。
VirtualService と DestinationRule
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews
spec:
hosts: [reviews]
http:
- match:
- headers:
user-agent: { regex: ".*Mobile.*" }
route:
- destination: { host: reviews, subset: v2 }
- route:
- destination: { host: reviews, subset: v1 }
weight: 90
- destination: { host: reviews, subset: v2 }
weight: 10
kind: DestinationRule
spec:
host: reviews
trafficPolicy:
connectionPool:
tcp: { maxConnections: 100 }
http: { http1MaxPendingRequests: 10 }
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
subsets:
- name: v1
labels: { version: v1 }
- name: v2
labels: { version: v2 }
4. mTLS — 「全通信が自動暗号化」の原理
証明書フロー
- istiod が自己 CA として動作 (ルート鍵を保持)
- 各 Envoy Sidecar は起動時に CSR を istiod へ送信
- CSR には Pod の Service Account が含まれる
- istiod が検証し署名証明書を返す (通常 24 時間有効)
- Envoy は SDS 経由で定期的に再発行
証明書の SAN に SPIFFE ID が入る:
spiffe://cluster.local/ns/default/sa/reviews
ハンドシェイク
A の Envoy が B の Envoy に接続: TLS ClientHello、B が証明書を提示、A が istiod のルート CA で検証。B も A に証明書を要求 (mTLS の "m" は mutual)。両者が SPIFFE ID を取得し、AuthorizationPolicy が「この SA から別の SA への呼び出しを許可」を強制する。
STRICT と PERMISSIVE
kind: PeerAuthentication
spec:
mtls:
mode: STRICT
本番は STRICT が目標。移行期は PERMISSIVE で平文も許容して段階移行する。
5. Sidecar のコスト
メモリ
Envoy 1 つで 50〜150MB。Pod 1000 個なら Sidecar だけで 100GB。小さなアプリほど比率が悪化する。
起動遅延
initContainer → Sidecar 起動 → xDS 設定取得 → アプリ Ready。2〜3 秒の追加遅延。Job や CronJob で特に問題。
ライフサイクル不一致
アプリは終了したが Sidecar は生存、あるいは逆のケース。Kubernetes 1.28 でネイティブ Sidecar Container が Beta になり解消されつつあるが、メモリ問題は残る。
ダブルホップ
App A → Envoy A → Envoy B → App B。リクエスト毎に 4 回の L7 パース。
デバッグの地獄
503 発生時: App A? Envoy A? ネットワーク? Envoy B? App B? 5 箇所のログを見る必要がある。
6. Ambient Mesh — Istio の Sidecar-less 革命
2022 年発表、2024 年 Beta、2025 年時点で GA。
中核アイデア: L4 と L7 の分離
Ztunnel (Node ごとの L4 プロキシ) — Node ごとに 1 つの Rust 製プロキシ。mTLS、認証、L4 ルーティングを担当。Pod からのトラフィックは iptables/eBPF で Ztunnel へリダイレクト。
Waypoint Proxy (Service ごとの L7 プロキシ) — L7 機能が必要なサービスにのみデプロイされる Envoy。Deployment としてオートスケール可能。
┌──────────────────────────────┐
│ Node │
│ [App Pod] [App Pod] │
│ │ │ │
│ ▼ ▼ │
│ [Ztunnel] (L4 mTLS) │
└──────┼───────────────────────┘
│
▼ (L7 必要時のみ)
[Waypoint Proxy Pod]
▼
[宛先サービス]
長所と短所
長所: メモリ削減、段階的適用 (L4 のみ → Waypoint 追加)、ライフサイクル分離。
短所: 新しい、Waypoint 経由時のホップ増、ツールがまだ成熟していない。
7. Cilium Service Mesh — eBPF でカーネルから
eBPF とは (1 分復習)
eBPF は Linux カーネル内の安全な仮想マシンでバイトコードを実行する技術。ネットワークフック (XDP、TC)、システムコールトレース、プロファイリング、セキュリティなどに使われる。カーネルモジュールや再起動なしで拡張可能。
Cilium の賭け: プロキシをカーネルへ
Pod から出たパケットはユーザスペースプロキシを通らずカーネル eBPF でルーティングされる。kube-proxy も置き換えられる (iptables なし)。L7 ルーティングは Envoy を使うが Node ごとに 1 つだけ。
┌────────────────────────────────┐
│ Node │
│ [App Pod] --- (eBPF hook) │
│ │ │
│ ▼ │
│ Kernel eBPF Program │
│ (L3/L4 policy, LB) │
│ │ │
│ ▼ │
│ [Envoy (per-node, L7 only)] │
└────────────────────────────────┘
性能 (Cilium 自身のベンチマーク)
- Sidecar 比で P99 遅延 2〜3 倍改善
- CPU 使用量 40% 以上削減
- 接続あたりのメモリオーバーヘッドはほぼゼロ
機能
- L3-L7 NetworkPolicy — HTTP メソッド/パスまで検査
- Hubble — flow logs、service map
- Tetragon — ランタイムセキュリティ
8. Linkerd — 簡潔さの哲学
Linkerd 2.0 (2018) から Rust 製軽量プロキシ linkerd2-proxy を使う。
- Envoy ではなく独自プロキシ
- メモリ: 10〜20MB (Envoy の約 1/10)
- 5 つの機能に集中: mTLS、リトライ/タイムアウト、メトリクス、ロードバランシング (EWMA)、サービスプロファイル
哲学: 「Mesh に詰め込みすぎると運用負担になる」。WASM、複雑な CRD を避ける。
対象: マイクロサービス 100 未満、Istio が重い、「mTLS とリトライだけ自動化したい」チーム。
9. 選定ガイド
Service Mesh が必要か?
├── サービス 10 未満 → 不要。ライブラリで十分
├── 単一言語 → 言語ネイティブ RPC ライブラリ
└── 言語混在 + ポリシー複雑 → 候補
どの Mesh?
├── 既に Istio → Ambient への移行検討
├── 大規模 (1000+) + 性能 → Cilium
├── 簡潔さ + Rust 信頼 → Linkerd
└── 豊富な機能 + コミュニティ → Istio (Sidecar または Ambient)
2025 年の現場
- Netflix、Uber、Airbnb — 自社ライブラリ/プロキシ (言語を統制)
- クラウドネイティブスタートアップ — Cilium 急上昇
- エンタープライズ (金融/通信) — Istio 安定志向
- 小チーム — Linkerd もしくは無し
10. 実務チューニング
Connection Pool
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1000
connectTimeout: 5s
http:
http1MaxPendingRequests: 1024
http2MaxRequests: 10000
maxRequestsPerConnection: 10000
Circuit Breaker
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 60s
maxEjectionPercent: 50
50% ルールが重要。さもないと全 Endpoint が排除されてサービス停止する。
リトライ予算
retries:
attempts: 3
perTryTimeout: 2s
retryOn: 5xx,connect-failure,refused-stream
リトライは負荷を増幅する。Circuit Breaker と必ずセットで。
11. 可観測性 — 隠れた贈り物
Service Mesh は自動的に以下を提供する:
istio_requests_total— ソース/宛先/コード別カウンタistio_request_duration_milliseconds— ヒストグラムistio_tcp_sent_bytes_total/received_bytes_total
さらに B3 ヘッダ (x-request-id、x-b3-traceid、x-b3-spanid) を自動伝播。ただし伝播はアプリ側の責務でもあり、途中でヘッダを捨てると trace が切れる。
アクセスログ: Envoy がリクエスト毎に JSON/カスタムで出力。Loki や Elasticsearch に流せば「5xx だけ」抽出できる。
12. 罠とアンチパターン
- STRICT と PERMISSIVE の混在 — デバッグ地獄。namespace 単位で統一する
- Ingress Gateway と Sidecar の混同 — ライフサイクル・チューニングが別
- すべてのサービスへ注入 — Redis/Kafka など stateful には不向き (L7 が無意味、コネクション再利用が破綻)
- Control Plane の誤設定で全体障害 — revision-based canary で段階適用
- WASM フィルタのコスト —
EnvoyFilter+ WASM は数 ms 増加。本番同等の負荷シミュレーション必須
13. 未来 — Service Mesh は消えるか
予測:
- eBPF が Sidecar を代替 — Cilium 路線、すでに現実
- Platform Engineering へ吸収 — ユーザは Mesh を意識せずポリシーを得る
- gRPC クライアントサイド LB の復帰 — アプリが直接 xDS を受ける (Google 内部方式)
- Gateway API 標準化 — GAMMA イニシアチブで CRD 統合
共通点: 「Sidecar Proxy は過渡期の設計だった」という認識。ただし Mesh が解いた問題 (言語中立ポリシー、mTLS 自動化、可観測性) は消えない。実装が進化するだけ。
14. 現場チェックリスト 12
- 本当に必要か 5 回自問
- 新規導入なら Ambient を優先
- CNI 互換性を確認 — Cilium なら Cilium Mesh
- mTLS は PERMISSIVE → STRICT へ段階移行
- リソース requests/limits を必ず設定 — Sidecar OOM はサービス停止
- Telemetry v2 有効化
- Envoy と Istio のバージョン整合
istioctl analyzeを CI に- Gateway は別 NodePool
- アクセスログはサンプリング
- Retry + Circuit Breaker はセット
- アップグレードは revision-based canary
次回予告 — OpenTelemetry で可観測性を締める
Service Mesh は自動でメトリクスと trace を出すが、実運用ではアプリコードとインフラの trace を一本に繋ぐ必要がある。次回は OpenTelemetry の誕生 (OpenTracing + OpenCensus)、Span/Trace/Context Propagation の正確な意味、Collector アーキテクチャ (Receiver/Processor/Exporter)、head と tail サンプリング、3 本柱 (logs + metrics + traces) の統合、プロファイル (Pyroscope/Parca) という第 4 の柱、eBPF 自動計装、OTLP の内部まで。
「可観測性はログ収集ではない。分散システムが自らの状態を説明できるようにする設計哲学である。」