Skip to content

Instantly share code, notes, and snippets.

@ohtake
Created May 15, 2012 09:19
Show Gist options
  • Save ohtake/2700318 to your computer and use it in GitHub Desktop.
Save ohtake/2700318 to your computer and use it in GitHub Desktop.
和訳: Cloud Foundry Open PaaS Deep Dive

和訳: Cloud Foundry Open PaaS Deep Dive

Cloud Foundry Open PaaS Deep Dive の和訳です。原文は2011年4月に書かれたもので、和訳をしたのは2011年7月なので内容は現状とは異なっているかもしれません。また訳し間違いもあるかもしれません。

You are probably wondering about how Cloud Foundry actually works, hopefully these details will clear things up for you about how Cloud Foundry the OSS project works, why it works, and how you can use it.

みなさんは Cloud Foundry がどのように動作するのか気になっていると思うが、ここでの説明で OSS プロジェクトの Cloud Foundry がどのように動作するのか、なぜ動作するのか、どのように使うのかがこの記事ではっきりしてくれると幸いである。 (注: わざわざOSSプロジェクトの Cloud Foundry と限定しているのは、.org にてOSSで公開しているものと .com で商用サービスしているものが異なることを暗に言っているのかもしれない。)

Cloud Foundry is on github here: https://github.com/cloudfoundry/vcap. The VCAP repo is the meaty part or what we call the "kernel" of Cloud Foundry as it is the distributed system that contains all the functionality of the PaaS. We have released a VCAP setup script that will help you get an Ubuntu 10.04 system running a instance of Cloud Foundry including all the components of VCAP as well as a few services (mysql, redis, mongodb) up and running so you can play along at home.

Cloud Foundry は github の https://github.com/cloudfoundry/vcap にある。VCAPレポジトリが最も充実した部分で Cloud Foundry の「カーネル」と呼んでいる。なぜならばVCAPがPaaSの全機能を含んだ分散システムであるからだ。VCAPのセットアップスクリプトもつけているので、VCAPとサービス(mysql, redis, mongodb) などのすべてのコンポーネントを含んで動作する Cloud Foundry のインスタンスを Ubuntu 10.04 に簡単に構築することができるだろう。 (注: VCAP は VMware Cloud Application Platform の略だったはず。)

We want to build a community around Cloud Foundry, as that is what matters most for now as far as the open source project. We imagine a whole ecosystem of "userland" tools that people can create and plug into our Cloud Foundry kernel to add value and customize for any particular situation. This project is so large in scope that we had to cut a release and get community involvement at some point and we feel that the kernel is in great shape for everyone to dig in and start helping us shape the future of the "linux kernel for the cloud" ;)

Cloud Foundry はオープンソースプロジェクトであり、コミュニティを築きたいと考えている。各自が作る userland ツールを Cloud Foundry カーネルに載せることでできるエコシステムによって、価値創造や様々な状況へのカスタマイズができると思っている。当プロジェクトは大規模なものなので、リリース単位を分けて、場所によってはコミュニティに参加してもらいたい。コミュニティが参加してくれることによって出来上がる Cloud Foundry は、クラウドにおけるLinuxカーネルのようなものになるだろう。

So how do you approach building a PaaS (Platform as a Service) that is capable of running multiple languages under a common deployment and scalability idiom, that is also capable of running on any cloud or any hardware that you can run Ubuntu on? VCAP was architected by my true rock star coworker Derek Collison (this guys is the man, for realz!). The design is very nice and adheres to a main core concept of "the closer to the center of the system the dumber the code should be". Distributed systems are fundamentally hard problems. So each component that cooperates to form the entire system should be as simple as it possibly can be and still do its job properly.

さて、どうすれば共通の基盤で複数の言語が動く PaaS を作れるだろうか。必要な要件は共通のデプロイ方法、共通のスケール方法、IaaS非依存、Ubuntuが動作するいろんなハードウェアで動く、といったものだ。VCAPのアーキテクチャは同僚の Derek Collison というスターによってなされた。よくできた設計で、根底にあるコンセプトは「システムの基盤にあるコードほど単純なコードであるべき」というものだ。一般に分散システムは根本的に困難な問題を抱えている。ゆえに各コンポーネントは自身が正しく動作する範囲でなるべく単純な方法で協調して全体のシステムを作るべきである。

