イノベーションの風に吹かれて

山下技術開発事務所 (YAMASHITA Technology & Engineering Office, LLC)

マイクロサービスのコンテナクラスター

先日の白熱塾ではインフラ系のOSSクラスタリングやデリバリパイプラインの系譜について話してきた。「OSSの話じゃない」と言われたので、このブログではまったくOSSのソフトウェアに触れず機能だけを解説することにしてみた。ご参考になれば。

 

Delivery Pipeline

アプリケーションが様々なライブラリーを必要として複雑化している環境で、開発者が編み出した工夫がコンテナだ。開発環境のガバナンスの強い環境では開発管理者が準備したライブラリーに縛られてしまったり、逆にガバナンスの弱い環境では他の開発者に勝手にライブラリーを変更されてしまったりするので、共有する開発マシンへの不満は大きい。サーバーを共有している他の開発者がスケジュールを無視してビルドを始めると全く動かなくなってしまうこともある。そこで開発者は開発マシンの中に自分独自のファイルシステムとリソース領域をを所有できるシステムを開発した。そのOSとライブラリーのスタックに閉じこもってプログラミングをすることで、外からの干渉がない開発テストが可能になった。しかし、このビルドをリリースするのは難しい。本番環境のOS、ライブラリーの依存関係が固定化していたらDEV/UTの環境の作業は無効だからだ。そこで出てくるのがImmutable Infrastructureだ。開発者のUT環境をそのままコンテナイメージ化して、コンテナをデプロイしたらUT環境と全く同じ動作できる冪等性を維持できるように、コンテナ実行環境を整備しておくことで開発環境をそのままリリースすることができる。

f:id:mash-kyam:20200117171416p:plain

コンテナ・クラスターとダイナミックオーケストレーション

コンテナイメージはInfrastructre as Codeであって、Immutable Infrastructureは実行中のサービスに変更を加えることは許されない。実行しているサービスとソースとなっているコードの間に差異が生じるとコードを再デプロイしたときの再現性が失われ冪等性がなくなるからだ。

こうしたことから考えると、コンテナを「負荷が少なく起動が早いサーバーインスタンス」と理解するのは誤りだ。コンテナはビジネスニーズに応じて、Blue-GreenやA/Bテスト、カナリアリリース、サーキットブレーカなどの様々なリリースパターンを実現するためのコードベースのデリバリーバイプラインである。Immutable Infrastructureではテスト済みサーバーをリリースするのではなくテスト済みコードをリリースする。コンテナシステムではリリースされたコードを管理するライブラリ、そのライブラリから実行環境にデプロイする機能、コンテナイメージを認証するセキュリティなどの機能が中心になっているのはそのためだ。

 

NFR Management

コンテナベースのシステムにおける可用性の考え方は、クラウド環境のFailure Based Designに基づいている。クラウド環境は非常に多くのコンポーネントが用いられているので障害に出会う可能性は高い。しかし、クラウド基盤は大規模なスケールを持っているので障害は局所的であることが多く、クラウドに再プロビジョニングを任せれば正常なサービスを得ることができることが多い。コードベースのImmutable Infrastructureを実現していれば、リリース作業を再度起動すれば同じサービスを再開できると考えるのが基本だ。固定的なサーバーをどれだけ長く動かし続けることができるか(MTBF)という視点でSLAの可用性を管理するのではなく、動かなくなったらどれだけ早く回復できるか(MTTR)という自動化の視点で管理するのが望ましい。サービスのメトリクスを管理し、システムのログやインシデントを総合してサービスの健全性を判断し、サービスインスタンスの追加や削除、再デプロイなどを管理するのがクラスター機能だ。VMベースでもコンテナベースでもクラスタリングの機能は提供されるので、適したクラスタリングフレームワークを選択すればよい。サービスメトリクスはアクティブユーザーなどのビジネスメトリクス、APM等からフィードされるパフォーマンスメトリクス、システム監視からフィードされるシステムメトリクスがある。プロバイダー、リージョン、AZにまたがるこれらのメトリクス群とトランザクションコストを総合的に判断して、非機能要件性能の管理を自動化することが求められている。

