動機
前スレの『さくらのクラウドとサーバレスアーキテクチャ』で書いた以下について説明不足と感じたので、ここで詳しく書いておこうと思います。
「クラウドに移行したもののランニングコストが予測よりずっと高く、期待したように下がらない」という話を時々聞きます。
自治体システム標準化、ガバクラ移行で運用コスト2~4倍に悲鳴「議会に通らない」(有料記事ですが1ページ目のみ無料で閲覧可能)
ガバメントクラウド移行で自治体の年間コストが5.7倍に…計画の重要性
ガバメントクラウド移行で自治体の運用コストは本当に下がるのか?
上記の引用はガバメントクラウドに関するものですが、過去に私が関わった民間企業のwebアプリケーションでも同様の現象が起きていました。この企業で使っていたのもKubernetes(GKE)ですが、「思うようにスケーリングできない」ので無駄にリソースを割り当ててアプリケーションを実行しているという状況でした。
問題点
クラウド上に実装されたアプリケーションで「Dockerコンテナに突っ込んでKubernetesでオーケストレーション」という作りをよく見ますが、webアプリケーションでこれが有効なケースは、実際には一部に限られます。
実際にはこの構成でwebアプリケーションを実装すると、以下の問題が発生します。
- オートスケールを設定しているのに、リクエストの急増でサーバビジーが発生する。
- (上記のように)運用コストが高いケースがある。
原因
クラウドがオンプレミス/レンタルサーバに比べて有利になる要因は、スケーリングの恩恵によるところが大きくなっています。
従来(オンプレミス/レンタルサーバ)では、あらかじめ契約により用意したリソースの中で、それを有効活用できるようにユーザがやりくりしていました。確保されるリソースは契約で変更するのが前提なので、リアルタイムのように迅速な変更はできず、これがリソースの無駄の原因となっていました。
対するクラウドでは、複数のプロジェクト(これには他人のプロジェクトも含みます)にまたがってデータセンター全体の中で、リアルタイムでリソースの割り当てを変更することで、リソースの無駄を削減します。必要なものを、必要な時に、必要なだけ確保します。ここが従来と最も異なる点です。無駄がなくなることによって運用コストも下げられます。
ここまでならKubernetesによるオートスケールでも実現できそうに感じるのですが、実際には一般的なwebアプリケーションでは、そう思いどおりにならないケースが多いようです。
一般的なwebアプリケーションではエンドユーザの操作に従ってクライアントからリクエストが送信され、サーバがそれに答えます。この間はエンドユーザが待っているので短い方が好ましく、一般的には1秒以下、瞬間的に遅くなっても3秒程度が限度とされます。
Kubernetesによるオートスケールはデフォルトでは30秒ごとにCPU負荷を監視して、コンテナ/Pod/ノードをスケーリングします。そのため負荷の変化が起きてからでないとスケーリングは始まりません。負荷を急増させるリクエストがあっても、そのリクエストはすでに処理を開始した後なので、スケーリングの恩恵を受けられません。
またwebアプリケーションのリクエストの一般的な処理時間に比べて、Kubernetesによる負荷監視の間隔はあまりに長いので、適切な監視およびスケーリングを行いきれません。監視間隔を短くすれば改善できるでしょうが、CPU負荷の測定そのものがコンテナに負荷をかけるので、短いのも悪影響があります。
さらにPodの水平スケールは秒単位で終わりますが、ノードのスケールは分単位で時間がかかります。これだけ長いとエンドユーザは待ってくれません。
つまりKubernetesでのオートスケールが有効なのは、リソース要求の変化が比較的ゆっくり(分単位かそれ以上)の場合です。急激に変化する場合は追従しきれません。
解決策
これですべてではなく、解決策の構成の1つが以下です。
webサーバのオートスケールのコントロールをKubernetesではなく、
Knativeで行うことで改善が期待できます。KnativeはKubernetesに替えてサーバレスアーキテクチャに基づいてオーケストレーションを行います。
webサーバの場合はリクエストはイベントとして処理され、リクエスト数がスケーリング指標となるので、CPU負荷に頼らずスケーリングが可能です。リクエストがプラットフォームに届いた時点でスケールアウトの必要性が判断され実行されるので、スケールアウトの要因となったリクエストもスケーリングの恩恵を受けられます。
またCPU負荷監視の間隔がスケーリングに与える影響が少なくなることもあり、負荷の変化に対して迅速なスケーリングが可能となります。
Knativeを利用したApp EngineやCloud Runサービスを使ってみると、ノードのスケールアウトに相当するケースに遭遇しません。ノードについてはプラットフォーム側である程度プールしているものと推測されます。ノードのスケールインは観測できないので、いつ起きているのか不明です。
またKnativeには、複雑なKubernetesの設定を簡略化してくれるという側面もあります。
設計
ユーザが自分でKnativeを組み込むことはまずなく、一般的にはすでにKnativeが組み込まれたPaaSを利用します。Google Cloudでは以下が該当します。
Knativeによるサーバレスアーキテクチャでの実装については、アプリケーション(=コンテナの中身)の設計・実装も従来とは変える必要があります。これはモノシリック構成に替えてマイクロサービス化する程度では対応できません。スケーリングがいつ起きてどこに影響するのかを考慮する必要があります。
具体的にどうすればいいのかは、長くなるのでまた別の記事で。(書くかもしれませんが書かないかもしれません)
例外
論理的に、アクティブユーザ(=同時接続していて操作しているユーザ)が十分多い大規模アプリケーションの場合、各ユーザの操作が平均化されて極端なリクエストの変化が起きにくくなる可能性があります。このような場合はKubernetesによる緩慢なスケーリングでも十分となります。
しかしこれに該当するには相当な規模のアクティブユーザ数が必要なようです。具体的にどの程度の規模が必要かを知るには、私自身もこの業界もまだ経験が足りないようです。toBの規模ではないかもしれません。toCでは「何時から開始」のようなケースでは、緩慢なスケーリングでは一時的に対応できなくなる可能性が高くなります。
またどのようなサービスでも最初は小規模から始まるものなので、ある程度の規模がないと効果がないKubernetesよりKnativeのほうが、損失を抑えながらサービスを立ち上げることができるという利点もあります。
またイベントドリブンではなく、要件や操作方法の工夫によってスケーリングの要求を緩慢なものにできるアプリケーションでは、Kubernetesで十分な性能を発揮できることになります。
まとめ
以下はwebアプリケーション、正確に言えばその中のwebサーバに限った話です。
コンテナの中身については、クラウド以前の古い設計・実装のままでも機能的には動くかもしれませんが、それではKubernetesにせよKnativeにせよ、性能面でクラウドが能力を発揮することはまずないでしょう。
オーケストレーションについては、ここで最適なのはKubernetesではなく、Knativeです。クラウドと同時に登場したサーバレスアーキテクチャこそが、イベントドリブンの場合の本来の使い方だと言えます。
最後に
「従来の設計・実装のままDockerコンテナに突っ込んでKubernetesでオーケストレーション」という例が未だになくならないのは、クラウドの使い方を理解している人が少ないだけでなく、仕事を受注してお金を稼げればいいだけの意識の低い受託開発業者が多く、発注側もこのような技術面での認識が出来ていないということだと思います。
もう少し踏み込んでモノシリックな構成から脱却しマイクロサービスアーキテクチャを取り入れているケースや、DDD(ドメイン駆動設計)を取り入れているケースもあります。これらはコンテナの使い方を意識したものと思われますが、スケーリングを考慮しないなら効果は限定的です。また分割の仕方によっては逆効果となる可能性もあります。
営利目的のサービスの場合は、多少運用コストが高くても売り上げを増やせば利益を確保できます。しかし行政のような直接売り上げを生み出さないアプリケーションの場合、運用コストの増大は危機的な悪影響となります。まして行政の場合は潜在ユーザは多いもののアクティブユーザは僅かと考えられますので、サーバレスアーキテクチャの一択です。
0 件のコメント:
コメントを投稿