2016年に USENIX Conference で発表された論文「Design patterns for container-based distributed systems」を読んだ.タイトルの通り,コンテナのデザインパターンがまとまっていて,これからコンテナ設計をする人も,既にコンテナを運用している人も,デザインパターンを学べるのは価値があると思う.一部ミスリードをしているかもしれない.
論文も公開されている.
パターン一覧
- Single-container management patterns(コンテナ管理用の単一コンテナパターン)
- Single-node, multi-container application patterns(シングルノードでのマルチコンテナパターン)
- Sidecar pattern(サイドカーパターン)
- Ambassador pattern(アンバサダーパターン)
- Adapter pattern(アダプターパターン)
- Multi-node application patterns(分散システムのためのマルチノードでのパターン)
- Leader election pattern(リーダー選出パターン)
- Work queue pattern(ワークキューパターン)
- Scatter/gather pattern(スキャッター/ギャザーパターン)
Single-container management patterns(コンテナ管理用の単一コンテナパターン)
- コンテナは境界を提供するため,アプリケーションだけではなく,管理用(オーケストレーション)としても使える
- コンテナを止めるときに
SIGKILL
シグナルを送り強制停止するのではなく,SIGTERM
でコンテナの終了処理を実行できるようにする - "upward" : 監視メトリクスやプロファイリング情報やヘルスチェックを取得することができる(コンテナに対する管理)
- "downward" : 優先順位の高いタスクのために,優先順位の低いタスクを終了することができる(コンテナ内部のプロセスに対する管理)
Single-node, multi-container application patterns(シングルノードでのマルチコンテナパターン)
Sidecar pattern(サイドカーパターン)
- メインコンテナを拡張し,強化する
- ウェブサーバがメインコンテナだとすると,ホスト側のディスクを読むログ保存コンテナはサイドカーになる
- 他にも Git リポジトリからコンテンツを取得して,ホスト側に定期的に同期するサイドカーもある
個人的に経験があるのはログ収集用に使う Fluentd コンテナで,まさに同じユースケースと言える.サイドカーが異常になった場合も,メインコンテナに影響しないというのがポイントだと思う.
Ambassador pattern(アンバサダーパターン)
- メインコンテナが外部とコミュニケーションをするときのプロキシになる
- 例えば Memcached プロキシの twemproxy など
- メインコンテナは localhost の Memcached に接続するように見えるけど,実際にはアンバサダーがプロキシをしている
ロードバランサーにも似ていて,外部とコミュニケーションをするという関心事をアンバサダーにオフロードしているのがポイントだと思う.他にも Microservices を構築するときに考える Service Mesh (Envoy / Linkerd) での Circuit Breaker もアンバサダーに分類されるかな?
Adapter pattern(アダプターパターン)
- アンバサダーとは異なり,外部とのインターフェースを標準化する
- システム内の全てのコンテナが同じモニタリングインターフェースを持つ
海外旅行で使う電源変換アダプタのイメージと言える.具体的には Prometheus のようなプル型のモニタリングシステムと相性が良さそう.
(構成図を作った)
Multi-node application patterns(分散システムのためのマルチノードでのパターン)
Leader election pattern(リーダー選出パターン)
- 分散システムのよく知られた課題に「リーダー選出」がある
- 複数のノードに分散したコンテナ同士で通信をする
- リーダー選出の実装は複雑になることが多いので,実装言語を気にせずコンテナを再利用することができる
今まで経験があるのは Consul のリーダー選出(内部的には Paxos?Raft?)ぐらいで,その他は経験がないけど,リーダー選出という複雑な部分をコンテナに押し込めるのはメリットがあると思う.ただし,論文にもあまり詳細は書かれていなかった.
Work queue pattern(ワークキューパターン)
- リクエストを非同期に処理するため,一度キューに入れてからワーカーコンテナで処理をする
- ワーカーコンテナは直接キューに接続するのではなく,コーディネーターコンテナからメッセージを受ける
読んでいるときに「一般的なキューとワーカーの組み合わせと何が違うんだろう?」と疑問だったけど,キューからメッセージを受ける部分もコーディネーターにオフロードすることで,キューの種類が変わっても(例えば Kafka, SQS, ActiveMQ, RabbitMQ など)ワーカーは影響を受けない構造になっていて,納得できた.個人的に1番学びのあるデザインパターンだった.
(構成図を作った)
Scatter/gather pattern(スキャッター/ギャザーパターン)
- ルートノード or 親ノードにリクエストを送る
- そこから子ノードに並行してリクエストをファンアウトする
- 子ノードの結果をマージするマージコンテナもある
Scatter(散布)と Gather(収集)という意味で,具体的な例で言えば MapReduce と同じ構成と言える.
(構成図を作った)
まとめ
- 論文「Design patterns for container-based distributed systems」を読んだ
- 論文などアカデミックな情報源から学べることも多いので,継続的に読んでいきたい
- これからコンテナ設計をする人も,既にコンテナを運用している人も,デザインパターンを学べるのは価値がある
- 最近はコンピュータサイエンスの論文の解説が聞けるポッドキャスト「Misreading Chat」がお気に入りでずっと聞いている
Cloud Computing Concepts, Part 1
Coursera で「Cloud Computing Concepts, Part 1」という講義を受講することができる.これは「分散システム」を学ぶ講義になっているので,興味がある人がいたら是非オススメしたい.僕が受講したときのメモは全て以下の記事にまとめてある.