Cloud Foundryは、なぜ動くのか
@jacopen Kazuto KusamaNTT Communications !Cloudn PaaSの開発・運用をやっています
最近
質問
はじめに
今回の発表、元々は !• Cloud Foundryのアーキテクチャ概要に軽く触れる • V2で変わったところを中心に、少し深く追ってみる
!
という予定でした
Open Cloud Summit Japan とかで喋りました
が、概要説明だけで100スライド近くになったので、今回は深追いするのは諦めました。 !
なので、かなり入門者向けの内容になっています。 !
深追いはまた次回!
Cloud FoundryにSinatraアプリをデプロイ
$ lsGemfile README.md dora.rb instances.rb logging_service.rb spec stress_testers.rbGemfile.lock config.ru get_instance_cookie_jars.sh log_utils.rb scripts stress vendor!
https://github.com/cloudfoundry/cf-acceptance-tests/tree/master/assets/dora
[23:08] jacopen@cape ~/Project/dora ✘╹◡╹✘ (master) cf push doraCreating app dora in org jacopen / space jacopen-space as admin...OK!Creating route dora.107.22.72.200.xip.io...OK!Binding dora.107.22.72.200.xip.io to dora...OK!Uploading dora...Uploading from: /Users/jacopen/Project/dora1.2M, 36 filesOK!Starting app dora in org jacopen / space jacopen-space as admin...OK(中略)1 of 1 instances running!App started!Showing health and status for app dora in org jacopen / space jacopen-space as admin...OK!requested state: startedinstances: 1/1usage: 256M x 1 instancesurls: dora.107.22.72.200.xip.io! state since cpu memory disk#0 running 2014-04-21 11:09:25 PM 0.0% 72.2M of 256M 0 of 1G
ok![23:09] jacopen@cape ~/Project/dora ✘╹◡╹✘ (master) cf appsGetting apps in org jacopen / space jacopen-space as admin...OK!name requested state instances memory disk urlsdora started 1/1 256M 1G dora.107.22.72.200.xip.io
cf push
この間、CF内では何が行われていたのか?
CFというブラックボックスの謎を解こう
アジェンダ
Cloud Foundryの仕組みを理解するための3章立て !• Cloud Foundryを外から叩いて、中身を推測する • Cloud Foundryの各コンポーネントの役割を知る • Cloud Foundryのコンポーネント間通信を知る
今回やらないこと!
• WardenコンテナやBuildpackなどの解説
• MySQLやPostgresなどのService系の解説
• loggregatorなどの、周辺サービスの解説
では始めましょう
Cloud Foundryを
外から叩いて 中身を推測しよう1
CF_TRACE=true[23:49] jacopen@cape ~/Project/dora ✘╹◡╹✘ export CF_TRACE=true[23:49] jacopen@cape ~/Project/dora ✘╹◡╹✘ cf push dora!REQUEST:GET /v2/spaces/dbf6ed0a-3108-45d8-9c78-a512d5071358/apps?q=name%3Adora&inline-relations-depth=1 HTTP/1.1Host: api.107.22.72.200.xip.ioAccept: application/jsonAuthorization: [PRIVATE DATA HIDDEN]Content-Type: application/jsonUser-Agent: go-cli 6.0.0-90db382 / darwin!!!RESPONSE:HTTP/1.1 200 OKContent-Length: 107Content-Type: application/json;charset=utf-8Date: Mon, 21 Apr 2014 14:49:13 GMTServer: nginxX-Content-Type-Options: nosniffX-Vcap-Request-Id: 18dcd4aefdd000506e49c4b5cf739aaa::65195823-dac9-410a-855a-4ef5ba249198!{ "total_results": 0, "total_pages": 0, "prev_url": null, "next_url": null, "resources": [! ]}Creating app dora in org jacopen / space jacopen-space as admin...
調査の鍵 CF_TRACE=true
CF_TRACE=trueにすると、cf コマンドが
裏で行っているリクエストを見ることができる。
cf pushを覗いてみよう
GET /v2/spaces/dbf6ed0a-3108-45d8-9c78-a512d5071358/apps?q=name%3Adora&inline-relations-depth=1 HTTP/1.1HTTP/1.1 200 OK!POST /v2/apps?async=true HTTP/1.1{"name":"dora","space_guid":"dbf6ed0a-3108-45d8-9c78-a512d5071358"}HTTP/1.1 201 Created!GET /v2/shared_domains HTTP/1.1HTTP/1.1 200 OK!GET /v2/domains?inline-relations-depth=1&q=name%3A107.22.72.200.xip.io HTTP/1.1HTTP/1.1 200 OK!GET /v2/routes?inline-relations-depth=1&q=host%3Adora%3Bdomain_guid%3A524ba14d-4d3f-495f-a2c7-a5ed25a70e81 HTTP/1.1HTTP/1.1 200 OK!POST /v2/routes?async=true&inline-relations-depth=1 HTTP/1.1{"host":"dora","domain_guid":"524ba14d-4d3f-495f-a2c7-a5ed25a70e81","space_guid":"dbf6ed0a-3108-45d8-9c78-a512d5071358"}HTTP/1.1 201 Created!PUT /v2/apps/0e948568-aa90-47e9-a128-9ff3cc680600/routes/ed912294-be29-4013-8b1c-735851acee24 HTTP/1.1HTTP/1.1 201 Created!PUT /v2/apps/0e948568-aa90-47e9-a128-9ff3cc680600/bits?async=true HTTP/1.1Content-Type: multipart/form-data;HTTP/1.1 201 Created!GET /v2/jobs/6dd46fe7-40b0-41d1-94aa-dd2ee80fd3b2 HTTP/1.1HTTP/1.1 200 OK(queued)!GET /v2/jobs/6dd46fe7-40b0-41d1-94aa-dd2ee80fd3b2 HTTP/1.1HTTP/1.1 200 OK(finished)!CONNECTING TO WEBSOCKET: wss://loggregator.107.22.72.200.xip.io:443/tail/?app=0e948568-aa90-47e9-a128-9ff3cc680600!PUT /v2/apps/0e948568-aa90-47e9-a128-9ff3cc680600?async=true&inline-relations-depth=1 HTTP/1.1{"state":"STARTED"}!GET /v2/apps/0e948568-aa90-47e9-a128-9ff3cc680600/instances HTTP/1.1HTTP/1.1 400 Bad Request{"code":170002,"description":"App has not finished staging","error_code":"CF-NotStaged"}!GET /v2/apps/0e948568-aa90-47e9-a128-9ff3cc680600/instances HTTP/1.1
api.107.22.72.200.xip.io と何かやりとりしてる
分かったこと
cf push
Cloud Foundryは、APIを提供している
APIを提供してくれる何か
cf push
cf pushは、APIをいろいろ叩いてデプロイする
APIを提供してくれる何か
GET xxxx
PUT xxxx
POST xxxx
GET xxxx
アプリを動かす何か
アクセス先を調べよう
API
api.107.22.72.200.xip.io
Application
dora.107.22.72.200.xip.io
あれ?
APIも、Appも、同じIPアドレス
$ nslookup api.107.22.72.200.xip.ioServer: 192.168.11.1Address: 192.168.11.1#53!Non-authoritative answer:api.107.22.72.200.xip.io canonical name = api.1jkk1uz.xip.io.Name: api.1jkk1uz.xip.ioAddress: 107.22.72.200!$ nslookup dora.107.22.72.200.xip.ioServer: 192.168.11.1Address: 192.168.11.1#53!Non-authoritative answer:dora.107.22.72.200.xip.io canonical name = dora.1jkk1uz.xip.io.Name: dora.1jkk1uz.xip.ioAddress: 107.22.72.200
cf push
アドレスを元にアクセスを分配する何者かが居る
APIを提供してくれる何か
アクセスを分ける 何かブラウザ
アプリを動かす何か
cf scale
$ cf scale -i 3 -m 256M doraScaling app dora in org jacopen / space jacopen-space as admin...OK
cf scaleコマンドで、稼働する「インスタンス数」「メモリサイズ」などを変更できる
cf push
アドレスを元にアクセスを分配する何者かが居る
APIを提供してくれる何か
アクセスを分ける 何かブラウザ
アプリが死ぬとどうなる?
dora/sigterm/KILL
sigterm/KILLで、自分自身のプロセスを終了
ポートが変わった
アプリの死活監視をしている何かが居る
APIを提供してくれる何か
アクセスを分ける 何か
死活 監視
結果
外から見えるCloud Foundry
APIを提供してくれる何か
アクセスを分ける 何か
アプリを動かす何か
死活 監視
Cloud Foundryの中身(の一部)
Cloud Controller
Router
DEA HealthManager
Cloud Foundryにおける
コンポーネントの 役割を知ろう2
コンポーネント=?
Cloud Controller
Router
DEA HealthManager
コンポーネント=アプリケーション
Cloud Controller (Ruby)
Router (Golang)
DEA (Ruby)
HealthManager (Golang)
全コンポーネントを1VMに集約できる
Cloud Controller (Ruby)
Router (Golang)
DEA (Ruby)
HealthManager (Golang)
VM
(一般的に)実運用では、 コンポーネントごとにVMを分ける
Cloud Controller (Ruby)
Router (Golang)
DEA (Ruby)
HealthManager (Golang)
VM
VM
VM VM
それぞれのコンポーネントを見ていこう
Router
Cloud Controller
Router
DEA HealthManager
Routerとは
URLによって、適切なコンポーネントにアクセスを振り分けるL7ロードバランサー(のようなもの)
ネットワーク機器の「ルーター」とは違う点に注意。
実体は、Ubuntu上で動く、Goで書かれたアプリケーション。(Gorouterという)
Cloud Controller
Router
DEA HealthManager
api.107.22.72.200.xip.io
dora.107.22.72.200.xip.io
Cloud Controller
Router
DEA HealthManager
api.107.22.72.200.xip.io
dora.107.22.72.200.xip.io
なぜRouterはリクエストの振り先を知っているのか?
Cloud Controller
Router
DEA HealthManager
router.register
各コンポーネントが、router.registerというメッセージをRouterに送る
api.107.22.72.200.xip.ioは10.244.0.138:9022に送って
dora.107.22.72.200.xip.ioは10.244.0.26:61032に送って
Cloud Controller
Router
DEA HealthManager
router.register
Routerは、収集した情報を元にアクセスを分配する
dora.107.22.72.200.xip.io => 10.244.0.26:61032 api.107.22.72.200.xip.io => 10.244.0.138:9022
api.107.22.72.200.xip.io
dora.107.22.72.200.xip.io
Cloud Controller
Router
DEA HealthManager
router.register
同一URLに複数の振り先でも大丈夫
dora.107.22.72.200.xip.io => 10.244.0.26:61032 dora.107.22.72.200.xip.io => 10.244.0.27:58719 api.107.22.72.200.xip.io => 10.244.0.138:9022 api.107.22.72.200.xip.io => 10.244.0.139:9022
api.107.22.72.200.xip.io
dora.107.22.72.200.xip.io
Cloud Controller
DEA
Cloud Controller
Cloud Controller
Router
DEA HealthManager
Cloud Controllerとは APIを提供するコンポーネント。
!
• cfコマンド等からアプリケーションの受け取り
• DEAに対してアプリの起動・停止の指示
• Service(データベース等)の作成の指示
!
などなど、Cloud Foundry全体に対しての
コントロールを行う。
POST /v2/apps?async=true HTTP/1.1{"name":"dora","space_guid":"dbf6ed0a-3108-45d8-9c78-a512d5071358"}HTTP/1.1 201 Created!GET /v2/shared_domains HTTP/1.1HTTP/1.1 200 OK!GET /v2/domains?inline-relations-depth=1&q=name%3A107.22.72.200.xip.io HTTP/1.1HTTP/1.1 200 OK!GET /v2/routes?inline-relations-depth=1&q=host%3Adora%3Bdomain_guid%3A524ba14d-4d3f-495f-a2c7-a5ed25a70e81 HTTP/1.1HTTP/1.1 200 OK!POST /v2/routes?async=true&inline-relations-depth=1 HTTP/1.1{"host":"dora","domain_guid":"524ba14d-4d3f-495f-a2c7-a5ed25a70e81","space_guid":"dbf6ed0a-3108-45d8-9c78-a512d5071358"}HTTP/1.1 201 Created!PUT /v2/apps/0e948568-aa90-47e9-a128-9ff3cc680600/routes/ed912294-be29-4013-8b1c-735851acee24 HTTP/1.1HTTP/1.1 201 Created!PUT /v2/apps/0e948568-aa90-47e9-a128-9ff3cc680600/bits?async=true HTTP/1.1Content-Type: multipart/form-data;HTTP/1.1 201 Created!GET /v2/jobs/6dd46fe7-40b0-41d1-94aa-dd2ee80fd3b2 HTTP/1.1HTTP/1.1 200 OK(queued)!GET /v2/jobs/6dd46fe7-40b0-41d1-94aa-dd2ee80fd3b2 HTTP/1.1HTTP/1.1 200 OK(finished)!CONNECTING TO WEBSOCKET: wss://loggregator.107.22.72.200.xip.io:443/tail/?app=0e948568-aa90-47e9-a128-9ff3cc680600!PUT /v2/apps/0e948568-aa90-47e9-a128-9ff3cc680600?async=true&inline-relations-depth=1 HTTP/1.1{"state":"STARTED"}!GET /v2/apps/0e948568-aa90-47e9-a128-9ff3cc680600/instances HTTP/1.1HTTP/1.1 400 Bad Request{"code":170002,"description":"App has not finished staging","error_code":"CF-NotStaged"}!GET /v2/apps/0e948568-aa90-47e9-a128-9ff3cc680600/instances HTTP/1.1
⇐appの作成⇐domainの取得
⇐routesの確認⇐routesの作成⇐appとroutesの紐付け⇐ソースのアップロード
⇐appを起動
DEA
Cloud Controller
Router
DEA HealthManager
DEAとは ユーザーアプリを動かすためのコンポーネント。
Droplet Execution Agentの略。
!
CF v2では、ユーザーアプリのStaging作業(Rubyのbundle installなど)も担当する。
!
DEAはWardenというLinuxコンテナを使い、ユーザーアプリを動かす(が、今回は触れない)
Clientからのソース受け取り
Cloud Controller
Router
DEA HealthManager
cf push
Gemfile lib/ bin/ config.ru app.rb
Staging依頼 (staging.start)
Cloud Controller
Router
DEA HealthManager
cf push
Gemfile lib/ bin/ config.ru app.rb
Gemfile Gemfile.lock vendor/ lib/ bin/ config.ru
Golden Packageの保存
Cloud Controller
Router
DEA HealthManager
cf push
Gemfile Gemfile.lock vendor/ lib/ bin/ config.ru
Start依頼 (dea.start)
Cloud Controller
Router
DEA HealthManager
cf push
Gemfile Gemfile.lock vendor/ lib/ bin/ config.ru
Gemfile Gemfile.lock vendor/ lib/ bin/ config.ru
Start依頼 (dea.start)
Cloud Controller
Router
DEA HealthManager
cf push
Gemfile Gemfile.lock vendor/ lib/ bin/ config.ru
Cloud Controller
Router
DEA HealthManager
cf scale -i 3
Gemfile Gemfile.lock vendor/ lib/ bin/ config.ru
DEA
Start依頼 (dea.start)
Cloud Controller
Router
DEA HealthManager
cf scale -i 3
Gemfile Gemfile.lock vendor/ lib/ bin/ config.ru
DEA
Start依頼 (dea.start)
Cloud Controller
Router
DEA HealthManager
cf scale -i 3
Gemfile Gemfile.lock vendor/ lib/ bin/ config.ru
DEA
Health Manager
Cloud Controller
Router
DEA HealthManager
DEA
Health Managerとは !
ユーザーアプリが、「あるべき姿」になっているかどうか、監視を行うコンポーネント。 !
最新版は、Goで書かれた「hm9000」
インスタンスの突然死
Cloud Controller
Router
DEA HealthManager
DEA
droplet.exited
Cloud Controller
Router
DEA HealthManager
DEA
hm9000.start
Cloud Controller
Router
DEA HealthManager
DEA
dea.start
Cloud Controller
Router
DEA HealthManager
DEA
dea.start
Cloud Controller
Router
DEA HealthManager
DEA
何故かインスタンスが多い場合
Cloud Controller
Router
DEA HealthManager
DEA
dea.heartbeat
Cloud Controller
Router
DEA HealthManager
DEA3インスタンスのはずなのに、4つ来た・・・
hm9000.stop
Cloud Controller
Router
DEA HealthManager
DEA
dea.stop
Cloud Controller
Router
DEA HealthManager
DEA
dea.stop
Cloud Controller
Router
DEA HealthManager
DEA
それぞれの関係、分かりましたか?
Cloud Controller
Router
DEA HealthManager
内部通信
外部からのアクセス
Cloud Foundryにおける
コンポーネント間 通信を知ろう3
さっきのこの図
Cloud Controller
Router
DEA HealthManager
内部通信
外部からのアクセス
Cloud Controller
Router
DEA HealthManager
NATS
NATSとは !
Publish-Subscribeモデルの軽量メッセージングシステム
!
Cloud Foundryの生みの親、Derek Collison氏が開発。
Cloud Foundry登場時から存在する、アーキテクチャの
キモになるシステム。 !
元々はRubyで、EventMachineを使って実装されていた。
現在はGoで実装された、gnatsdになっている
Publish-Subscribeモデル
Publisher Subscriber
NATS
Subject: foo.bar
Subject: foo.bar
Publish-Subscribeモデル
Publisher Subscriber
NATS
Subject: foo.bar{“message”: “hogefuga”}
{“message”: “hogefuga”}
{“message”: “hogefuga”}
Publish-Subscribeモデル
Publisher Subscriber
NATS
Cloud Controller
DEA
Router
Subject: router.register {“host":"10.244.0.138","port":9022,"uris":
["api.107.22.72.200.xip.io"]}
Subject: router.register {“host":"10.244.0.111","port":37902,"uris":
["dora.107.22.72.200.xip.io"]}
全Subscriberが同じメッセージを受け取れる
NATS
Cloud Controller
DEA
Router
Subject: router.register {“host":"10.244.0.138","port":9022,"uris":
["api.107.22.72.200.xip.io"]}
Subject: router.register {“host":"10.244.0.111","port":37902,"uris":
["dora.107.22.72.200.xip.io"]}
Router
Router
Publisher Subscriber
もしNATSが無かったら・・・
NATSあり 直接通信
1.Routerを起動
2.Routerはrouter.registerをsubscribe
1.新Routerを管理DBに登録
2.Routerを起動
3.DEA, CCは管理DBを参照し、Routerリストを取得
4.各Routerに対してメッセージ送信
Cloud Controller
Router
DEA HealthManager
NATSRouter
Router
Cloud Controller
DEA
DEA
DEA
Cloud Controller
Cloud Controller
Cloud Foundryのアーキテクチャ !
• NATSを中心とした、疎結合なコンポーネント間連携
• スケールしやすい! • 自律分散型システム
• 管理する情報は必要最低限 • セルフヒーリング
• 要は勝手に治る
• SPoF(単一障害点)は排除
• ただし最近までのNATSを除く
Cloud Foundry V1と 変わってない?
CF v1 と v2 の違い
• 大まかなアーキテクチャは変わっていない
• DEAがDEAngになり、WardenというLinuxコンテナでアプリを動かすように
• いろんなコンポーネントがGoに書き換えられた
• HerokuのBuildpackが使えるように
• APIの互換性は一切無し!
次回はもうちょっと踏み込んだ内容をやるよ