VCAP is broken down into 5 main components plus a message bus: The Cloud Controller, the Health Manager, the Router's, the DEAs (Droplet Execution Agents) and a set of Services. Let's take a closer look at each component in turn and see how they fit together to form a full platform or for the cloud.

VCAP は5つのメインコンポーネントとメッセージバスに分けることができる。5つのコンポーネントは Cloud Controller, Health Manager, Router, DEA (Droplet Execution Agent), Service である。順に各コンポーネントの詳細を追っていき、どのように全体のプラットフォームを構築しているか見てみよう。(注: 発表資料によっては DEA の名称を Application Execution Engine としていることもある。ソースコード中では DEA の名称で統一されている。)

NATS is a very simple pub/sub messaging system written by Derek Collison (this dude knows messaging, trust me;) of TIBCO fame. NATS is the system that all the internal components communicate on. While NATS is great for this sort of system communication, you would never use NATS for application level messaging. VMware's own RabbitMQ is awesome for app level messaging and we plan to make that available to Cloud Foundry users in the near future.

NATS はとてもシンプルな pub/sub メッセージシステムで、 TIBCO でメッセージングに明るいと評判の Derek Collison によって書かれた。すべてのコンポーネント間の通信はこの NATS を利用している。システムコミュニケーションとして NATS はとても優れているが、アプリケーションレベルでのメッセージングで使うものではない。VMware が所有している RabbitMQ はアプリレベルでのメッセージングに優れていて、Cloud Foundry でも近いうちに利用できるようにする予定だ。

It should be stated here that every component in this system is horizontally scalable and self healing, meaning you can add as many copies of each component as needed in order to support the load of your cloud, and in any order. Since everything is decoupled, it doesn't even really matter where each component lives, things could be spread across the world for all it cares. I think this is pretty cool ;)

各コンポーネントは水平的にスケール可能で自立している。つまりクラウドの付加に対応するために、各コンポーネントのマシンをいくつでもどの順番でも追加することできる。各コンポーネントが独立しているため、コンポーネントが物理的にどこにあるかは関係なく、地球の反対側にコンポーネントを置くこともできる。いけているだろう。

Cloud Controller

The Cloud Controller is the main 'brain' of the system. This is an Async Rails3 app that uses ruby 1.9.2 and fibers plus eventmachine to be fully async, pretty cutting edge stuff. You can find the Cloud Controller here: https://github.com/cloudfoundry/vcap/tree/master/cloud_controller. This component exposes the main REST interface that the CLI tool "vmc" talks to as well as the STS plugin for eclipse. If you were so inclined you could write your own client that talks to the REST endpoints exposed by the Cloud Controller to talk to VCAP in whatever way you like. But this should not be necessary as the "vmc" CLI has been written with scriptability in mind. It will return proper exit codes as well as JSON if you so desire so you can fully script it with bash or ruby, python, etc.

Cloud Controller はシステムの「頭脳」である。Async Rails 3 のアプリケーションで ruby 1.9.2 と Fiber と EventMachine を使って完全に非同期になっていてとても最先端なものだ。Cloud Controller のコードは https://github.com/cloudfoundry/vcap/tree/master/cloud_controller にある。このコンポーネントは REST インタフェースを公開していて、CLIツールの vmc や Eclipse の STS プラグイン がそのインタフェースを利用している。VCAP と対話するために Cloud Controller が公開している REST インタフェースを呼び出すクライアントを各自が作ることができる。だが、vmc はスクリプタビリティを考慮に入れて作られているので、わざわざ自作する必要はないだろう。JSON のレスポンスと同じ exit code を vmc が返すので、bash, Ruby, Python などのスクリプトから操作することができるだろう。

We made a decision not to tie VCAP to git even though we love git, we need to support any source code control system, yet we want the simplicity of a git push style deployment, hence the vmc push. But we also do want to have the differential deploys, meaning that we want to push diffs when you update your app, we do not want to have to push your entire app tree every time you deploy. Feeling light and fast is important to us. Our goal is to rival local development.

