LESSON 30分

ストーリー

マイクロサービスアーキテクチャの設計が進んできた。サービス分割、イベント駆動通信、分散トランザクション管理 — しかし佐藤CTOは、まだ重要なピースが残っていると言います。

佐藤CTO
サービスが10個、20個と増えていくと、サービス間の通信管理が爆発的に複雑になる。認証・認可、トラフィック制御、障害検知、可観測性 — これらをすべて各サービスのコードに埋め込むつもりか?
あなた
それは…各チームが同じようなライブラリを個別に実装することになりますね
佐藤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 GatewayIstio, 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を使っていない導入・運用の難易度が極端に上がる
運用チームの成熟度が低い複雑さがさらに増す

主要なサービスメッシュ比較

特性IstioLinkerdConsul Connect
プロキシEnvoylinkerd2-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分