NTT Communicationsが提供するCloudn PaaS や、IBMの提供するBluemixは、どちらもCloud FoundryをベースにしたPaaSです。
Cloud Foundryは、アンチベンダーロックインを掲げ、同じCFであれば同じように使えるという点をウリにしています。であれば、Cloudn PaaSも、Bluemixも同じように利用できるはず!
今回はRailsアプリをCloudn PaaSとBluemix、それぞれにデプロイして本当に両者の互換性が保たれているのか、確認してみます。
Railsアプリの準備
今回はrails newした後に、scaffoldと必要な設定をしただけの、シンプルなRailsアプリを使って実験します。
バージョンは、これを執筆している時点で最新のものを利用します。
Rails version: 4.1.4
Ruby version: 2.1.1
scaffoldでベースを作る
rails new cf-rails-sample
cd cf-rails-sample
rails g scaffold item name:string description:string
rake db:migrate
rails s
よくある画面が出来ました。
Gemfileを編集する
今回はMySQLを使いたいので、次の行をGemfileに追加します。
group :production do
gem 'mysql2'
gem 'rails_12factor'
gem 'rails_stdout_logging'
end
rails_12factorは、元々Heroku向けの調整を行うgemですが、Cloud Foundryでも利用できるので入れておきます。また、cf logsコマンドでRailsのログを取得できるように、rails_stdout_loggingも入れておきます
編集が終わったらbundle updateしておきます
bundle update
.cfignoreの追加
.cfignoreファイルを作成し、以下の内容を記述します。
vendor/bundle
このファイルに記述されたファイル/ディレクトリは、cfコマンドでpushする際に無視されます。
ローカルで動かす際にbundle install --path=vendor/bundleされる方は多いと思いますが、デプロイ時には改めてCF内部でbundle installされるので、このディレクトリをアップロードしても意味がありません。なので、アップロードを高速に行うためにも、この記述の追加をお勧めします。(必須ではありません)
Cloudn PaaSの準備
Railsの準備ができたら、Cloudn PaaSの準備を行います。
CloudnやCloudn PaaSの申し込みは、ここでは解説しません。マニュアル等を参考に申し込みしておいてください。
cfコマンドのインストール
Cloudn PaaSでは独自コマンドのgudを提供しているようですが、今回は使用しません。代わりに、Cloud Foundry標準のcfコマンドをインストールしておきます。
cfコマンドのREADMEにあるDownloadから、自分の環境用のcfをダウンロードしてインストールしておきます。
Cloudn PaaSへのログイン
cfコマンドでCloudn PaaSへログインします。
Cloudn PaaSの場合、APIアクセスキーとシークレットキーがそのままPaaSのログインユーザー、パスワードになります。APIアクセスキー画面で取得しておきます。
そしてcf api、cf loginコマンドでログイン。
$ cf api api.paas.jp-e1.cloudn-service.com
Setting api endpoint to api.paas.jp-e1.cloudn-service.com...
OK
API endpoint: https://api.paas.jp-e1.cloudn-service.com (API version: 2.0.0)
Not logged in. Use 'cf login' to log in.
$ cf login
API endpoint: https://api.paas.jp-e1.cloudn-service.com
Email> <APIアクセスキー>
Password> <シークレットキー>
Authenticating...
OK
Targeted org clnxxxxxxxx
Select a space (or press enter to skip):
1. default
2. development
3. production
Space> 1
Targeted space default
API endpoint: https://api.paas.jp-e1.cloudn-service.com (API version: 2.0.0)
User: clnxxxxxxxxx@cloudnpaas.com
Org: clnxxxxxxxxx
Space: default
MySQL Serviceの作成
無料のMySQL DBを作成します。
cf create-service mysql default cf-rails-sample-mysql
manifest.ymlの作成
manifest.ymlを作成し、以下のように記述します
applications:
- name: cf-rails-sample
command: bundle exec rake db:migrate && bundle exec rails s --port=$PORT
services:
- cf-rails-sample-mysql
env:
SECRET_KEY_BASE: hogehogefugafuga
name: デプロイするアプリケーション名
command: デプロイ後、実行したいコマンド
services: アプリに結びつけたいservice名(ここでは、作成したMySQLサービスの名前を指定)
env: アプリケーションに渡したい環境変数を指定
デプロイ!
準備ができたら、以下のコマンドでpushします
cf push
最後にこんなメッセージができたらデプロイ成功です。
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: cf-rails-sample.paas.jp-e1.cloudn-service.com
state since cpu memory disk
#0 running 2014-07-16 10:09:40 PM 0.0% 151.3M of 256M 91.4M of 1G
urlsに、自動で割り振られたURL名が表示されているので、ブラウザでアクセスします。
問題なさそうですね!
同じものをBluemixにデプロイ
さて、それでは同じものをBluemixにデプロイしてみましょう。
Bluemixの登録方法はここでは解説しないので、このあたりを参考に登録しておきましょう。
Cloudnで下準備は既にできているはず。CF間の互換性とやらを見せて貰いましょう。
ログイン
IBM IDを使ってログインします。
$ cf api api.ng.bluemix.net
Setting api endpoint to api.ng.bluemix.net...
OK
API endpoint: https://api.ng.bluemix.net (API version: 2.2.0)
Not logged in. Use 'cf login' to log in.
$ cf login
API endpoint: https://api.ng.bluemix.net
Email> <IBM ID>
Password> <password>
Authenticating...
OK
Targeted org xxxxxxxx
Targeted space dev
API endpoint: https://api.ng.bluemix.net (API version: 2.2.0)
User: xxxxxxx
Org: xxxxxxx
Space: dev
MySQL Serviceの作成
無料のMySQL Serviceを作成します。CloudnとはPlanの指定が少し違うので、間違えないように。(Cloudn:default, Bluemix:100)
cf create-service mysql 100 cf-rails-sample-mysql
デプロイ!
Cloudn側でmanifest.ymlも作成したので、もうこれだけでデプロイできちゃいます。
cf push
requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: cf-rails-sample.mybluemix.net
state since cpu memory disk
#0 running 2014-07-16 10:26:30 PM 0.0% 160.5M of 1G 101.9M of 1G
動きました!
総評
試してみたところ、Cloudn PaaS、Bluemixともに同じコード、同じ操作でデプロイすることができました。
コードを全く変更することなく、cfコマンドの向き先を変えるだけで同じアプリがデプロイできるのは、ベンダーロックインされないという意味でも良さそうです。
QA
database.ymlの設定は要らないの?
CFでMySQLやPostgreSQLをbindすれば、自動でdatabase.ymlが生成されますので、予め指定しておく必要はありません。
ほんとうにコードの変更なしに両方で同じように動くの?
必ず両方で動くと保証はできませんが、いくつかのポイントに注意すれば、高い確率で同じように動くのではないかと思います。
例えば、設定項目はファイルに書くのではなく、環境変数で渡すなどの工夫をしたほうが良いです。そうすれば、コードベースを変更することなく、CF間でアプリの移行を行うことができます。
もっとも、これはCFというより、クラウドネイティブなアプリの作成に共通する話ですが。(12 factor appsに書かれている話ですね)