Consul の文脈で出てきた Sidecar Proxy なんかは Sidecar Pattern に あてはまります。ぼく自身、このあたりの知識があまりないので、初歩的な知識を得たいと思い、以下の論文を読んでみました。
Google が出したこの論文では、Container が分散システムにおけるデザインパターンにどう位置付けられていっているのかという話と、 これまでに出てきたデザインパターンを以下の 3 つの種類に分けて説明しています。
- Single-container management patterns
- Single-node, multi-container application patterns
- Multi-node application pattern
- コンテナと分散システムのデザインパターン
- Single-container management patterns
- Single-node, multi-container application patterns
- Multi-node application pattern
- 所感
- 合わせて読みたい
コンテナと分散システムのデザインパターン
デザインパターンとしては OOP のものが有名ですが、共通的な問題へのアプローチを体系化することで、デザインパターンは
- 経験の浅い人であっても品質の良い設計・コードが書けるようになり
- また、それらの知見を封じ込めた再利用可能なライブラリ
をもたらしてきました。
一方、分散システムにおいては MapReduce といったパターンも出てきていましたが、Apache Hadoop 等の限定されたところにしか 適用がなかなかなされなかったという状況があります。 そこで出てきたのがコンテナで、これがまさに OOP における Object のように、分散システムにおけるデザインパターンの主役になるんじゃないかという話になっています。
Single-container management patterns
コンテナというのは OOP における Object のようなもので、きちんとした境界を定義するものであるから、管理用にもきちんとインタフェースを提供しようね、という内容だと受け取りました。
管理用に監視メトリクスやログの情報を提供する API を設けたり、適切なライフサイクルを定義し管理用の API を設けて「契約」として定義すれば、ディベロッパはその「契約」にのみ頼って アプリが書けるようになるよね、と。
ちょっと抽象的ではありますが、例えば、
- Kubernetes においての、
SIGTERM の前に SIGKILLSIGKILL の前に SIGTERM を送って数秒待つような仕組み- この数秒で、終了処理ができるよね
とかそういうことを言っているようでした。
Single-node, multi-container application patterns
1 ノードに複数コンテナを配置するパターンなのですが、ここで主役を張るのが Sidecar Pattern です。
Sidecar Pattern
Sidecar Pattern は、複数のコンテナを 1 つの単位 (k8s でいう Pods、Nomad でいう task group) の中で動かすパターンです。 メインでアプリ処理を行う main container を拡張、強化するという意味から "Sidecar" という名前が付いています。
具体例としては、
- Web Server の書き出したログを、別コンテナが集約してクラスタストレージに送る
- Web Server が配信するコンテンツを、別コンテナで同期を取る
といった例があります。
1 コンテナでもできることを複数コンテナで実現するメリットは以下の 5 点。
- コンテナはリソース割当の単位になるので、個々の処理に必要なリソースを柔軟に選択できる
- コンテナは packaging の単位であるので、開発上の責任分担がやりやすい
- コンテナは再利用の単位であり、色んなコンテナとの組み合わせが可能
- コンテナは障害を封じこめる境界にもなるので、1 コンテナの障害が他コンテナに伝搬しにくい
- コンテナは deploy の単位であるので、独立して upgrade できる
- ver. が異なってくるので、テストマトリックスはその分複雑になってしまいますが…
基本的にこれらのメリットは、以下のパターンにも適用されます。
Ambassador Pattern
main container の代わりに通信処理を肩代わりしてくれるコンテナを配置するパターンです。Consul Connect でいう Sidecar Proxy なんかがこれに当たるんじゃないでしょうか。
基本的に main container は、localhost 上の ambassadar に通信すれば良く、全体として非常に単純化された view を main container に提供することになります。 ambassador がロードバランスや Circuit break なんかの面倒を見てくれるので、main container 上のアプリのテストは非常に容易になりますし、プロダクション環境と同じ設定でテストが可能です。
また、ambassador 自体も、別のアプリと組み合わせるような再利用が可能です。 通信ライブラリが Container として外出しされたイメージでしょうか。
Adapter Pattern
実装言語が異なる、フレームワークが異なるといった、ヘテロな複数のアプリがある中で、中央の監視システムに共通したインタフェースを提供するパターンです。
アプリに変更無しで、他システムとの連携を行うことができます。
Multi-node application pattern
ここには以下の 3 つが出てきます。
Leader election pattern
リーダー選出って設計も実装も複雑で、個別実装は大変ですし、ライブラリもいくつか出てはいるんですがライブラリを組込むには実装言語が制約されるという問題があります。
そこで、Leader election のみを専門で行うコンテナを配置することで、アプリはリーダー選出から解放されます。 Leader 選出の開始や状態の確認用に、アプリに Interface を提供する感じです。
Work queue pattern、Scatter/gather pattern
前者は Queue への投入や Queue からの Job の取得といったジョブキューの制御部分、後者については分割統治アルゴリズムにおける問題の割振りや集約といった共通部分を Container で提供するというパターンです。
所感
Sidecar とか Ambassador とかは分かるんですが、Scatter/gather pattern とかを見ると「これまであったボイラープレート的な部分はコンテナに置き換わっていく」ような印象を受けました。 それによって、今までフレームワークが担っていた部分に対して Language-neutral な基盤が提供されるのかなと。
一方で、個人的には分割統治的な部分までコンテナに置き換えるのは結構オーバーテクノロジー感があって、軽量とは言いながらもコンテナ化することによるオーバヘッドは気になりますし、 何より自分の持っている感覚にそぐわないというか、え、それってコンテナが担うところなの?という気持ちがあります。
こうやって老害になってしまうのだろうか。