伊藤直也氏が語る、モダンなWebテクノロジーに共通する傾向とは?(前編) Chef、Docker、MicroservicesからReact、FRPまで。QCon TOkyo 2015
最新のITと関連技術をエンジニアの視点で掘り下げるイベント「QCon Tokyo 2015 Conference」が4月21日に都内で開催されました。
そのセッションの1つとしてKAIZEN platform Inc.の伊藤直也氏が行ったのが、「モダンWebシステム開発」と題して、最近のWebアプリケーションに関する技術に共通する傾向を探った講演です。
ChefやPuppetなどによるInfrastructre as CodeからImmutable Infrastructureなどのインフラ周りからReactなどのフロントエンドにまで共通する考え方とは何か、示唆に富むその内容をダイジェストで紹介します。
モダンWebシステム開発
Kaizen Platform, Inc. 伊藤直也氏。
今日は45分の講演ですが、スライドを90枚作ってしまったので(笑)、ちょっと駆け足になるかもしれませんがお付き合いください。

ここ1年か2年くらいのあいだに、気になったアーキテクチャやパラダイムの概観をして、モダンなアーキテクチャやパラダイムの傾向を見ていきたいと思います。

なぜモダンなアーキテクチャやパラダイムが要求されるかというと、クラウドを使ってシステムを作るのが当たり前になってきたのが大きい要因で、ただクラウドは便利なんですが、壊れやすく、サーバが止まったりすることがある。

クラウドは、サーバが止まってもシステムが止まることを避けるための部品は提供するけど、それをどう組み合わせて、止まらない、スケーラブルなシステムを作るのかは自分で考えてね、となっています。
また、クラウドは縦にスケールするよりも横にサーバを並べて広げていくのが前提になっていて、そういうのを前提にシステムを設計しようとすると、従来通りのシステムやアプリケーションの設計だとうまくいかないこともあると。そこで新しい考え方が必要だねとなってきました。
そこでインフラでは、「Infrastructure as Code」とか「Immutable Infrastructure」とか「コンテナ」とか、そういう話がいろいろでてきました。

アプリケーションだと「Microservices」とか、Facebookが作った「React」とか、少し飛んで「Functional Reactive Programming」とか、この辺が自分のアンテナでは最近話題になっていると思っています。

今日はこれらを見つつ考察してみようということです。
で、結論として何が言いたいかというと、昨今のアーキテクチャやパラダイムの背後にあるテーマは「状態」や「依存関係」といった、これらがシステムが複雑化する原因なんですが、それとどう戦うかについて、よいパラダイムやアーキテクチャにはそこに明確な回答を持っていると。

ただこれがモダンかというと、計算機の歴史はずっとそういうものだ、という反論もあるかもしれませんが、僕はそういう風に見ていますと。
それぞれを見ていきましょう。
Infrastructure as Code
Infrastructure as Codeはここ2年くらいですかね、定着してきたのは。サーバの構成管理を手作業でごりごりやっていくのはつらいので、ChefやPuppet、Ansibleといったプロビジョニングフレームワークを使いましょうと。
ChefやPuppetやAnsibleなどは、「サーバ設定の自動化ツール」と説明されることが多いのですが、それは若干表面的だと思っていて、本質的にはサーバの状態や依存関係を封じ込めるというか管理するものなんですね。
じゃあサーバの状態とは何ですか、というと、例えばある日サーバが納品されたとして、そこにDNSの設定やキャッシュの設定や、このモジュールを入れてあのモジュール入れてとか、いろんな設定をいろんな担当者が入れていくわけです。納品された日と比べると、中身がずいぶん変わっていく。

これがこの文脈で「サーバの状態」と呼ぶものです。
こうやってサーバの状態を手で管理していくと、サーバの状態が複雑になるにつれて状態がどんどん分からなくなってくる。これをChefとかでどうやって解決しているかというと、サーバのあるべき状態をコードとして「宣言的」に記述するわけです。命令的ではなく。

状態をコードとして記述してあげると、あるべき状態がコンピュータに分かるようになるので、そこへシステムを収束させていくことができます。
Chefなどのプロビジョニングフレームワークは、設定の自動化ツールと説明されることが多いのですが、状態を記述できるということが本質的なことで、設定の自動化というのはその結果でしかないと思います。
Infrastructure as codeでは状態や依存関係を記述するのが重要というのと、もうひとつ「冪等性」(べきとうせい)というのがあります。これは簡単に言うと、ある操作を1回行っても複数回行っても、結果は同じであることを保証する、といった意味です。
ChefとかPuppetで、あるコマンドを何度か実行したら別の状態になっちゃった、というのでは困るので、あるコマンドの実行結果はいつも同じであると。だから、これらのツールは冪等性を保証しているわけです。
結果的にこの2つ、状態や依存関係を宣言的に記述することと冪等性を保証することを達成すると、壊れたものはすぐに戻せるし、横に増やすときには簡単に同じ構成が作れる。これがクラウドネイティブな環境にマッチしたから、こういうのが使われるようになったと思っています。
インフラもコードで管理するように
サーバの状態がコードになっているなら、それをGitで管理すればよい、という発想は当然出てきます。Gitに載せればインフラもpull requestやコードレビューで変更できるようになる。
で、コードで書けるのならインフラもテストすればいいじゃんということで、Serverspecというツールが現れて、サーバが期待通りの動作をするかテストできるようになりました。
インフラも、例えばGitHubでNginxのコンフィグレーションを書き換えるコードをpushしてpull requestしてレビューしてマージしたら、CI(Continuous Delivery、継続的デリバリ)と連係して変更が反映される、といったことができますよね、というかやっていますと。

