「Cloud Foundry 百日行」第95日目,今日は最近注目されているジョブ・スケジューラー Rundeck です。Webベースのジョブ・スケジューラーといえば, 92日目に webcrontab を紹介 しましたが,Rundeck はこれと比べるとずっと本格派で,最近はインフラ周りの管理に使われることも増えているようです。
基本情報
-
公式サイト
http://rundeck.org/ -
ソースコード
https://github.com/rundeck/rundeck
上記の場所にソースコードがありますが,今回は公式で配布されている JAR ファイルを使ってデプロイを行いました -
その他参考情報
- http://rundeck.org/docs/administration/index.html
非常に多機能なアプリケーションで,ドキュメントも充実しています
- http://rundeck.org/docs/administration/index.html
手順の概要は以下の通りです。
- 1) Buildpack の修正
- 2) 各種設定ファイル/スクリプトの作成
- 3) サービスの作成とバインド及び接続設定
- 4) アプリのデプロイ
- 5) 動作確認
1. Buildpack の修正
JAR ファイルを使っていることからもわかるように,このアプリは Java で書かれているのですが,
- Cloud Foundry 標準の java-buildpack は JAR / WAR / ZIP ファイルを展開してアプリのステージング/実行を行う
- 本アプリの起動プロセスは JAR ファイルが存在することを前提にしている
cf. https://github.com/rundeck/rundeck/blob/v2.6.1/rundeck-launcher/launcher/src/main/java/com/dtolabs/rundeck/ExpandRunServer.java#L732-L734
という理由から, Cloud Foundry 標準の java-buildpack は使えないことがわかりました。
そこで JAR ファイルを直接起動できる buildpack を探した結果, energizedwork/heroku-buildpack-runnable-jar を見つけました。
この buildpack は,アプリケーションの JAR ファイルをステージング時にダウンロードすることが前提なので,今回はコードの取得も不要になりました。
ただ,1つだけ問題が。
この buildpack にはデプロイの事前処理を行う機能があり,さらにそれをオプションでスキップできるようになっているのですが,バグ(と思われる問題)があってスキップが正常に行えず,Rundeck の場合ステージングが正常終了しません。
そこで,スキップが正常に行えるようにコードの修正を行いました。オリジナルのバージョンは検証時点の master ブランチのヘッド ( https://github.com/energizedwork/heroku-buildpack-runnable-jar/tree/a736a0571ab050815c287cef5bdf74a3a6e59152 ) で,それとの差分は以下の(実質)1行です。
$ git diff a736a05
diff --git a/bin/compile b/bin/compile
index f729d59..fa327fb 100755
--- a/bin/compile
+++ b/bin/compile
@@ -17,6 +17,8 @@ BUILD_DIR=$1
CACHE_DIR=$2
ENV_DIR=$3
+source ${BUILD_DIR}/manifest.sh
+
GRADLE_TASK=${GRADLE_TASK-stage}
export_env_dir $ENV_DIR
この修正を施した buildpack を,
に push しました。
2. 各種設定ファイル/スクリプトの作成
2.1. Buildpack用設定ファイルの作成
前節で述べた通り,今回の buildpack では
- アプリの JAR ファイルをダウンロードするので,その URL を指定
- デプロイの事前処理をスキップするように設定
する必要があります。
これらの設定は manifest.sh という shell スクリプト・ファイルに書くことになっているので,最終的に以下の内容の manifest.sh ファイルを作成しました(この辺りの説明は README.md には書かれていなかったので, bin/ 下のスクリプト から直接読み解きました)。
$ cat manifest.sh
export ARTIFACT_URL=http://download.rundeck.org/jar/rundeck-launcher-2.6.1.jar
export NO_PRE_DEPLOY=true
2.2. 起動スクリプトの作成
今回使う buildpack はデフォルトの起動スクリプトを持たないので,Procfile もしくはコマンドで起動方法を指定する必要があります。
単に java
コマンドに -jar
で JAR ファイルを渡せば済む,のであればよかったのですが,残念ながらそれではメモリ設定が固定値になってしまうので,割り当てられたメモリに合わせて起動スクリプト側でメモリ設定を計算するようにしました。
計算は Cloud Foundry 標準の java-buildpack のやりかたをベースにしました。
- https://github.com/cloudfoundry/java-buildpack-memory-calculator/blob/6a7690ba8d6ae97b0c87209f22a2ad09d6098504/memory/allocator.go#L179-L181
- https://github.com/cloudfoundry/java-buildpack/blob/485c4552f9465b7e4dcf0acb0bdab43087e4637b/config/open_jdk_jre.yml#L32-L37
最終的に出来上がった起動スクリプトは以下の通りです。
$ cat start.sh
#!/bin/bash
set -x
## Calculate memory actually assigned to Java process
## '* 75 / 110' comes from:
## - https://github.com/cloudfoundry/java-buildpack-memory-calculator/blob/6a7690ba8d6ae97b0c87209f22a2ad09d6098504/memory/allocator.go#L179-L181
## - https://github.com/cloudfoundry/java-buildpack/blob/485c4552f9465b7e4dcf0acb0bdab43087e4637b/config/open_jdk_jre.yml#L32-L37
mem=$(echo $MEMORY_LIMIT | perl -ne '/(\d+)([gmk])/; $mx = $1; $factor = $2; if ($factor eq "g") { $mx = $mx * 1024 * 1024 } elsif ($factor eq "m") { $mx = $mx * 1024 }; print (int($mx))')
heap=$(($mem * 75 / 110))
stack=$(($mem * 5 / 110))
export JAVA_TOOL_OPTIONS="-Xmx${heap} -Xss${stack} -Dfile.encoding=UTF-8"
java -Dserver.http.port=$PORT -jar application.jar
なお,このメモリ設定の計算は,本来なら buildpack 側で行うべき処理ですが,試してみたものの環境変数の引き渡しがうまくいかなかったため,今回は諦めて起動スクリプト側で計算/設定を行うことにしました。
2.3. アプリケーション・マニフェストの作成
必須ではありませんが,push 時の指定オプションが多いので,アプリケーションの各種設定をまとめたマニフェスト・ファイルも作りました。内容は以下の通りです。
$ cat manifest.yml
applications:
- name: rundeck
command: "./start.sh"
buildpack: "https://github.com/nota-ja/heroku-buildpack-runnable-jar.git#cf-100-day-challenge-095"
memory: 1536m
services:
- mysql-rundeck
Buildpack として1節で修正したものを,起動スクリプトとして2.2節で作成したものを指定しています。またメモリ容量は試行錯誤の結果1.5GBとしました。サービスについては,次の節で述べます。
3. サービスの作成とバインド及び接続設定
本アプリはデータの永続化に DBMS を使います。DBMS については, 公式のマニュアル で MySQL について詳しく述べてあることから,今回は MySQL を使うことにしました。
3.1. MySQLサービスの作成
manifest.yml に指定したのと同じ名前でサービスを作成します。
$ cf create-service p-mysql 100mb mysql-rundeck
Creating service instance mysql-rundeck in org nota-ja / space 100 as nota-ja...
OK
3.2. アプリのアップロード及びバインド
アプリを非起動状態で push します。manifest.yml があるので,自動的に bind まで行われます。
$ cf push --no-start
Using manifest file /home/nota-ja/repos/rundecks/rundeck-jar/manifest.yml
Creating app rundeck in org nota-ja / space 100 as nota-ja...
OK
Using route rundeck.10.244.0.34.xip.io
Binding rundeck.10.244.0.34.xip.io to rundeck...
OK
Uploading rundeck...
Uploading app files from: /home/nota-ja/repos/rundecks/rundeck-jar
Uploading 2K, 7 files
Done uploading
OK
Binding service mysql-rundeck to app rundeck in org nota-ja / space 100 as nota-ja...
OK
3.3. DBMS接続及びその他の設定ファイルの作成
本アプリは DBMS の接続情報を環境変数から取得する機能がないため,通常どおり設定ファイルから読み込めるよう,ファイルを作成する必要があります。 公式サイトのマニュアル の記述に沿って,server/config/rundeck-config.properties というファイルを作成し,そこに設定を記述します。
接続情報は cf env
を使って取得します。
$ cf env rundeck
..
"VCAP_SERVICES": {
"p-mysql": [
{
"credentials": {
"hostname": "10.244.7.6",
"jdbcUrl": "jdbc:mysql://10.244.7.6:3306/cf_fefc58cd_f912_4324_9117_caa3aefb5fe1?user=32KOFnad6F1BmBJU\u0026password=77Fi15F6RNbggaKj",
"name": "cf_fefc58cd_f912_4324_9117_caa3aefb5fe1",
"password": "77Fi15F6RNbggaKj",
"port": 3306,
"uri": "mysql://32KOFnad6F1BmBJU:77Fi15F6RNbggaKj@10.244.7.6:3306/cf_fefc58cd_f912_4324_9117_caa3aefb5fe1?reconnect=true",
"username": "32KOFnad6F1BmBJU"
},
"label": "p-mysql",
"name": "mysql-rundeck",
"plan": "100mb",
"tags": [
"mysql"
]
}
]
}
}
..
併せて,アプリの正常な動作に必要と思われるサーバーURL (grails.serverURL) の設定もこのファイルで行います。
最終的に server/config/rundeck-config.properties は以下のようになりました。
$ cat server/config/rundeck-config.properties
grails.serverURL = http://rundeck.10.244.0.34.xip.io
dataSource.url = jdbc:mysql://10.244.7.6:3306/cf_fefc58cd_f912_4324_9117_caa3aefb5fe1?user=32KOFnad6F1BmBJU&password=77Fi15F6RNbggaKj
dataSource.username = 32KOFnad6F1BmBJU
dataSource.password = 77Fi15F6RNbggaKj
dataSource.dbCreate = update
rundeck.projectsStorageType = db
VCAP_SERVICES
の jdbcUrl
内にあった \u0026
は,設定ファイルの dataSource.url
では &
に置き換えています。
4. アプリのデプロイ
準備が整ったので,アプリをデプロイします。アプリケーション・マニフェストがあるので, cf push
のみでOKです。
$ cf push
Using manifest file /home/nota-ja/repos/rundecks/rundeck-jar/manifest.yml
Updating app rundeck in org nota-ja / space 100 as nota-ja...
OK
..
0 of 1 instances running, 1 starting
1 of 1 instances running
App started
OK
App rundeck was started using this command `./start.sh`
Showing health and status for app rundeck in org nota-ja / space 100 as nota-ja...
OK
requested state: started
instances: 1/1
usage: 1.5G x 1 instances
urls: rundeck.10.244.0.34.xip.io
last uploaded: Mon Nov 9 10:34:42 UTC 2015
stack: cflinuxfs2
buildpack: https://github.com/nota-ja/heroku-buildpack-runnable-jar.git#cf-100-day-challenge-095
state since cpu memory disk details
#0 running 2015-11-09 07:36:04 PM 1.1% 920.2M of 1.5G 0 of 1G
起動しました。
5. 動作確認
アプリ起動後,ブラウザーでアプリのURLにアクセスすると,ログイン画面に遷移するので,ユーザー名とパスワードを入力してログインします。デフォルトのユーザー名/パスワードは, 公式マニュアル によると admin / admin です:
【New Project+】をクリックして,プロジェクトを作成してみます。
とりあえず【Project Name】と【Description】以外はデフォルトのままです:
【Create】ボタンをクリックするとプロジェクトが作成され,プロジェクトのジョブ一覧画面に遷移します:
【Create a new Job…】をクリックして,ジョブを作成してみます。
【Job Name】と【Description】を適当に入力します:
echo
と date
を使ったコマンドを入力して【Save】します:
残りの設定は全てスキップして【Create】ボタンをクリックします:
【Run Job Now】をクリックしてジョブを実行してみます。
【Log Output】タブをクリックすると,出力が表示されます:
想定通りの出力になっていました。
以上で動作確認は終わりです。多機能すぎるのでこれ以上の確認は時間的に無理でしたが,試した範囲での動作に問題はありませんでした。
このアプリは,基本的にデータを DBMS に格納するようなので, Jenkins と違って Cloud Foundry 上でも本格利用ができるかもしれません。また当然ながら,Jenkins と同様に,簡単に試して捨てられるジョブの試験環境としても使うことができると思います。
今回使用したソフトウェア
- cf-release (v211)
https://github.com/cloudfoundry/cf-release/tree/v211
(commit hash: 2121dc6405e0f036efa4dba963f7f49b07e76ffa) - bosh-lite
https://github.com/cloudfoundry/bosh-lite/tree/552dc6869600c5350eb7ffb4fb9c9c5e79e3889d - CF CLI (v6.12.0-8c65bbd-2015-06-30T00:10:31+00:00)
https://github.com/cloudfoundry/cli/releases/tag/v6.12.0 - cf-mysql-release (v20)
https://github.com/cloudfoundry/cf-mysql-release/tree/v20
(commit hash: 8f7f6916b75a2e01332cc91df8c285dabe698703) - heroku-buildpack-runnable-jar
- 本記事で使用した版
https://github.com/nota-ja/heroku-buildpack-runnable-jar/tree/cf-100-day-challenge-095
(commit hash: 9f53c25148786f56a6380a8994acd278b305f606) - ベースにした版
https://github.com/energizedwork/heroku-buildpack-runnable-jar/tree/a736a0571ab050815c287cef5bdf74a3a6e59152
- 本記事で使用した版
- Rundeck
- http://download.rundeck.org/jar/rundeck-launcher-2.6.1.jar
- 本記事で使用した各種デプロイ用ファイルを含むリポジトリー
https://github.com/nota-ja/cf-rundeck-jar/tree/cf-100-day-challenge-095
(commit hash: 9ccc94bb77b386f8c84f4de5642dc031d0071b9c)