PaaS基盤「Cloud Foundry V2」のアーキテクチャは、どうなっている?(後編)

2014年5月13日

Publickeyでは2011年10月に開催された「第1回 CloudFoundry輪読会」を基に「PaaS基盤「Cloud Foundry」のアーキテクチャは、どうなっている?」という記事を公開しました。あれから3年半経過した現在、Cloud FoundryはV2へバージョンアップしました。

そして「第18回 Cloud Foundry 輪読会」では、このCloud Foundry V2のアーキテクチャについて解説されました。本記事は、その内容をまとめたものです。

(本記事は「PaaS基盤「Cloud Foundry V2」のアーキテクチャは、どうなっている?(前編)」の続きです)

Cloud Foundry内部のRouterはリクエストを振り分ける

Cloud Foundryにおけるコンポーネントの役割を説明していきましょう。

コンポーネントとは何か。これはつまりアプリケーションで、1つのプロセスです。例えばRouterはGo言語で書かれたアプリケーションで、Health ManagerもGo言語になっています。DEAやCloud ControllerはRubyで書かれています。

これらはただのアプリケーションなので、やろうと思えば1つのVM(仮想マシン)上で動かせますが、一般に実運用を考えると、1コンポーネントずつ1VMで動かすことが多いでしょう。

fig

まずRouterですが、URLによってアクセスを振り分けるコンポーネントです。

fig

api.xxxだったり、dora.xxxだったり、URLを見て振り分けるわけです。ネットワーク機器のルータとは別のものですので注意してください。Cloud FoundryではGoRouterと呼ぶことが多いですね。

fig

なぜRouterはリクエストの振り先を知っているのでしょうか。それはrouter.registerというメッセージの仕組みがあって、DEAやCloud Controllerが「このURLの振り先は実体がここだから転送して」とか「DEAはここだから、こっちに転送して」など、各コンポーネントがRouterに対してあらかじめ情報を送っておくんです。

fig

Routerはオンメモリデータベースを持っていて情報を格納しておき、実際のアクセスと突き合わせて振り先を判断しています。

fig

仮に同じアプリケーションが複数インスタンス合った場合でも、それぞれがデータベースに入っているので、ラウンドロビンで振り分けられるようになっています。ですから同一のURLに複数の振り先があっても大丈夫なようにできています。

fig

Cloud ControllerはAPIの提供、DEAはアプリの実行

Cloud Controllerはいろいろ機能がありすぎて説明が面倒くさいのですが、基本的にはAPIを提供するコンポーネントだと考えてください。

fig

DEAはユーザーのアプリケーションを動かすためのコンポーネントです。ユーザーアプリケーションはDropletという単位に分けられるので、DEAはDroplet Execution Agentの略となります。

fig

