ストーリー
マイクロサービスアーキテクチャの設計が進んできた。サービス分割、イベント駆動通信、分散トランザクション管理 — しかし佐藤CTOは、まだ重要なピースが残っていると言います。
サービスメッシュとは何か
サービスメッシュ(Service Mesh)とは、マイクロサービス間の通信をインフラストラクチャ層で一元的に管理する仕組みです。各サービスの横に配置されるプロキシ(サイドカー)が、通信の制御・監視・セキュリティを透過的に処理します。
graph TD
subgraph サービスメッシュ
subgraph SA["Service A"]
A1["App Code"]
A2["Sidecar Proxy"]
A1 --> A2
end
subgraph SB["Service B"]
B1["App Code"]
B2["Sidecar Proxy"]
B1 --> B2
end
A2 <-->|"通信"| B2
CP["Control Plane(制御プレーン)<br/>設定管理 / 証明書管理 / ポリシー配信"]
end
CP -.->|"設定配信"| A2
CP -.->|"設定配信"| B2
なぜサービスメッシュが必要か
マイクロサービスが増えると、以下の課題が顕在化します。
| 課題 | 説明 | サービスメッシュなしの対応 |
|---|---|---|
| サービス間認証 | 各サービス間のmTLS通信 | 各サービスに個別実装 |
| トラフィック制御 | カナリアリリース、A/Bテスト | デプロイツールに依存 |
| 障害検知・回復 | サーキットブレーカー、リトライ | アプリケーションコードに埋め込み |
| 可観測性 | 分散トレーシング、メトリクス収集 | 各チームが独自に実装 |
| レート制限 | 過負荷保護 | APIゲートウェイに依存 |
// サービスメッシュなし: 各サービスに横断的関心事が混入する
class OrderService {
async createOrder(dto: CreateOrderDto): Promise<Order> {
// リトライロジック
const result = await retry(
() => this.paymentClient.charge(dto.amount),
{ maxRetries: 3, backoff: 'exponential' }
);
// サーキットブレーカー
if (this.circuitBreaker.isOpen('payment-service')) {
throw new ServiceUnavailableError();
}
// メトリクス記録
this.metrics.recordLatency('payment-service', elapsed);
this.metrics.incrementCounter('orders.created');
// 分散トレーシング
const span = this.tracer.startSpan('create-order');
// ...
span.end();
// 本来のビジネスロジック
return this.orderRepo.save(order);
}
}
// サービスメッシュあり: ビジネスロジックに集中できる
class OrderService {
async createOrder(dto: CreateOrderDto): Promise<Order> {
// リトライ、サーキットブレーカー、メトリクス、トレーシングは
// すべてサイドカープロキシが透過的に処理する
const result = await this.paymentClient.charge(dto.amount);
return this.orderRepo.save(order);
}
}
データプレーンとコントロールプレーン
サービスメッシュはデータプレーンとコントロールプレーンの2層構造で構成されます。
データプレーン(Data Plane)
データプレーンは、各サービスの横に配置されるサイドカープロキシの集合体です。実際のサービス間通信を仲介します。
graph LR
subgraph Pod["Pod(Kubernetes)"]
SC["Service Container<br/>localhost:8080"] --> SP["Sidecar Proxy<br/>(Envoy)<br/>localhost:15001"]
end
SP -->|"外部通信"| EXT["他のサービス"]
データプレーンの責務:
- トラフィックのインターセプトとルーティング
- ロードバランシング
- TLS終端・mTLS実施
- リトライ、タイムアウト、サーキットブレーカー
- メトリクス収集、アクセスログ生成
- 分散トレーシングヘッダーの伝播
コントロールプレーン(Control Plane)
コントロールプレーンは、データプレーン全体を一元的に管理・設定するコンポーネントです。
コントロールプレーンの責務:
- サービスディスカバリ
- プロキシの設定配信
- 証明書(mTLS用)の発行・更新
- ポリシーの定義・配信
- テレメトリデータの集約
graph TD
CP["コントロールプレーン"]
API["設定API → 管理者が設定変更"]
CERT["証明書管理 → mTLS証明書の自動ローテーション"]
DISC["ディスカバリ → サービスエンドポイントの管理"]
POL["ポリシーエンジン → アクセス制御ルールの配信"]
DP["データプレーン(各サイドカープロキシ)"]
CP --> API
CP --> CERT
CP --> DISC
CP --> POL
CP -->|"設定を配信"| DP
サイドカープロキシパターン
サイドカーとは
サイドカーパターンは、メインのアプリケーションコンテナに補助的なコンテナを並行して配置するデプロイパターンです。サービスメッシュでは、このサイドカーとしてプロキシ(通常はEnvoy)を配置します。
# Kubernetes Pod定義の例
apiVersion: v1
kind: Pod
metadata:
name: order-service
spec:
containers:
# メインのアプリケーション
- name: order-service
image: myapp/order-service:v1.2.0
ports:
- containerPort: 8080
# サイドカープロキシ(通常は自動注入される)
- name: istio-proxy
image: docker.io/istio/proxyv2:1.20.0
ports:
- containerPort: 15001
resources:
requests:
cpu: 100m
memory: 128Mi
サイドカーパターンの利点
| 利点 | 説明 |
|---|---|
| 言語非依存 | アプリケーションの実装言語に関係なく機能を提供 |
| 関心の分離 | ネットワーク制御とビジネスロジックを分離 |
| 独立したライフサイクル | プロキシの更新がアプリケーションに影響しない |
| 統一的な制御 | 全サービスに一貫したポリシーを適用 |
サイドカーパターンの注意点
| 注意点 | 説明 |
|---|---|
| レイテンシ増加 | プロキシを経由するため数ミリ秒のオーバーヘッド |
| リソース消費 | 各Podでプロキシコンテナ分のCPU/メモリが必要 |
| 複雑さの増加 | デバッグ時にプロキシの挙動も考慮が必要 |
サービスメッシュの主要機能
1. トラフィック管理
graph TD
T["<b>トラフィック管理</b>"]
T1["リクエストルーティング<br/>ヘッダーベース / 重み付き(カナリア)"]
T2["ロードバランシング<br/>ラウンドロビン / 最小接続数"]
T3["リトライ・タイムアウト"]
T4["サーキットブレーカー"]
T5["フォールトインジェクション<br/>(意図的な障害注入によるテスト)"]
T --> T1
T --> T2
T --> T3
T --> T4
T --> T5
style T fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
2. セキュリティ
graph TD
S["<b>セキュリティ</b>"]
S1["mTLS(相互TLS認証)<br/>サービス間通信の暗号化 / 証明書の自動ローテーション"]
S2["認可ポリシー<br/>サービス間のアクセス制御"]
S3["レート制限"]
S4["セキュリティ監査ログ"]
S --> S1
S --> S2
S --> S3
S --> S4
style S fill:#ffebee,stroke:#c62828,stroke-width:2px
3. 可観測性(Observability)
graph TD
O["<b>可観測性</b>"]
O1["分散トレーシング<br/>リクエストの全経路追跡"]
O2["メトリクス<br/>レイテンシ、エラー率、スループット"]
O3["アクセスログ"]
O4["サービス依存関係の可視化"]
O --> O1
O --> O2
O --> O3
O --> O4
style O fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
サービスメッシュ vs APIゲートウェイ
サービスメッシュとAPIゲートウェイは役割が異なります。
| 観点 | APIゲートウェイ | サービスメッシュ |
|---|---|---|
| 位置 | ネットワークの境界(North-South) | サービス間(East-West) |
| 対象通信 | 外部→内部 | 内部→内部 |
| 主な機能 | 認証、レート制限、APIバージョニング | mTLS、トラフィック制御、可観測性 |
| 設定粒度 | APIエンドポイント単位 | サービス・Pod単位 |
| 典型ツール | Kong, AWS API Gateway | Istio, Linkerd |
graph TD
Client["外部クライアント"]
GW["API Gateway<br/>認証、レート制限、API管理"]
A["Service A"]
B["Service B"]
C["Service C"]
Client -->|"North-South<br/>(南北)通信"| GW
GW --> A
GW --> B
A <-->|"East-West<br/>(東西)通信"| B
B <-->|"East-West<br/>(東西)通信"| C
style GW fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
style A fill:#e8f5e9,stroke:#2e7d32
style B fill:#e8f5e9,stroke:#2e7d32
style C fill:#e8f5e9,stroke:#2e7d32
「APIゲートウェイとサービスメッシュは競合するものではない。役割が違う。多くの本番環境では両方を併用している」 — 佐藤CTO
サービスメッシュの導入タイミング
導入が適切なケース
| 条件 | 理由 |
|---|---|
| サービス数が10以上 | 手動管理が困難になる閾値 |
| 複数チームが独立開発 | 統一的なポリシー適用が必要 |
| 多言語環境 | 言語ごとのライブラリ管理が非現実的 |
| ゼロトラストセキュリティ要件 | mTLSの一括適用 |
| 高度なデプロイ戦略が必要 | カナリア、ブルーグリーン |
導入が時期尚早なケース
| 条件 | 理由 |
|---|---|
| サービス数が5未満 | オーバーヘッドに見合わない |
| 単一チーム開発 | ライブラリでの対応で十分 |
| Kubernetesを使っていない | 導入・運用の難易度が極端に上がる |
| 運用チームの成熟度が低い | 複雑さがさらに増す |
主要なサービスメッシュ比較
| 特性 | Istio | Linkerd | Consul Connect |
|---|---|---|---|
| プロキシ | Envoy | linkerd2-proxy (Rust) | Envoy / Built-in |
| 複雑さ | 高い | 低い | 中程度 |
| 機能の豊富さ | 非常に豊富 | 必要十分 | 豊富 |
| リソース消費 | 高め | 軽量 | 中程度 |
| 学習曲線 | 急峻 | 緩やか | 中程度 |
| Kubernetes統合 | 深い | 深い | 複数プラットフォーム |
| mTLS | 自動 | 自動 | 自動 |
| マルチクラスタ | 対応 | 対応 | 対応(Mesh Gateway) |
| コミュニティ | 大規模(Google/IBM) | 中規模(Buoyant/CNCF) | 大規模(HashiCorp) |
| 推奨ケース | 大規模・高機能要求 | シンプル・低リソース | マルチプラットフォーム |
// サービスメッシュ選定の判断フレームワーク
interface ServiceMeshSelection {
evaluationCriteria: {
teamExperience: 'beginner' | 'intermediate' | 'advanced';
serviceCount: number;
performanceRequirements: 'standard' | 'high' | 'ultra-low-latency';
featureNeeds: 'basic' | 'advanced' | 'enterprise';
platform: 'kubernetes-only' | 'multi-platform';
};
recommendation: (criteria: ServiceMeshSelection['evaluationCriteria']) => string;
}
const recommend = (criteria: ServiceMeshSelection['evaluationCriteria']): string => {
if (criteria.platform === 'multi-platform') return 'Consul Connect';
if (criteria.teamExperience === 'beginner') return 'Linkerd';
if (criteria.featureNeeds === 'enterprise') return 'Istio';
if (criteria.performanceRequirements === 'ultra-low-latency') return 'Linkerd';
return 'Istio'; // デフォルト
};
まとめ
| ポイント | 内容 |
|---|---|
| サービスメッシュの定義 | サービス間通信をインフラ層で一元管理する仕組み |
| 2層構造 | データプレーン(サイドカープロキシ)+ コントロールプレーン |
| 主要機能 | トラフィック管理、セキュリティ(mTLS)、可観測性 |
| vs APIゲートウェイ | APIゲートウェイは南北通信、サービスメッシュは東西通信 |
| 導入タイミング | サービス10以上、多チーム、多言語環境で効果的 |
| 主要選択肢 | Istio(高機能)、Linkerd(軽量)、Consul Connect(マルチプラットフォーム) |
チェックリスト
- サービスメッシュの定義と必要性を説明できる
- データプレーンとコントロールプレーンの役割を説明できる
- サイドカープロキシパターンの利点と注意点を理解した
- サービスメッシュの3つの主要機能を列挙できる
- APIゲートウェイとの違いを説明できる
- 導入タイミングの判断基準を理解した
次のステップへ
サービスメッシュの全体像を掴んだところで、次は最も広く使われているサービスメッシュ実装である「Istio/Envoy」の具体的なアーキテクチャと設定方法を学びます。
推定読了時間: 30分