cloud foundry v2を、もうちょっと深掘りしよう
DESCRIPTION
Cloud Foundry V2はV1と比べて何が変わったのか。変わった点を深掘りしますTRANSCRIPT
Cloud Foundry V2を、もうちょっと深掘りしよう
@jacopen Kazuto KusamaNTT Communications !Cloudn PaaSの開発・運用をやっています
ワタシハクラウドファウンドリーチョットデキルI can develop Cloud Foundry a little
前回
http://www.slideshare.net/jacopen/cloud-foundry-33851040
前回の要約役割ごとにコンポーネントが分かれている
• APIの提供や、各コンポーネントへ指示出しするCloud Controller
• APIやアプリへのアクセスを分配するRouter
• ユーザーアプリを動かすDEA
• ユーザーアプリの状態監視を行うHealth Manager
Cloud Controller
Router
DEA HealthManager
前回の要約コンポーネント間は、NATSという軽量メッセージングシステムを介して、疎結合に繋がっている。
V1とV2で、大まかなアーキテクチャはあまり変わっていない
Cloud Controller
Router
DEA HealthManager
NATS
じゃあ、変わったところは何よ?
アジェンダ
Cloud Foundry V2を知るための3点 !• Buildpackとは何か • Buildpackとアプリがどう関係して動作するようになるのか
• アプリのセキュリティを担保するWardenとは何か
Cloud Foundry Buildpack1
Cloud Foundry Heroku Buildpack1
Buildpackとは
Herokuが作った、任意の言語やフレームワークを利用できるようにする仕組み
Herokuの場合
$ heroku create myapp -b https://github.com/kr/heroku-buildpack-go.git
Herokuが公式提供していない言語、
この例だとGolangを使えるようになる
CFの場合
$ cf push myapp -b https://github.com/dmikusa-pivotal/cf-php-build-pack.git
CFにおけるbuildpack
• CFのBuildpackは、Herokuの仕様に準拠している •なので、的に基本は互換性があるはず •実際には、HerokuとCFの環境の違い(OS、コンテナ、ネットワークなど)により、動かないHeroku Buildpackも存在する。
Buildpackのしくみ
Buildpackの必須要素
•detect •compile •release
1. detect
detect
• buildpackの実行条件を指定するスクリプト •デプロイされたアプリケーションに対してこの
detectスクリプトを実行し、exit 0ならOK、exit 1ならNGとする。
heroku-buildpack-phpのdetect
#!/usr/bin/env bash!if [[ -f "$1/composer.json" || -f "$1/index.php" ]]; then echo "PHP" && exit 0else exit 1fi
アプリ内にcomposer.json or index.phpがあれば、このbuildpackが使われる
heroku-buildpack-rubyのdetect#!/usr/bin/env ruby!require 'pathname'!if Pathname.new(ARGV.first).join("Gemfile").exist? puts "Ruby" exit 0else puts "no" exit 1end
アプリ内にGemfile あれば、
このbuildpackが使われる
detect
•実行可能であれば、何で書いても良い。heroku-buildpack-phpはbash, heroku-buildpack-rubyはrubyで書かれている。
• detect自体はbashで書いて、その中からpythonスクリプトを呼んでいるような例もある(cf-php-build-pack)
•最終的にexit 0か1を返せば良い
2. compile
compile
•言語の実行環境をセットアップするためのスクリプト。buildpackのキモになる部分。
•名前の通り、実行環境のソースを落としてきてコンパイルする・・・が、実際には時間がかかりすぎるので、予めコンパイル済のバイナリをダウンロードしてくるものが多い。
3. release
release
•実行に必要なメタデータをyamlで返すスクリプト。
#!/bin/sh!cat << EOF---addons: - heroku-postgresql:devdefault_process_types: web: bin/node server.jsEOF
#!/bin/sh!cat << EOF---addons: - heroku-postgresql:devdefault_process_types: web: bin/node server.jsEOF
addon: buildpackが必要とするaddonを記述する。CFでは今の所未対応
default_process_types: アプリケーションの実行コマンドを記述。現在の所、web: のみ対応。
Buildpackを使った
Stagingの仕組み2
CFv2における”Staging”とは
• Golden package Dropletを作る作業。
• Dropletは、実行可能になったアプリケーションの一式
• CFv2では •ユーザーがデプロイしたアプリケーションを、 • Buildpackの記述に従って処理し、
• Dropletを作る
までの流れを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
1.cf pushで、ユーザーはCloud Controllerにアプリケーションをアップロードする
2.Cloud Controllerは、DEAにstaging.startメッセージを送り、Staging作業を依頼する
3.DEAはStaging作業を行い、Dropletを作成する
4.Dropletが完成したら、Cloud Controllerに送り返す
これをもうちょっと深掘り
{ "app_id": "65bf0610-fb24-4756-a49a-b64edbe456ed", "task_id": "3b638a01c39b4187a64c76e3ae89a5dd", "properties": { "services": [ ], "resources": { "memory": 256, "disk": 1024, "fds": 16384 }, "environment": [ ], "meta": { "console": false } }, "download_uri": "http://upload-user:[email protected]:9022/staging/apps/65bf0610-fb24-4756-a49a-b64edbe456ed", "upload_uri": "http://upload-user:[email protected]:9022/staging/droplets/65bf0610-fb24-4756-a49a-b64edbe456ed/upload", "buildpack_cache_download_uri": null, "buildpack_cache_upload_uri": "http://upload-user:[email protected]:9022/staging/buildpack_cache/65bf0610-fb24-4756-a49a-b64edbe456ed/upload", "start_message": { "droplet": "65bf0610-fb24-4756-a49a-b64edbe456ed", "name": "dora", "uris": [ "dora.107.22.72.200.xip.io" ], "prod": false, "sha1": null, "executableFile": "deprecated", "executableUri": null, "version": "32395f10-ce09-40c1-99c2-e0f317d66e51", "services": [ ], "limits": { "mem": 256, "disk": 1024, "fds": 16384 }, "cc_partition": "default", "env": [ ], "console": false, "debug": null, "start_command": null, "health_check_timeout": null, "vcap_application": { "limits": { "mem": 256, "disk": 1024, "fds": 16384 }, "application_version": "32395f10-ce09-40c1-99c2-e0f317d66e51", "application_name": "dora", "application_uris": [ "dora.107.22.72.200.xip.io" ], "version": "32395f10-ce09-40c1-99c2-e0f317d66e51", "name": "dora", "space_name": "jacopen-space", "space_id": "33ab8f3b-1a1f-40a7-933d-d2f55a1c80c4", "uris": [ "dora.107.22.72.200.xip.io" ], "users": null }, "index": 0 }, "admin_buildpacks": [ { "key": "9130b02f-9938-4994-9d95-3c864eb1f7b2_f05a183eea56c23f90d8fd616694d8e6a1627ddf", "url": "http://upload-user:[email protected]:9022/v2/buildpacks/9130b02f-9938-4994-9d95-3c864eb1f7b2/download" }, { "key": "c23f44c8-16e4-44bf-a4ed-b228bd05c9a9_ea13962fc6930f2b0d82be4d87ba8222cd3fab6a", "url": "http://upload-user:[email protected]:9022/v2/buildpacks/c23f44c8-16e4-44bf-a4ed-b228bd05c9a9/download" }, { "key": "42d73ff8-20a2-4ff3-bb52-c36444186c84_e6c7c383baf52d8e9cfbee8042cd62ac1dc5798a", "url": "http://upload-user:[email protected]:9022/v2/buildpacks/42d73ff8-20a2-4ff3-bb52-c36444186c84/download" } ]}
staging.startの実物
拡大
{ "app_id": "65bf0610-fb24-4756-a49a-b64edbe456ed", "task_id": "3b638a01c39b4187a64c76e3ae89a5dd", "properties": { "services": [ ], "resources": { "memory": 256, "disk": 1024, "fds": 16384 }, "environment": [ ], "meta": { "console": false } },
アプリケーションの基本情報
"download_uri": "http://upload-user:[email protected]:9022/staging/apps/65bf0610-fb24-4756-a49a-b64edbe456ed", "upload_uri": "http://upload-user:[email protected]:9022/staging/droplets/65bf0610-fb24-4756-a49a-b64edbe456ed/upload", "buildpack_cache_download_uri": null, "buildpack_cache_upload_uri": "http://upload-user:[email protected]:9022/staging/buildpack_cache/65bf0610-fb24-4756-a49a-b64edbe456ed/upload",
ユーザーアプリのダウンロードURL
出来上がったDropletのアップロード先
Buildpack cacheのダウンロードURL
Buildpack cacheのアップロード先
"start_message": { "droplet": "65bf0610-fb24-4756-a49a-b64edbe456ed", "name": "dora", "uris": [ "dora.107.22.72.200.xip.io" ], "prod": false, "sha1": null, "executableFile": "deprecated", "executableUri": null, "version": "32395f10-ce09-40c1-99c2-e0f317d66e51", "services": [ ], "limits": { "mem": 256, "disk": 1024, "fds": 16384 }, "cc_partition": "default", "env": [ ], "console": false, "debug": null, "start_command": null, "health_check_timeout": null, "vcap_application": { "limits": { "mem": 256, "disk": 1024, "fds": 16384 }, "application_version": "32395f10-ce09-40c1-99c2-e0f317d66e51", "application_name": "dora", "application_uris": [ "dora.107.22.72.200.xip.io" ], "version": "32395f10-ce09-40c1-99c2-e0f317d66e51", "name": "dora", "space_name": "jacopen-space", "space_id": "33ab8f3b-1a1f-40a7-933d-d2f55a1c80c4", "uris": [ "dora.107.22.72.200.xip.io" ], "users": null }, "index": 0 },
アプリケーションの起動方法など
"admin_buildpacks": [ { "key": "9130b02f-9938-4994-9d95-3c864eb1f7b2_f05a183eea56c23f90d8fd616694d8e6a1627ddf", "url": "http://upload-user:[email protected]:9022/v2/buildpacks/9130b02f-9938-4994-9d95-3c864eb1f7b2/download" }, { "key": "c23f44c8-16e4-44bf-a4ed-b228bd05c9a9_ea13962fc6930f2b0d82be4d87ba8222cd3fab6a", "url": "http://upload-user:[email protected]:9022/v2/buildpacks/c23f44c8-16e4-44bf-a4ed-b228bd05c9a9/download" }, { "key": "42d73ff8-20a2-4ff3-bb52-c36444186c84_e6c7c383baf52d8e9cfbee8042cd62ac1dc5798a", "url": "http://upload-user:[email protected]:9022/v2/buildpacks/42d73ff8-20a2-4ff3-bb52-c36444186c84/download" } ]}
admin_buildpackの一覧
Cloud Controller
DEAここからアプリ持っていって。出来上がったらココにおいて※
あ、Stagingできたら、ついでにアプリ起動もやっておいて
Stagingに使えるBuildpackはこいつらだから。
※NATSで大きなバイナリの受け渡しは好ましくないため、実際はHTTP経由で行う
つまり、staging.startとは
admin buildpack
• Cloud Foundryに直接インストールされているbuildpack
•ユーザーがbuildpackを指定しなかった場合、admin buildpackから適したものが選ばれる
•管理者コマンド create-buildpackで追加可能
•つまり、admin buildpackを用いることで、サービス提供者は「標準対応言語」を増やすことができる
DEA
staging.startを受け取ったDEA
DEA
admin buildpackのdetectを優先度の高い順に実行
Gemfile lib/ bin/ config.ru app.rb
Ruby
Java
node
GemfileがあるからRubyだ!
DEA
マッチしたBuildpackのcompileを実行
Gemfile lib/ bin/ config.ru app.rb
Ruby
• Rubyのバイナリのダウンロード
• バイナリの設置
• bundle installの実行
• database.ymlの書き換え(Railsの場合)
• 等々
DEA
releaseを実行し、必要な情報を抽出。
Gemfile lib/ bin/ config.ru app.rb
---buildpack_path: /var/vcap/data/dea_next/admin_buildpacks/c23f44c8-16e4-44bf-a4ed-b228bd05c9a9_ea13962fc6930f2b0d82be4d87ba8222cd3fab6adetected_buildpack: Ruby/Rackstart_command: bundle exec rackup config.ru -p $PORT
staging_info.yml
DEA
Dropletのできあがり!"## app$ "## bin$ $ "## erb -> ../vendor/ruby-1.9.3/bin/erb$ $ "## gem -> ../vendor/ruby-1.9.3/bin/gem$ $ "## irb -> ../vendor/ruby-1.9.3/bin/irb$ $ "## rake -> ../vendor/ruby-1.9.3/bin/rake$ $ "## rdoc -> ../vendor/ruby-1.9.3/bin/rdoc$ $ "## ri -> ../vendor/ruby-1.9.3/bin/ri$ $ "## ruby -> ../vendor/ruby-1.9.3/bin/ruby$ $ &## testrb -> ../vendor/ruby-1.9.3/bin/testrb$ "## config.ru$ "## dora.rb$ "## Gemfile$ "## Gemfile.lock$ "## get_instance_cookie_jars.sh$ "## instances.rb$ "## loop.sh$ "## README.md$ "## routes.txt$ "## spec$ $ "## instances_spec.rb$ $ "## spec_helper.rb$ $ &## stress_testers_spec.rb$ "## stress$ "## stress_testers.rb$ &## vendor$ "## bundle$ "## cache$ "## heroku$ &## ruby-1.9.3"## logs$ &## staging_task.log"## staging_info.yml&## tmp
buildpackで作られたRubyの実行バイナリ
アップロードされたアプリ
bundle installで入ったもの
Start commandなどの記述
custom buildpack
•デプロイ時にユーザーがbuildpackを指定できる。これをcustom buildpackという。
• custom buildpackが指定された場合、detectは実行されず、いきなりcompileの実行から始まる。
$ cf push myapp -b https://github.com/dmikusa-pivotal/cf-php-build-pack.git
buildpackがアップデート
された場合
buildpackのアップデート•たとえばRuby buildpackの場合、そのバージョンの最新のパッチレベルでデプロイされる。Ruby 2.0.0であれば、本日時点でp481
•デプロイ後、新しいパッチレベルが公開されたらどうなる?
DEMO
デモまとめ• アプリの起動・停止ではbuildpackの更新は行われない。
• 作成済みのDropletが用いられるため
• 再Staging(再度cf pushするなど)することで、新しいbuildpackでデプロイされる。
• 最近出たv171で、restaging APIが実装された
• ただしcfコマンドは未対応
アプリを動かすコンテナ
Wardenの仕組み3
Warden
• うぉーどん!
• Cloud Foundryでユーザーアプリを隔離するために作られたコンテナ
• ユーザーアプリはWardenコンテナ内で実行。アプリが終了するとコンテナも破棄される
• 現在はアプリを動かす他に、Staging処理やBosh-liteで構築したCFコンポーネントを動かすのにも使われている
なぜコンテナにするのか
http://www.slideshare.net/i_yudai/warden
DEAのVM上でpstreeすると
DEA(ng) = dea_next + wardenDEA
dea_next (Ruby)
warden(Ruby)
※正確には他にもいるけど、ここでは気にしない
DEA(ng) = dea_next + wardenDEA
dea_next (Ruby)
warden server(Ruby)
container wshd (C)
Warden Protocol
Warden Client
Start Request
Warden
• dea_nextはwarden clientを使って、warden serverのAPIを叩く。
• wardenとの通信はwarden protocolで定められている
• warden serverはRubyで書かれている。warden serverが起動するコンテナはCで書かれている。
Wardenが利用する技術• Namespaces(空間の分離)
• NET • MNT • PID • UTS • IPC
• Cgroups(CPU, メモリの制限)
• aufs(10.04), overlayfs(12.04)によるコピーオンライト
ネットワーク周り• コンテナに仮想NICが作られる
• 仮想NICに対してiptablesでNATする
だいたい一緒
• LXC • Docker
最近よく聞かれる話
なぜWardenなのか (vs LXC)
• 実は初期のCFはLXCを使っていた
• LXCはLinux前提に作られているが、CFは将来的にLinux以外もカバーしていきたいから、マルチプラットフォームな仕組みが欲しかった
• LXCはCFの要求に対して過剰性能すぎた。Cで1000行以下で、最低限の機能さえあればよかった。(その分、シンプルで透明性がほしい)
https://github.com/cloudfoundry/warden/tree/master/warden
なぜWardenなのか (vs Docker)
• Dockerは1プロセス前提なので、CFの仕組みに合わない
• コンテナ作成後に、動的に制限をコントロールしたり出来ない
• ディスク制限や帯域の制限ができない
https://docs.google.com/document/d/1DDBJlLJ7rrsM1J54MBldgQhrJdPS_xpc9zPdtuqHCTI/edit
なぜWardenなのか (vs Docker)
• Dockerは1プロセス前提なので、CFの仕組みに合わない
• コンテナ作成後に、動的に制限をコントロールしたり出来ない
• ディスク制限や帯域の制限ができない
https://docs.google.com/document/d/1DDBJlLJ7rrsM1J54MBldgQhrJdPS_xpc9zPdtuqHCTI/edit
赤字はjacopenツッコミ
(Supervisor使えばできるけど・・・一手間いるのは確か)
(確かにそうなんだけど、そもそもCFが 動的に変えるなんてオペレーションしてない)
(今のDockerだと出来るんじゃない?(未確認))
Infrastructure as Code
Heroku Buildpackで記述 ⇒ LXCで稼働 !Cloud Foundry Buildpackで記述 ⇒ Wardenで稼働 !Docker Dockerfileで記述 ⇒ Dockerで稼働
個人的な気持ち• DockerでもHerokuでもCFでも、最終的に達成されるものは一緒。WardenをDockerに置き換えるのはあまり意味がない。
• 個人的にはDockerfileよりもBuildpackのほうが書きやすい
• とはいえ、手元で動くDocker imageをそのままデプロイっていうのはやってみたい。
参考• CloudCredoというところが、CFでDockerfileを使ったデプロイを可能にした、Deckerというものを作っている
• ActiveStateは、CFをベースにしたStackato 3.0でDockerを取り入れた。(それ以前は、LXCを導入していた)
• DEAの次期アーキテクチャであるDiegoでは、Dockerを何らかの方法でサポートするオプションがあるらしい(基本はWardenのGo実装であるGardenを使う)
質問?