VMware発のPaaS、CloudFoundryを試してみた


VMwareRailsJavaやNodeが動くPaaSを始めるらしいと聞いて2週間ほど前にBeta登録していたんですが、すっかり忘れた昨日の夜、英語でアカウント発行のお知らせが来てました。no-reply@cloudfoundry.comから「Welcome to Cloud Foundry – Your signup is approved!」というタイトルのメールが来るので間違えて捨てないように気をつけましょう(^^;
さて、折角登録できたので、早速いくつかアプリのデプロイを試してみることにします。
最初の一歩はチュートリアルのpdf見ながら、DB使ったりNode使ったりとかのドキュメントはまだ少ないぽいが、ForumのKnowledge Base辺りを見ると、DBの使い方とかも色々見つかる。

デプロイツール

最近よくある形の、APIで全てのオペレーションを行う仕組みになっており、APIの利用実装として、STSというEclipseプラグインと、vmcというコマンドラインツールが提供されているようです。
両方試してみようと思ったところ、Eclipseプラグインの方がなぜかプラグインサイトが403でアクセス拒否されてダウンロード出来なかったので今日は諦めました。後日改めて試してみようと思います(^^;
コマンドライン版の vmc というツールはRubyで出来ており、gemが使える環境ができていれば gem install vmc で簡単にインストールすることが出来ます。

Sinatraアプリを動かしてみる

Rubyにはそんなに明るくないけどまずはチュートリアル通りにHelloWorldを作ってみます。


まずやることは、vmcのAPIエントリポイントの設定です。これくらいはデフォルトで設定しておいてくれて良い気がしますがとりあえず指示通りやります。この設定をしないと他のコマンドが実行エラーになります。

$ vmc target api.cloudfoundry.com
Succesfully targeted to http://api.cloudfoundry.com

ちなみにProxyが必要な場合は export http_proxy=http://myproxy.example.jp:8080 というふうに環境変数を設定してから vmc target をすれば良いようです。


次にログインです。*** には登録完了メールに書いてある一時パスワードを入れます。

$ vmc login
Email: kawazzz@gmail.com
Password: ********
Successfully logged into http://api.cloudfoundry.com

↑で入れたパスワードは平文メールで送られて来た、あくまで一時パスワードなので以下のコマンドでパスワードを変更しておきましょう。

$ vmc passwd
Changing password for 'kawazzz@gmail.com'
New Password: **********
Verify Password: **********

Successfully changed password


さて、ここからアプリの作成です。hello.rb だけの超簡単なSinatraアプリです。

$ mkdir hello-sinatra
$ cd hello-sinatra
$ cat <hello.rb 
> require 'sinatra'
> get '/' do
>   "初めての Cloud Foundry"
> end
> EOF


アプリが出来たら vmc push でアプリ登録&デプロイをします。
途中で聞かれる Application NameはURLやその他操作で使われるアプリ名になります。あとインスタンスが使用するメモリ容量が選択できます。ゴミのようなアプリなのでとりあえず最小の選択肢の64MBにしておきます。

$ vmc push
Would you like to deploy from the current directory? [Yn]: 
Application Name: kawaz-hello-sinatra
Application Deployed URL: 'kawaz-hello-sinatra.cloudfoundry.com'? 
Detected a Sinatra Application, is this correct? [Yn]: 
Memory Reservation [Default:128M] (64M, 128M, 256M, 512M, 1G or 2G) 64M
Creating Application: OK
Would you like to bind any services to 'kawaz-hello-sinatra'? [yN]: 
Uploading Application:
  Checking for available resources: OK
  Packing application: OK
  Uploading (0K): OK   
Push Status: OK
Staging Application: OK                                                         
Starting Application: OK                                                        

Sinatraアプリであるとは一言も言っていないのに勝手にファイル群を見て判別してくれます。起動用のファイル名も何でもよくて勝手に探して判別して良きに計らってくれるようです、楽チン!たぶんマニュアル指定するやり方もあると思うけどとりあえずはお任せで問題ない限りおまかせで。
ちなみにファイルを更新したら vmc update {appid} で再デプロイが出来ます。

$ vmc update kawaz-hello-sinatra
Uploading Application:
  Checking for available resources: OK
  Packing application: OK
  Uploading (0K): OK   
Push Status: OK
Stopping Application: OK
Staging Application: OK                                                         
Starting Application: OK           


さて、無事デプロイが出来たのでURLへアクセスしてみましょう。

初めての Cloud Foundry

http://kawaz-hello-sinatra.cloudfoundry.com/

おー、無事動いてます!パチパチパチ。

Nodeも試すよ

Rubyは適当だったけどNodeはnpmパッケージとか使ってちょっと凝ったことをしてみようと思う。
Nodeを動かすにあたってポイントは2点ある。
一つは待ち受けポート。これは環境変数 VMC_APP_PORT から取れるので、listen を以下のように書いておくと良い、ローカルで動かす場合は3000番になる。

app.listen(process.env.VMC_APP_PORT || 3000);

2つ目は、npmモジュールを使う場合はアプリケーションにバンドルしておく必要があるということ。まぁ難しい事は無く、例えば express, jade, socket.io を使うのであれば以下のような package.json を作成しておき、npm bundle を実行すればOKです。

{
  "name":"kawaz-hello-node",
  "version":"0.0.1",
  "dependencies":{
    "express":"",
    "jade":"",
    "socket.io":""
  }
}

するとカレントディレクトリに node_modules というディレクトリが出来るので。後はアプリの頭のほうで、以下の1行を追記しておけばバンドルされたモジュールが使われるようになります。

require.paths.unshift('./node_modules');


Nodeアプリケーションの場合も vmc push でアプリ登録とデプロイが出来ます。Nodeアプリケーションであることはまたしても自動判別してくれます。
今回は簡単なチャットアプリを書いてみました。以下URLで動いてますので見てみてください。
http://kawaz-hello-node.cloudfoundry.com/
ソースコードは以下で公開してます。
https://github.com/kawaz/vmc-example

ところでSocket.IOとは相性が凄く悪いっぽいな…

僕のコード側で改善できる余地はあるかも知れないけど、とにかくよく切れる。まずWebSocketもflashsocketも通らないし、再接続もコケまくる。普通のサーバで動かす分にはこんなこと無いんだがなぁ…。
WebSocketが通らないのはフロントにnginxが居るせいっぽいね。nginxがWebSocketのProxyに対応してないからCloudFoundryとしても使えない。逆を言えばnginxが対応すればCloudFoundryでもWebSocketが使えるようになるかのせいもある。
追記) そもそもアクセスが増えて複数インスタンスが起動されると、サーバ側で行うブロードキャストのグループがインスタンス毎に分断されてしまうから、PaaSでこういうアプリを書くこと自体が間違いなのかもしれんね。

その他いろいろ

vmc -h するとその他に色々な情報を見ることが出来ます。


vmc info では現在のログインユーザ、使用メモリ、サービス数、アプリケーション数が確認できます。SinatraとNodeのアプリを1つずつ、64MBずつのメモリでpushしたので、メモリが計128MB、アプリ数2個となっているのが確認できます。

$ vmc info
VMware's Cloud Application Platform
For support visit support@cloudfoundry.com

Target:   http://api.cloudfoundry.com (v0.999)
Client:   v0.3.10

User:     kawazzz@gmail.com
Usage:    Memory   (128.0M of 2.0G total)
          Services (0 of 16 total)
          Apps     (2 of 20 total)


vmc runtimes では利用できるランタイムがとバージョンが確認できます。javaも使えますが今回はまだ試してません。STSの方でやってみる予定。

$ vmc runtimes

+--------+-------------+-----------+
| Name   | Description | Version   |
+--------+-------------+-----------+
| ruby18 | Ruby 1.8    | 1.8.7     |
| ruby19 | Ruby 1.9    | 1.9.2p180 |
| java   | Java 6      | 1.6       |
| node   | Node.js     | 0.4.5     |
+--------+-------------+-----------+

利用可能フレームワークの確認。

$ vmc frameworks

+---------+
| Name    |
+---------+
| rails3  |
| grails  |
| spring  |
| node    |
| sinatra |
+---------+

利用可能なサービスの確認。今のところサービスといってもDBサーバしか無いみたい。これらは vmc create-service することで利用可能になります。

$ vmc services
============== System Services ==============

+---------+---------+-------------------------------+
| Service | Version | Description                   |
+---------+---------+-------------------------------+
| mongodb | 1.8     | MongoDB NoSQL store           |
| redis   | 2.2     | Redis key-value store service |
| mysql   | 5.1     | MySQL database service        |
+---------+---------+-------------------------------+

=========== Provisioned Services ============


最後に vmc を使う作業がひと通り終わったら、vmc をログアウトしておきましょう。これで勝手にアプリを停止されたりといったことを避けられます。

$ vmc logout
Successfully logged out of [http://api.cloudfoundry.com]