我々は git が大好きではあったが、 VCAP と git を結びつけない設計とした。いろんなソースコード管理システムをサポートしなければならないからだ。それでも git の push スタイルでデプロイすることのシンプルさは必要なので vmc push というコマンドとした。差分デプロイは必要だと思っている。つまりアプリのアップデートをするときにアプリ全体をアップロードするのではなく差分だけをアップロードすることだ。軽く素早く動くことは重要で、ローカルでの開発と拮抗できるようにすることが目標だ。

So we designed a system where we can get the best of both worlds. You as a user can use any source control system you want, when you do a vmc push or vmc update we will examine your app's directory tree and send a "skeleton fingerprint" to the cloud controller. This is basically a fingerprint of each file in your apps tree and the shape of your directory tree. The cloud controller keeps these in a shared pool, accessible via their fingerprint plus the size for every object it ever sees. Then it returns to the client a manifest of what files it already has and what files it needs your client to send to the cloud in order to have all of your app. It is a sort of 'dedupe' for app code as well as framework and rubygem code and other dependency code. Then your client only sends the objects that the cloud requires in order to create a full "Droplet" (a droplet is a tarball of all your app code plus its dependencies all wrapped up into a droplet with a start and stop button) of your application.

そこで、クラウドとローカルの両方のいいとこどりをしたデザインにした。ユーザとしては好きなソース管理システムを使って開発をし、vmc push または vmc update コマンドを実行すると vmc はアプリケーションのディレクトリツリーを調べて「skeleton fingerprint」を cloud controller に送る。Skeleton fingerprint にはディレクトリツリーの構造やそこにあるファイルのフィンガープリントが含まれているだけのものである。Cloud controller は共通プールに Skeleton fingerprint を記憶させており、フィンガープリントとファイルサイズで当該ファイルにアクセスすることができる。Cloud controller はすでにクラウド上に存在するファイルの一覧と送るべきファイルの一覧をクライアントに返す。アプリケーションコードのいわゆるデデュープとも呼ぶべきもので、フレームワークや Rubygem や他の依存の重複を排除する。クライアントはユーザのアプリケーションのドロップレット (ドロップレットとはアプリコード、依存ライブラリ、起動停止スクリプトを tarball で固めたファイルのことである) を作成するのに必要なファイルのみをクラウドに送信する。

Once the Cloud Controller has all the 'bits' it needs to fully assemble your app, it pushes the app into the "staging pipeline". Staging is what we call the process that assembles your app into a droplet by getting all the full objects that comprise your applications plus all of its dependencies, rewrites its config files in order to point to the proper services that you have bound to your application and then creates a tarball with some wrapper scripts called start and stop.

アプリケーションを構築するのに必要な全ファイルが揃うと、cloud controller はアプリケーションを stating pipeline に乗せる。アプリケーションをドロップレットにするプロセスを staging と呼んでいる。ドロップレットを作るには、アプリケーションのコードと依存ファイルをそろえ、アプリケーションにバインドされているサービスを参照できるように設定ファイルを書き換え、start と stop の名前のラッパースクリプトを付けて tarball にすることである。(注: サービスを参照するために設定ファイルを書き換えると書かれているが、具体的なIPアドレスとかが書かれたものに書き換えるわけではない。DEAの節を参照。)

DEA

The Droplet Execution Agent can be found here: https://github.com/cloudfoundry/vcap/tree/master/dea. This is an agent that is run on each node in the grid that actually runs the applications. So in any particular cloud build of Cloud Foundry, you will have more DEA nodes then any other type of node in a typical setup. Each DEA can be configured to advertise a different capacity and different runtime set, so you do not need all your DEA nodes to be the same size or be able to run the same applications.