状態を宣言的に記述することで、再現可能性だったりテスタビリティだったり、クラウドへの適合だったり、よりプログラマブルだったり、いろんなメリットが得られますが、これらをざっくりいうとスケーラブルである、ということだと思います。
Immutable Infrastructure
次はImmutable Infrastructureです。
Infrastructre as Codeの文脈で語ったのは「状態」をコードとして記述することでした。しかしImmutable Infrastructureは、状態を管理しない考え方です。
最近ではImmutable Infrastructureはよく語られているので、いまさら聞いてもそんなに不思議ではないと思えますが、最初に状態を管理しないと聞いたときにはびっくりしました。インフラって状態べったりの世界だと思っていたので、それを管理せずにシステムの運用ができるのかと。でもまあ、できるんだよ、という話です。

Immutableというのは、いちどシステムを変更したら上書きでさらに変更を加えるなと、そうではなくて変えるのならそのために新しいものを用意して、古いものは捨てろと。
これを発展させるとできるのが、Blue Green Deploymentというもので、左側が変更前、右が変更後の図です。

あるシステムをアップデートするとき、既存のデプロイツールだと、既存のシステムの上に新しい設定を上書きして再起動します。しかしこれだと新しい設定に不具合があったときに切り戻すのが難しかったり、新しい設定をテストするためにはデプロイするシステムとは別の環境で行わなければならないのでリスクがあったり、という問題があります。
でもBlue Green Deploymentでは、新しい設定のシステムには既存のシステムとは別に新しいシステムを丸ごと用意しておいて、ロードバランサーで切り替えればいいよねと。切り替える前にデプロイしてテストできるし、問題があればロードバランサーを元に戻してすぐに切り戻しできるよねと。
これもクラウドが当たり前になって、プロビジョニングフレームワークも使われるようになった結果、サーバの構成をソフトウェアで一気に人手を介さずにできるようになったので、そうなってくると上書きするより新しいものを立ち上げて切り替える方が早いんじゃないか、という考え方ができるようになって使われ始めているのではないかと思います。 Immutableである、という制約をシステムに加えて運用することで、結果的により捨てやすく、再現しやすいシステムになって、これは壊れやすく、横にスケールする環境により適合しやすくなると。

コンテナ技術
Immutable Infrastructureを支える技術にコンテナがあります。
仮想マシンはソフトウェアでサーバをエミュレートしますが、コンテナはOSの中の軽量なプロセスなので、起動が速いなどのメリットがあります。
このコンテナを使ってImmutable Infrastructureを実現するというのが昨今よく言われていることで、コンテナとしてDockerが話題になっています。
Circle CIのブログでは、コンテナが次世代インフラのスタンダードだと言い切っていて、また、Googleは昨年にGoogleで動いているすべてはコンテナの上で動いていると発表しています。

モダンなインフラにおける状態の扱いには、Infrastructure as Codeで見たように状態を記述して管理可能にする、ということと、Immutable Infrastructureのように、状態を管理しないというと言い過ぎですが、管理しないような考え方をとる方法と、この2つがありますと。

いずれも結果的に、スケーラビリティが得られるということです。
Microservices
次の話題はアプリケーション寄りになって、Microservices(マイクロサービス)です。
これは一連の小さなサービスを組立てて1つのアプリケーションを開発する手法です。独立した小さなコンポーネントがHTTP APIで通信をしますと。

なんでわざわざそんな面倒くさいことをやるかというと、基本的にモノリシックなアプリケーションはシンプルで簡単に動かせていいのですが、ながくやっているとつらいのが分かってきました。
例えばtypoを直すのにサーバ100台で運用していたら、100台の全部をビルド&デプロイし直さなければならないとか、特にBtoBのソフトウェアだとそれほどカジュアルにビルド&デプロイしにくいので、typoを1つ直すのにしばらく待たなければならないとか。
それからモノリシックで内部にいろんな依存関係のあるものを作ると、部分の変更で予想外のところが壊れるとか。あるいは、例えばユーザー認証の部分がボトルネックになっているのでスケールさせたいというときに、モノリシックだとほかの機能も全部入っているので余計な部分までメモリを使っていて、全体をスケールさせるのがつらいとか。

こうした理由で、部分ごとに独立した開発やデプロイサイクルを獲得したいというのがマイクロサービスのおもなモチベーションです。独立した部分を疎結合して、独立して開発、デプロイできるようにしましょうと。
影響は局所化して状態を関係のある部分だけに隠蔽するというのは、特に新しいアプローチではないですが、それをライブラリとかモジュール単位ではなく、ネットワーク上のコンポーネントの1個、サービスの1個として抽象化してしまうのがマイクロサービスです。
で、マイクロサービスとImmutable Infrastructureはけっこう関係があって、マイクロサービス化によってひとつのシステムは単一の役割のコンポーネントになれる。ユーザー認証とか、マイクロサービスにするときには1つのコンポーネントがひとつの役割ぐらいにするとちょうどよくて、一方でコンテナもWebサーバとかコンテナひとつごとにひとつのコンポーネントを動かすようになっています。

すると影響範囲が局所化して独立性の高いコンポーネントとして動かすことができると。

これもスケーラブルにつながっています。
あわせて読みたい
伊藤直也氏が語る、モダンなWebテクノロジーに共通する傾向とは?(後編) Chef、Docker、MicroservicesからReact、FRPまで。QCon TOkyo 2015
≪前の記事
HerokuがDockerのサポートを開始、DockerコンテナがPaaSで運用管理可能に。その仕組みは