Cloud Foundry V2ではユーザーアプリケーションのステージング作業、例えばRubyではバンドルのインストールとかそういうこともDEAがしています。またDEAはCloud Foundry V2からWarden(ウォードン)というLinuxコンテナを使っています(参考「すごく分かるwarden」。

cf pushでアプリケーションをデプロイする流れを見てみましょう。クライアントからcf pushすると、Cloud Controllerがクライアントからソースコード一式を受け取ります。

fig

次にステージング依頼としてstaging.startという命令でCloud ControllerがDEAにバンドルのインストールを行うように要求し、DEAはその作業をします。

fig

バンドルのインストールが終わった一連のパッケージを「Golden Package」と呼んだりしますが、Cloud Controllerはそれを手元に保存し、それをDEAに「実行して」と要求します。

fig
fig

するとDEAはそれを自分のところのVMで立ち上げます。

fig

さっきcf scale -i 3でインスタンスを3つにしましたが、この命令はCloud Controllerがソース一式を持っているので、dea.startをDEAに依頼をして各DEAがインスタンスを立ち上げるということになっています。

fig

アプリケーションを監視するHealth Manager

Health Managerはユーザーアプリケーションがあるべき姿になてちるかどうか、監視を行うコンポーネントで、最新版はGo言語で書かれていて「hm9000」と呼ばれています。

Health Managerは何をしているのかというと、例えばユーザーアプリケーションのインスタンスが突然死んだら、死んだことをDEAがHealth ManagerにDroplet.exitを送って伝えます。

Cloud Controllerはそれを基にdea.startをかけて、インスタンスが無事復活する、という仕組みです。

fig

Health Managerは状態を見て、怪しかったらCloud Controllerに伝える役割なのです。

それから、たまにcf scaleコマンドでインスタンスを3つ起動したのに、4つ起動されることがあります。それはDEAが重たくてインスタンスの起動に手間取ってタイムアウトして、ほかのDEAに起動を依頼したところ、あとから重くて起動に手間取っていたインスタンスも上がってきてしまった、といった理由です。

fig

DEAはユーザーアプリケーションごとに定期的にハートビートをHealth Managerに送っています。するとハートビートが4つ来ることになるので、多いからなんとかしてとHealth ManagerがCloud Controllerに伝えると、Cloud Controllerがdea.stopで1つ減らすと。

fig

けっこうよく考えられたよくできた仕組みですね。

fig

コンポーネント間の通信を知ろう

Cloud Foundryの内部の通信をもう少しよく見ていきましょう。さっきのこの図ですが。

fig

実はウソです。正確には、こういう仕組みになっています。

fig

あいだに何かいます。これがNATSです。NATSがいろんなメッセージを仲介することになっています。

NATSはPublish/Subscribeモデルの軽量メッセージングシステムです。もともとCloud Foundryの生みの親、Derek Collison氏が作ったもので、彼はいまは違う会社にいますが、Cloud Foundryができたときからある仕組みです。

Cloud FoundryはNATSありきのアーキテクチャになっていると言っても過言ではありません。もともとNATSはRubyで書かれていましたが、いまはこれもGo言語になりました。Cloud Foundryの中心になるところはかなりGo化されてきていますね。

Publish/Subscribeモデル(Pub/Subモデル)は、発信するPublisherがいて、受け取るSubscriberがいて、Suscriberはfoobarというメッセージがきたらほしいです、とNATSに伝えておきます。で、Publisherがfoobarをしゃべると、Subscribeしている人たちに届けられます。情報をほしい人だけにほしい情報が届けられる仕組みです。

fig

これをCloud Foundryがどう使っているかというと、さっきのRouterの例がそうですね。Cloud Controllerから、api.xxxというメッセージはここに届けてほしい、DEAからはdora.xxxというメッセージはこのホストに届けてほしいということを、router.registerという命令でNATSに送ります。

そしてRouterはrouter.registerという命令をSubscribeしているので、無事にこれらのメッセージを受け取れる、という仕組みです。

fig

これでなにがうれしいかというと、Routerを増やしたときにそれぞれのRouterがまったく同じメッセージを受け取れる、というメリットがあることです。

fig

NATSがあれば、Routerを起動すれば、あとはRouterが自分でNATSのrouter.registerをSubscribeすれば受け取れます。だからRouterの起動だけで済みます。

NATSがないと、例えばRouterを起動する前にIPアドレスをデータベースか何かに登録してからRouterを起動し、DEAやCloud Controllerは定期的にデータベースを参照して、ルータが増えたことを検知したら、増えたルータにそれぞれ情報を送る、といったことが必要となります。やらなくてはいけないことが増えてしまいます。

Pub/Subモデルはスケールアウトに強いアーキテクチャになっています。

実際のCloud Foundryの運用ではRouterもDEAもCloud Controllerも複数あるという形態になっています。Health Managerは1つしかいませんが。

fig

Cloud Foundryは自律分散型システム

まとめです。

Cloud FoundryのアーキテクチャはNATSを中心とした疎結合なコンポーネント連係の自律分散型システム。中央で管理している情報はほとんどなくて、それぞれのコンポーネントが勝手にしゃべって成り立っているシステムといえます。また自己修復機能で、アプリケーションが死んだりしても勝手に直ります。

そして単一障害点(SPOF)を排除しています。このあいだまではNATSがSPOFでしたが、NATSのクラスタ化ができるようになったので解決されつつあります。

fig

Cloud Foundry V1とV2ではコアなコンポーネントやおおまかな仕組みは変わっていません。

ただDEAがDEAngになって、Wardenという独自開発のコンテナを使っていて、そこでアプリケーションを動かすようになっています。それからいろんなコンポーネントがGo言語で作られるようになって、だいたい半分がGo言語になっています。

今回は説明していませんが、HerokuのBuildpackが使えるようになりました。

そして大事なことですが、APIの互換性はV1とV2で一切ありません。アーキテクチャは変わってないのに、これはどうなんだとじゃっかん思わないでもないですが。

fig

Cloud Foundry V2のアーキテクチャ

あわせて読みたい

クラウド Cloud Foundry PaaS




タグクラウド

クラウド
AWS / Azure / Google Cloud
クラウドネイティブ / サーバレス
クラウドのシェア / クラウドの障害

コンテナ型仮想化

プログラミング言語
JavaScript / Java / .NET
WebAssembly / Web標準
開発ツール / テスト・品質

アジャイル開発 / スクラム / DevOps

データベース / 機械学習・AI
RDB / NoSQL

ネットワーク / セキュリティ
HTTP / QUIC

OS / Windows / Linux / 仮想化
サーバ / ストレージ / ハードウェア

ITエンジニアの給与・年収 / 働き方

殿堂入り / おもしろ / 編集後記

全てのタグを見る

Blogger in Chief

photo of jniino

Junichi Niino(jniino)
IT系の雑誌編集者、オンラインメディア発行人を経て独立。2009年にPublickeyを開始しました。
詳しいプロフィール

Publickeyの新着情報をチェックしませんか?
Twitterで : @Publickey
Facebookで : Publickeyのページ
RSSリーダーで : Feed

最新記事10本