Droplet Execution Agent のソースコードは https://github.com/cloudfoundry/vcap/tree/master/dea にある。このエージェントは実際にアプリケーションを動かすためのもので、グリッド上の各ノードで動いている。よって Cloud Foundry の PaaS を作った場合には、一般にDEAノードがほかの種類のノードよりも多くの数を占めることになるだろう。各DEAはマシンの性能やランタイムを伝えることができるため、すべての DEA が同じマシンスペックである必要もなければ、PaaS でサポートしてるすべてのフレームワークを動かせるようになっている必要もない。

So continuing on from our Cloud Controller story, the CC has asked for help running a droplet by broadcasting on the bus that it has a droplet that needs to be run. This droplet has some meta data attached to it like what runtime it needs as well as how much RAM it needs. Runtimes are the base component needed to run your app, like ruby-1.8.7 or ruby-1.9.2, or java6, or node. When a DEA gets one of these messages he checks to make sure he can fulfill the request and if he can he responds back to the Cloud Controller that he is willing to help.

Cloud controller での話から続けると、cloud controller はドロップレットを動かすためにメッセージバスにドロップレットを動かしたいとブロードキャストする。ドロップレットにはメタデータがついており、そのメタデータは何のランタイムが必要か、RAMがどれだけ必要かなどが書かれている。ラインタイムとはアプリケーションを動かすために必要な基盤コンポーネントのことで、ruby-1.8.7, ruby-1.9.2, java6, node といったものがある。DEAがメッセージを受け取ると、自身がその要求に応えることができるかチェックし、もし要求に応えることができるのであれば DEA は cloud controller に対して協力したいと返答する。

The DEA does not necessarily care what language an app is written in. All it sees are droplets. A droplet is a simple wrapper around an application that takes one input, the port number to serve HTTP requests on. And it also has 2 buttons, start and stop. So the DEA treats droplets as black boxes, when it receives a new droplet to run, all it does it tells it what port to bind to and runs the start script. A droplet again is just a tarball of your application, wrapped up in a start/stop script and with all your config files like database.yml rewritten in order to bind to the proper database. Now we can't rewrite configs for every type of service so for some services like Redis or Mongodb you will need to grab your configuration info from the environment variable ENV['VCAP_SERVICES'].

DEAはアプリケーションがどの言語で書かれているか関知する必要がない。DEAはアプリケーションを単にドロップレットとしてしか見ていない。ドロップレットは単なるラッパーで、唯一の入力パラメタとしてHTTPリクエストを受け付けるポート番号を指定するだけである。ドロップレットには2つのボタンがあり、それは start と stop である。DEAはドロップレットを起動するときにドロップレットをブラックボックスとして扱いポート番号を指定して start スクリプトを実行しているだけである。繰り返しになるがドロップレットはアプリケーションの単なる tarball で start/stop スクリプトが付けられていて、データベースにバインドできるようにするために database.yml などが書き換えられているだけである。Redis や Mongodb などのすべてのサービスに対応できるような設定ファイルの書き換えはできないため、環境変数 ENV['VCAP_SERVICES'] から設定情報を取得する必要がある。

In fact there is a bunch of juicy info in the ENV of your application container. If you create a directory on your laptop and make a file in it called env.rb like this:

$ mkdir env && cd env $ cat << EOF > envvars.rb require 'sinatra' require 'pp' get '/' do "

#{ENV.pretty_inspect}
" end EOF $ vmc push ...


実際アプリケーションコンテナの環境変数を見てみると面白いことが分かる。以下の手順で空のディレクトリを作り env.rb というファイルを作ってみる。

$ mkdir env && cd env $ cat << EOF > envvars.rb require 'sinatra' require 'pp' get '/' do "

#{ENV.pretty_inspect}
" end EOF $ vmc push ...


> That will make a simple app that will show you what is available in your ENVIRONMENT so that you can see what to use to configure your application. If you visit this new app you will see something like this:

環境変数から何が得られるかを示すだけの簡単なアプリだが、これを見るとどの変数を使ってアプリケーションを構成すればいいか分かるだろう。出力例は以下にある。

