Carpe Diem

備忘録。https://github.com/jun06t

マイクロサービスでのSidecarパターンとは何か

概要

マイクロサービス化したシステムを運用する上で出てくる課題を解決するパターンとしてService Meshというものがあります。
このService Meshというものは以下の2つのコンポーネントで構成されます。

  • Data plain
  • Control plain
    • Data plainの管理

このData plainのproxyはSidecarパターンという形で構築します。
今回はそれが生まれた背景などをEnvoyを用いて説明していこうと思います。

Sidecarパターンは何が嬉しいの?

そもそもどういった問題背景から生まれたのかを考えます。

モノリス

最初はシンプルな機能であったため、モノリシックなAPIで十分でした。 f:id:quoll00:20180701011333p:plain

しかし機能が増え、チーム人数も増えたためドメイン毎に機能を分けてマイクロサービス化する事を考えます。
また通信のレイテンシを下げるため、gRPCの導入も考えます。

とりあえず分割したマイクロサービス化

先程のモノリスAPIを機能毎に分けたのが以下です。

f:id:quoll00:20180701004845p:plain

ここでは簡単のため、AliveUserという2つのサービスだけあるとします。
一見サービス毎に分割できてめでたしめでたし、に見えますが、よく考えてみると分割した分、システム的には複雑性が増しています

例えばAliveUserの中でどうやって負荷分散をすればいいのか、などです。
gRPCを使ったメリットがある一方でL4では分散できない問題が起きます。

負荷分散どうする

簡単のためGatewayからUser ServicePodsへの通信のみ考えます。

Front Proxy LB

f:id:quoll00:20180701005235p:plain

前回

christina04.hatenablog.com

で試した例ですね。シンプルにLBとして用意するので分かりやすいです。
一方でデメリットとして

  • LBを経由するのでレイテンシが増える
  • LBにコネクションが集中するので、LB自体のスケール性を考慮する必要がある
  • gRPCではL4のLBは使えない

といったことがあります。

Client Side LB

LBを経由しない方法として、サービスの呼び出し側(Client)がバランシングするという考え方があります。

f:id:quoll00:20180701005245p:plain

ただこの場合User ServiceのPodが増える度に、GatewayはそのIPを検知して設定を更新する必要がありますし、サービスの種類が増える度にアプリケーション側でコードに修正を入れる必要があるのは保守・運用的に辛いところがあります。

それ以外の課題

最初に述べたようにマイクロサービスでは分割した分、システム的には複雑性が増しています
パッと考えるだけでも負荷分散以外に

  • トレーシング
  • メトリクス
  • 通信の暗号化
  • ACL
  • 一部のサービスが落ちた時のCircuit Breaker
  • 自動リトライ

などネットワーク層の問題を考慮する必要があります。
これらをすべてアプリ側で対応するのは非常に大変だという事が分かります。

Sidecarパターン

それらのネットワーク層の課題をアプリケーション側で考えるのでなく、別途Proxyを用意してそちらに責務を持たせようとしたのがSidecarパターンです。

f:id:quoll00:20180701005256p:plain

この図のように先程のClient Side LBで問題になっていた部分をEnvoyが吸収します。

負荷分散以外ものネットワーク層の問題も、すべてSidecarに任せることでアプリケーションはドメインロジックにのみ集中することが可能になります。
ちなみにEnvoyはどうやってUser ServiceのPodのIPを知るかというと、別途Service Discoveryを用意してそこから定期的にチェック・更新することになります。

f:id:quoll00:20180701005347p:plain

KubernetesならHeadless serviceを使いますし、AWSECSならConsulなどを使います

まとめ

マイクロサービスでのSidecarパターンが生まれた背景と、その構成を図示しました。
次回は実際にKubernetes上で上記のシステムを構築します。

ソース