コンテナベースのクラスターを用いている場合、サービスのデプロイから起動にかかる時間を短縮できる。このことはダイナミックオーケストレーションへの異なる要求を生み出している。十分にチューニングされたコンテナ環境では数十ミリ秒から数百ミリ秒でサービスの起動が可能なので、ユーザーのAPIコールが届いてからサービスの起動をすることも可能だ。もちろんトラヒックのない時にインスタンス数をゼロにしておくことはないが、トラヒックが到着してからサービスの提供環境を変化させる動作が可能になっている。)このことは可用性に関する考え方を大きく変化させる。サービスは動いている状態が安定しているのではなく、動いていない状態が安定しているのだ。ここまで述べてきた通り、コンテナのサービスインスタンスは動いていないことが安定しているので、コンテナのライフサイクルは極力短くします。インスタンスは、現在のインフライトの処理数、総処理数、連続稼働時間などのポリシーでできるだけ短いサイクルでリフレッシュしておくのがよいでしょう。こうしたことを日常的に行うことで緊急時の対応が迅速に行えるようになる。こうしたクラスタリングの様々な機能をパッケージングしたコンテナクラスターのダイナミックオーケストレーションは非機能要件の管理に新しい考え方をもたらしている。

 

Volatile vs. Persistent

アプリケーションにはフロントエンドの揮発性インスタンスとデータを保持する永続化インスタンスが必要です。コンテナクラスター内で動かすフロントエンドのアプリケーションは再デプロイして機能を再開することが前提となっているので、基本的にステートレスであるべきです。ステートレスなアプリケーションは負荷分散装置で並列化することができるため、負荷分散装置がクラスターの入り口に配置されています。負荷分散装置配下のコンテナはクラスター内のプライベートなアドレスを自動的に振られ、コンテナクラスターの発行するサーバー証明書をそれぞれインストールしています。こうしたステートレスなインスタンスは前の節で述べた通り、いつ消滅してもアプリケーションに影響が少ない揮発性のインスタンスです。一方で、トランザクションのセッションや再ロードできないデータセットなどはデータベースやデータストアに永続化しておく必要があります。これらの永続化するインスタンスはデータの保護を中心に考えて負荷分散装置とは異なる実装をします。インメモリーのキャッシュや多地点保存のオブジェクトストレージ、同じくマルチインスタンスのKVSなど永続化の特性によって選択します。

フロントエンドの揮発性インスタンスは、どのような環境でデプロイされても必要な永続化インスタンスの位置を探り当ててサービスとしてバインドすることが必要です。永続化インスタンスとの接続プロファイルにも冪等性のあるバインディングのメカニズムが求められます。負荷分散機能、コンテナ、ライブラリ、デプロイ、モニタリング、永続化サービス、バインディングなどを一つにまとめたアプリケーションクラスターを活用することで、クラウドネイティブな環境を一気に手に入れることもできる。

 

Transaction Control Point

永続化インスタンスを運用する上で、アプリケーションレベルではトランザクションログの保全トランザクションコンペンセーションを適切に設計していることが大切です。フロントエンドでセッション情報を維持することは極力避けたいので、ユーザーの発するトランザクショントランザクションコントロールポイントを設定してトランザクションログを保全するべきです。近年のWEBアプリケーションにはこうした傾向にあるので、フロントエンドではユーザーアクションをログに書き出し、バックエンドのアプリケーションプロセスがログを読み出して永続化処理を行うPublisher-Subscriberのアーキテクチャパターンを選択することがあります。SOA時代のコレオグラフィーというアーキテクチャーパターンに非常に近い考え方です。こうすることで、バックエンドのマイクロサービスはドメイン境界を厳守した個別のデータとトランザクションでの運用が可能になります。アプリケーション障害が発生した場合にはログをベースに、各マイクロサービスにトランザクションごとの処理状況を確認してフォワードリカバリーあるいはロールバックを選択することができます。インフライトのトランザクションのコンペンセーション負荷が高くなりすぎないようにマイクロサービスのトランザクションリカバリーはトランザクションごとに分散して行えることが重要です。