> [ENV output](https://raw.github.com/gist/922647/926a26eabb127c368156d65873fd5b6e5b1fb839/gistfile1.txt)

[環境変数の出力](https://raw.github.com/gist/922647/926a26eabb127c368156d65873fd5b6e5b1fb839/gistfile1.txt)

> So the DEA's job is almost done, once it tells the droplet what port to listen on for HTTP requests and runs it's start script, and the app properly binds the correct port, it will broadcast on the bus the location of the new application so the Routers can know about it. If the app did not start successfully it will return log messages to the vmc client that tried to push this app telling the user why their app didn't start (hopefully). This leads us right into what the Router has to do in the system so we will hand it over to the Router (applause).

DEAがやっていることはこれでほとんどだ。ひとたびDEAがドロップレットにHTTPリスンのポート番号を伝えて start スクリプトを起動すれば、アプリケーションは正しいポート番号でリスンし、アプリケーションの場所を Router に伝えるためにメッセージをブロードキャストするだろう。仮にアプリケーションが起動に失敗したら、ログメッセージを vmc クライアントに送り、なぜ起動できなかったのかユーザに伝える。システム内で router が何をしてくれるかを説明してもらうために、 Router さんに登場願おう。

Router
------

> The Router is another eventmachine daemon that does what you would think it does, it routes requests. In a larger production setup there is a pool of Routers load balanced behind Nginx (or some other load balancer or http cache/balancer). These routers listen on the bus for notifications from the DEA's about new apps coming online and apps going offline etc. When they get a realtime update they will update their in-memory routing table that they consult in order to properly route requests. So a request coming into the system goes through Nginx, or some other HTTP termination endpoint, which then load balances across a pool of identical Routers. One of the routers will pick up the phone to answer the request, it will start inspecting the headers of the request just enough to find the Host: header so it can pick out the name of the application this request is headed for. It will then do a basic hash lookup in the routing table to find a list of potential backends that represent this particular application. These look like: `{'foo.cloudfoundry.com' => ['10.10.42.1:5897', '10.10.42.3:61378', etc]}` So once it has looked up the list of currently running instances of the app represented by 'foo.cloudfoundry.com' it will pick a random backend to send the request to. So the router chooses one backend instance and forwards the request to that app instance. Responses are also inspected at the header level for injection if need be for functionality such as sticky sessions.

Router も EventMachine デーモンで、お察しの通りリクエストのルーティングを行う。大規模実運用環境では Nginx や他のバランサーの後段に router のプールがあることだろう。これらの router はDEA からのアプリケーションがオンラインまたはオフラインになったという通知をメッセージバスから受け取っている。通知を受け取ると院メモリのルーティングテーブルを更新して適切にルーティングできるようにする。つまりシステムに入ってくるリクエストはまず Nginx などのバランサを通り、router に渡される。そのリクエストがどのアプリケーション向けのリクエストなのか特定するため必要なことは router が HTTP リクエストの Host ヘッダを見るだけである。そしてルーティングテーブルのハッシュテーブルを参照してアプリケーションをホストしているインスタンス一覧を得ることになる。たとえば `{'foo.cloudfoundry.com' => ['10.10.42.1:5897', '10.10.42.3:61378', etc]}` のようになる。当該アプリを動かしているインスタンス一覧を得られてたら、ランダムでインスタンスを選びリクエストを送る。つまり router は1つの後続インスタンスを選んでリクエストを転送するだけだ。レスポンスもヘッダーのレベルでチェックしてスティッキーセッションを要求されていたらヘッダを追加するなどのことも行う。

> The Router can retry another backend if the one it chose fails and there are many ways to customize this behavior if you have your own instance of Cloud Foundry setup somewhere. Routers are fairly straightforward in what they do and how they do it. They are eventmachine based and run on ruby-1.9.2 so they are fast and can handle quite a bit of traffic per instance, but like every other component in the system, they are horizontally scalable and you can add more as needed in order to scale up bigger and bigger. The system is architected in such a way that this can even be done on a running system.

選んだ後続インスタンスが落ちていたら Router は別の後続インスタンスにリクエストを再送する。Cloud Foundry を自身でセットアップするのであれば、この動作はカスタマイズ可能で方法もたくさんある。Router が行っていることおよびどのように行っているかはとても簡単なものである。Ruby-1.9.2 で動く EventMachine であり、動作が速くたくさんのトラフィックをさばくことができる。もちろんほかのコンポーネントと同様に水平スケール可能でインスタンスを追加することでスケールすることができる。PaaSが動作している最中に動的にスケールさせることができるようにするためにこのような設計とした。

Health Manager
--------------

> The Health Manager is a standalone daemon that has a copy of the same models the Cloud Controller has and can currently see into the same database as the Cloud Controller.

Health manager は単独で動作するデーモンで、cloud controller が保持しているモデルのコピーを持ち同じデータベースを見ることができる。

> This daemon has an interval where it wakes up and scans the database of the Cloud Controller to see what the state of the world "should be", then it actually goes out into the world and inspects the real state to make sure it matches. If there are things that do not match then it will initiate messages back to the Cloud Controller to correct this. This is how we handle the loss of an application or even a DEA node per say. If an application goes down, the Health Manager will notice and will quickly remedy the situation by signaling the Cloud Controller to star a new instance. If a DEA node completely fails, the app instances running there will be redistributed back out across the grid of remaining DEA nodes.

このデーモンは起動して cloud controller のデータベースに書かれている「あるべき姿」を読んでから実際の状態があっているか確認するまでにインターバルがある。もし「あるべき姿」とマッチしないものがあれば、 cloud controller に直すようにメッセージを送る。そうしてアプリケーションがこけていたりDEAが落ちていたりするのを修復する。もしアプリケーションが落ちていたら health manager はすぐに状況を cloud controller に伝え新しいインスタンスを起動させる。もし DEA 自身が死んでいたとしたら、別のマシンの DEA にアプリケーションを再配布することでしょう。

Services
--------

> These are the services your application can choose to use and bind to in order to get data, messaging, caching and other services. This is currently where redis and mysql run and will eventually become a huge ecosystem of services offered by VMware and anyone else who wants to offer their service into our cloud. One of the cool things I will highlight is that you can share service instances between your different apps deployed onto a VCAP system. Meaning you could have a core java Spring app with a bunch of satellite sinatra apps communicating via redis or a RabbitMQ message bus.

アプリケーションがデータ格納やメッセージングやキャッシングのためにバインドして使える service がある。Redis や MySQL はこの service によって動いており、やがて大きなエコシステムになることだろう。このエコシステムは VMware だけによって提供されるものではなく、誰しもが Cloud Foundry の service を提供することができる。Service で最もすごいことは、VCAPのシステムによって別々のアプリケーションから同一の service を共有できることである。つまり、コアとなる Java Spring アプリケーションのほかに、Sinatra のアプリを置きそれらを Redis や RabbitMQ のメッセージバスで通信させるようなことができる。

> Ok my fingers are tired and my shoulder hurts so I am going to call this first post done. I plan on blogging a lot more often as well as trying to help organize the community around Cloud Foundry the open source project. I hope you are as excited as I am by this project, it is basically like "rack for frameworks, clouds and services" rather then just ruby frameworks. Pluggable across the 3 different axis and well tested and well coded. This thing is very cool and I am very proud just to be a member of the team working on this thing.

指も疲れてきたし肩も痛くなってきた。もうそろそろこの初投稿を終わらせよう。Cloud Foundry オープンソースプロジェクトのコミュニティを形成するためにたくさんブログを書くつもりだ。当プロジェクトが単なる ruby のフレームワークではなく「フレームワーク、クラウド、サービスの積み重ね」であるということに感動してくれればと思う。組み合わせ可能な3つの軸は十分にテストされコーディングされている。Cloud Foundry はよくできており、このチームでかかわることができたことを誇りに思っている。

> This has been a huge team effort to get out the door and we hope it will become a huge community effort to keep driving it forward to truly make it "The Linux Kernel of Cloud Operating Systems". Will you please join the community with me and help build this thing out to meet its true potential?

チームによる努力によってドアを開けた状態が今であり、これからはコミュニティによる多大なる協力によって「クラウドOSにおけるLinuxカーネル」となるべく前進してくようになることを願っている。真の可能性を達成するためにコミュニティに参加してください。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment