Skip to content

クラウドネイティブ

サービスメッシュとは何か:現代のプラットフォームに必要な理由

サービスメッシュが実際に何をするのか、開発チームの負担をどう軽減するのか、そしてプロキシアーキテクチャがそれをどう実現するかを実務者の視点で解説します。

Todea Engineering

クラウドネイティブ・プラクティス

·8 分で読了
#service-mesh#kubernetes#zero-trust#platform-engineering
サービスメッシュとは何か:現代のプラットフォームに必要な理由

Kubernetes上でマイクロサービスを少し多めに運用しているなら、あなたの開発者たちはおそらくすでにサービスメッシュの半分を再発明してしまっているでしょう。あらゆるHTTPクライアントに埋め込まれたリトライとタイムアウトのロジック。CronJobとスクリプトでかろうじて維持している証明書ローテーション。ベアラートークンで場当たり的に組み立てたサービス間認証。リポジトリごとに散らばるライブラリバージョン、言語ごとの書き方、「あとで直す」ままの設定。

どのチームも同じ問題を少しずつ違うやり方で解いています。サービスメッシュはこうした関心事をアプリケーションコードから取り出し、プラットフォームチームが所有するインフラへと移します。

開発者が持つべきでない責務

モノリスをマイクロサービスに分割すると、それまでプロセス内で起きていたすべてのこと — エラーハンドリング、リトライ、タイムアウト、認証、メトリクス — も一緒に分割されます。メッシュがなければ、すべてのチームが同じパターンを作り直すことになり、たいていは自分たちの言語のイディオムで、しばしば設定を誤り、一貫性を欠いた形になります:

  • リトライとタイムアウトのロジックがすべてのHTTPクライアントに、しばしば誤った設定で
  • TLS証明書の管理が、ヘッダーで回される共有シークレットに頼る形で
  • サービス間認証がAPIトークンで場当たり的に
  • 分散トレーシングの計装がエンドポイントごとに手作業で追加される形で
  • サーキットブレーカーがサービス間でコピー&微改変されている
  • ロードバランシングとリトライ予算がアプリケーションコード全体に散らばっている
  • ネットワークポリシーが誰も触りたがらないIP許可リストとして表現されている

これをすべてのサービス、出荷するすべての言語、そしてそれを保守するすべてのチームに掛け算してみてください。コストは膨大、一貫性は低く、信頼性も損なわれます。

サービスメッシュはこれらの関心事を開発者から取り除きます:

サービスメッシュが開発者の負担を軽減する領域

開発者はビジネスロジックを書きます。メッシュが横断的な配管処理を引き受けます。

仕組み:プロキシアーキテクチャ

どのサービスメッシュも同じ2つのコンポーネントの上に構築されています:

  1. データプレーン: サービス間トラフィックのすべてのバイトを傍受し、mTLSを処理し、ポリシーを適用するネットワークプロキシ。
  2. コントロールプレーン: それらのプロキシを構成し、ワークロードIDを発行し、テレメトリを集約するコントローラー。

メッシュ間で違うのはプロキシがどこで動くかです。主要なモデルは2つあります。

サイドカープロキシ

サイドカーモデルでは、プロキシはすべてのアプリケーションPodの中に追加コンテナとして動作します。Linkerdはデフォルトでこの方式ですし、従来のIstioも同様です。Pod起動時に、initコンテナまたはCNIプラグインのいずれかがiptablesルールをインストールし、PodのインバウンドとアウトバウンドのすべてのTCPトラフィックを透過的にサイドカーへリダイレクトします。

サービスAがb.default.svc.cluster.localを呼び出すとき、Aのアプリケーションコンテナはただ普通にKubernetes ServiceへHTTPリクエストを送ります。iptablesのリダイレクトがそのリクエストをAのサイドカーに流し込み、サイドカーがmTLS、リトライ、タイムアウト、ルーティングを処理してからBのサイドカーへ転送します。Bのサイドカーは認可ポリシーを適用し、メトリクスを記録し、ループバック経由でBへ転送します。

サービスメッシュのプロキシアーキテクチャ

サイドカーレスアーキテクチャ

主なプレイヤーは:

  • Istio ambientモードは、L4トンネル(ztunnel)をノードごとに1つのDaemonSetとして動かし、そのノード上のすべてのPodに対するmTLSを処理します。L7機能(HTTPルーティング、パスベース認可など)は、オプションのwaypointプロキシを名前空間ごとにデプロイする形で追加されます。L7のコストは必要な場所でだけ支払うことになります。

  • Cilium Service MeshはL4のmTLSとポリシーをLinuxカーネル内のeBPFに押し込み、L7の関心事にはノードごとにEnvoyを動かして対処します。

トレードオフは反転します: Podあたりのオーバーヘッドはなく、Pod起動は速く、ワークロードあたりの可動部品も少ない — しかし共有プロキシであるということは、同じノードに同居するワークロード間でテナンシーの懸念が滲み出すということであり、単一サービスのトラフィックをデバッグするにはノード単位のコンポーネントを追って考える必要が出てくるということでもあります。

サイドカーレスのサービスメッシュアーキテクチャ

アプリケーションから見れば、どちらのモデルも同じに見えます: Kubernetes Serviceに普通のHTTPリクエストを投げるだけです。運用者から見れば、アプリケーションコードを1行も変えずに、そのトラフィックのすべてのバイトが認証され、暗号化され、観測可能になり、ポリシーで統治できるようになります。

プラットフォームレベルで得られるもの

適切にデプロイされたサービスメッシュは、アプリケーションの変更なしに次のものを提供します:

  • すべてのサービス間のmTLS: 証明書の発行、ローテーション、失効はメッシュが処理します。アプリチームのリポジトリにPKIコードが入ることはありません。
  • ワークロードID: IPアドレスや共有シークレットではなく、暗号証明書に基づきます。ゼロトラストネットワーキングの土台です。
  • トラフィック管理: リトライ、タイムアウト、サーキットブレーキング、カナリアリリース — すべて設定として宣言できます。
  • 分散トレーシング: すべてのリクエストにトレースIDが自動で伝播されます。
  • 一貫したメトリクス: リクエスト率、エラー率、p50/p95/p99レイテンシ — 計装作業ゼロで、すべてのサービスについて取得できます。
  • マルチクラスターのサービスディスカバリ: クラスターAのサービスが、クラスターBのサービスをまるで隣人のように呼び出せるようになります。

よくある落とし穴

サービスメッシュの導入は予測可能な形で失敗します:

  1. スイッチのように扱う。 インストールをゴールだと考えること。メッシュを動かすところまでは簡単な部分です。本当の投資が必要なのはそこから先 — 運用し、トラストアンカーをローテーションし、リクエストパス上のプロキシ問題をデバッグし、アップグレードに追従し、クラスタが成長するにつれてリソース制限を調整していくこと — です。最初から予算を確保しておかないと、メッシュは棚ざらしになります。
  2. 適合性ではなく機能で選ぶ。 Istio、Linkerd、Consul、Cilium Service Meshはそれぞれまったく異なる運用プロファイルを持ちます。チームが3人なら、機能リストが最も長いメッシュが答えではありません — 運用面を実際に自分たちで持てるメッシュを選んでください。
  3. オブザーバビリティの作業を省く。 サービスメッシュは膨大なテレメトリを生み出します。ダッシュボードとSLOがなければ、そのデータは価値を持ちません。