本記事は英語版ブログで公開された記事の翻訳版です。
クラウドには2種類のアプリがあります。「動くアプリ」と「動かないアプリ」です。動くほうは「 Twelve Factor アプリ」と呼ばれます。 これはクラウド向けに特化して書かれているためクラウドで動作します。動かないほうは「レガシーアプリ」と呼ぶことにします。こちらは従来的なVPSホストで動かすことを前提に設計されています。
残念ながら、現在普及しているアプリのほとんどはレガシーアプリです。クラウドでの運用を想定して書かれていないので、たいていの場合、そのままでは動作しません。 レガシーアプリの例としてはWordPress、Magento、Drupalなどが挙げられます。あなたがクラウドに移行しようと考えている社内アプリも、もしかしたら同類かもしれません。
これはどう解決すべきでしょうか。レガシーアプリをクラウドで動かす方法はあるのでしょうか?
アプローチ
ひとつのアプローチは、レガシーアプリを単一サーバーにデプロイし、必要に応じてスケールアップすることです。 しかし、これでは従来のVPSホスティングと変わりません!それに、万一Amazonがインスタンスをリタイヤ(停止または終了)させでもしたら大打撃です……
やはりアプリそのものを修正してクラウドで動作可能にするほうが、ましなアプローチといえるでしょう。 クラウドで動かせるということは、クラスターに分散できるということです。つまり、サーバーを追加してスケールアウトが可能です。サーバーが障害を起こしても、新しいものと置き換えられます。
しかし、オフザシェルフのレガシーアプリに大きな変更を加えようとすると、事実上そのコードベースをフォークすることになります。 そのために開発者の時間がとられるだけでなく、上流からの変更を絶えず取り込んでいく手間もかかります。もっといいアプローチはないものかと思いますよね。
幸いにも、それはあるんです!
その話に入る前に、少し基礎を説明させてください。いくつかの概念を頭に入れてからのほうが、後の話が分かりやすくなるもので。
問題をもう少し詳しく見てみる
クラウドコンピューティングの基本コンセプトを解説するシリーズ記事から、以下にいくつかかいつまんでご紹介します。
ペットと家畜
従来のVPSモデルでは、サーバーはペットのようなものです。調達すれば高くつき、セットアップは複雑で、交換するにも時間がかかります。 結果として、管理者は1台1台手間暇かけて世話をし、調子が悪くなれば正常に戻るまで修復することになります。
クラウドでは、サーバーは調達費用も安く、構成は朝飯前で、交換するのも簡単です。結果として、家畜の群のように扱うことになります。 1台1台が機能的にまったく同一なので、1台の調子が悪くなれば、他のものと入れ替えるまでです。
レガシーアプリはペットサーバーで動かすことを想定しています。私たちの仕事は、これを家畜サーバーで動くようにすることです。
起動前に構成する、ということ
家畜サーバーはどうしてそんなに簡単に立ち上げられるのでしょうか?それは構成へのアプローチが違うからです。
従来のモデルでは、ペットサーバーは起動した後で構成していくものです。変更は手動で適用し、その数は時とともに増えていきます。
クラウドでは、代替サーバーを一刻でも早く用意する必要があります。人間が新しいマシンを構成するのを待つ暇はありません。 そこで、構成をあらかじめ記述しておきます。そのとおりに構成すれば、クラスター内のどのサーバーもまったく同じになるわけです。
これを実行するのに使われるのが構成管理ツールです。構成は現に動いていて状況に応じて変えられるものではなく、どこかの時点で凍結されたものになります。 そこに何か実質的な変更を加えるごとに、クラスター全体を新しいスナップショットから再デプロイしなければなりません。
つまり、レガシーアプリに凍結された構成を使わせることができれば……
関数、スレッド、プロセスと来たら、 その次は? 家畜だ
ファイルシステムに情報を書き込むのがなぜ悪いのでしょう?
コンピュータープログラム内で共有ステートを扱う方法はいくつもあります。アプリがスレッドを使っているなら、スレッドセーフメモリが使えます。 マルチプロセスモデルを使っているなら、共有パイプ、ファイルシステム、データベースといったIPC(プロセス間通信)が使えます。
では、アプリインスタンスのクラスターなら?アプリを多数のマシン間でクラスター化するのは、プロセスをforkするのに少し似ています。 ただしプロセスはそれぞれ物理的に隔離されたハードウェア上で動作することになります。したがってメモリもIPCメソッドも使えません。ステートはネットワーク間でやりとりする必要があります。
レガシーアプリはどうすればいいのでしょう?ファイルシステムにステートを書き込もうとする処理は、すべてネットワーク呼び出しに置き換えなければいけません。 でないとステートが共有されず、アプリは破綻してしまいます。
シェアード ナッシングとスケーリング
本当にそこまでする必要があるのでしょうか?ファイルシステムも何かに使えないものでしょうか?
使えるといえば使えるのですが、ファイルシステムをクラウドに置くことは大きな危険が伴います。例えば、多くのレガシーアプリは自分自身のファイルを書き換えられると想定しています。 しかしそれを許してしまうと、次にGitリポジトリからデプロイをトリガーしたら、書き換えられた部分がすべて消えてしまいます!
では、解決するにはどのようなアプローチがあるのでしょうか。ひとつの方法は、アプリを単一サーバーでだけ動かすステートフル アプローチです。 デプロイをトリガーすることはできますが、ファイルシステムの面倒を見なければなりません。しかも、すでに説明したように、これではクラウドの利点がほとんど失われてしまいます。
分散ファイルシステムを使うという手もありますが、すると別の問題にぶつかります。一貫性、可用性、分断耐性のどれかを犠牲にしなければならないのです。 アプリがそれを想定して書かれていなければ、いずれトラブルが起きるでしょう。
最善のアプローチは、完全なシェアード ナッシング アーキテクチャにしてしまうことです。ファイルシステムはあくまでローカルステートの一時的な保持にしか使いません。他のものはすべて共有データストアに書き込む必要があります。
アプリを氷漬けにする
では、いったいどういう手が残されているのでしょう。
レガシーアプリはクラウドと互換性がありません。まだクラウドがなかった時代に作られ、その当時から進歩していないのです。 幸い、そうしたアプリを一から書き直す必要はありません。ステートフルなアプリを「だまして」ステートレスな環境で動かす方法があります。
言うなれば、ローカルステートを「凍結」してしまうのです。
まず、アプリのコピーをローカルマシン上で動作させます。次に、標準の管理コンソールを使ってアプリを構成します。プロダクション環境で構成するのと同じように行うのです。プラグインをインストールしたり、構成に調整を加えたり、その他色々。バックグラウンドでは、アプリはファイルシステムにどんどんデータを書き込みます。そういう具合に動くようにできているのですから。
肝心なのはここからです。変更を加え終わったら、そのファイル群をそのままバージョン管理システムへコミットしてしまいます。これでステートは事実上凍結されます。
いったんステートを凍結してしまえば、後はどこでも好きなところにデプロイできます――単一サーバーにでも、サーバー1000台のクラスターにでも。ご自由にお選びください。
危険!危険!(『宇宙家族ロビンソン』風に)
しかし、このアプローチには3つの危険が潜んでいます。
すべての構成は開発環境で済ませなければなりません。ただし、データベースに保持される構成設定を変更する場合、デプロイ後に同じ変更をプロダクション環境で行う必要があります。
凍結したアプリをデプロイした後は、ファイルシステムに変更が生じるような構成の変更(プラグインのインストールなど)は行えません。プロダクション環境によっては、管理者ダッシュボードの一部をロックダウンするなどという対策も考えられます。
アプリの中で、永続的なファイルをプロダクション環境に書き込む可能性がある部分(画像アップロードスクリプトなど)はすべて置き換える必要があります。これを回避する方法はありません。幸い、ほとんどの場合、S3プラグインなどで簡単に置き換えることができます。
おそらくレガシーアプリの管理者にとってはなじみのないワークフローでしょうし、それを強制するのは無理かもしれません。誰かを管理者にする前に、必要なアップグレードやデプロイメント手順を説明しておいたほうがいいでしょう。
まとめ
クラウドの扱い方は、時として直感的とはいえません。しかしこうした新しい概念は大きな力を与えてくれます。フォールトトレランス、高可用性、柔軟なスケーリング、などなど。初めはなじみがない概念も、実践を重ねればじきに慣れてくるものです。そして「ステートレス環境」の基本がのみこめれば、後はその応用の繰り返しです。
皆さんがこの奇妙で新しい世界に慣れる手助けとなるよう、次回からは実際のアプリを例にとって解説しようと思います。手始めに、WordPressを完全なクラウド環境にセットアップする手順を、今回の記事でとりあげたテクニックもまじえて説明する予定です。
あなたはレガシーアプリをクラウドにデプロイさせられた経験はありますか?その時はどういう手直しを加えましたか?下のコメント欄で教えてください!
(翻訳:福嶋美絵子)