概要
あるところからデータの塊を取ってきて何らかの解析にかけたい.それらを GCP (Google Cloud Platform) で行いたいが,インスタンスの設定やファイルのダウンロード,アップロードが面倒.そんな時に使える Dockerコンテナイメージを作った.
なお,ここでの処理は,毎日ログデータを深夜に処理するなどのバッチ処理を考える.ストリーム処理には向かない.
Roadie-GCP
GCP でプログラムを実行する時に使える補助コンテナ.必要なファイル,処理内容,実行結果の保存先などをまとめた YAML スクリプトファイルを渡せば後はうまくやってくれる.なおベースイメージは Ubuntu である.
スクリプトファイル名が conf.yaml
の場合,実行方法は次の通り.
$ docker run -i jkawamoto/roadie-gcp < conf.yml
なお,このコンテナは実行が終わり,結果をアップロードし終わるとインスタンスを削除する.そのため,インスタンスの作成時に https://www.googleapis.com/auth/compute
スコープを指定する必要がある.この挙動を変える場合には --no-shutdown
オプションを指定する.
スクリプトファイル
スクリプトファイル conf.yaml
は apt
, source
, data
, run
, result
, upload
の6要素を定義するYAML ファイル.それぞれ,プログラム実行に必要な apt パッケージ,プログラムのソースファイル,プログラムの実行に必要なデータファイル,プログラム実行手順,実行結果の保存先,そして実行結果のファイルパターンを定義する.script.yml
は次のような形になる.
apt:
- unrar
source: https://github.com/abcdefg/some-program.git
data:
- http://mmnet.iis.sinica.edu.tw/dl/wowah/wowah.rar
run:
- unrar x -r wowah.rar
- ./analyze WoWAH
result: gs://somebucket/
upload:
- "*.png"
このスクリプトファイルは,次のことを指示している.
- apt-get で
unrar
パッケージをインストールする. - GitHub からソースコードをダウンロードする.
- プログラムの実行に必要なファイルをウェブから取得する.
- 次の二つのコマンドを実行する.
- unrar で取得したファイルを解凍.
- 自前の解析プログラムを実行する.
- Google Cloud Storage のバケットを出力の保存先として設定する.
- 解析プログラムが作成した *.png ファイルを (5) で設定したバケットにアップロードする.
apt
apt
要素では,apt-get でインストールするパッケージのリストを指定する.特にインストールすべきパッケージがない場合は省略可.
source
source
要素には,実行するプログラムのソース URL を指定する.URLは次の形式をサポートしている.
- URLが
.git
で終わっていれば,Gitリポジトリと判断してクローンする. - URLが
dropbox://
で始まっていれば,
Dropbox からダウンロードする.
この URL は Dropbox のパブリックリンクの先頭をhttps://
からdropbox://
に変えたものになる. - URLが
gs://
から始まっていれば,Cloud Storage からダウンロードする. - それ以外では,
http://
とhttps://
をサポートする.
どの場合でも,URLが .zip
, .tar
, .tar.gz
で終わっていれば適切に解凍される.ダウンロードしたソースは /data
に展開される.
data
data 要素では,実行前に取得するファイルをリスト形式で記述する.リストの各要素は,URL:保存先
の形をとる.
URLスキームには,http
, https
の他 Google Cloud Storage を表す gs
,Dropboxの公開リンクを表す dropbox
が使用できる.
保存先には絶対パス,相対パスどちらも使用できる.パスが /
で終わっている場合は,指定されたディレクトリ内にURLが示すファイル名で保存する.逆に,パスが /
で終わっていない場合は,当該ファイル名に変更して保存する.
なお,デフォルトのディレクトリは /data
である.
data:
- http://sample.com/input.json
- gs://a-project/input/data:/tmp/
上記の例では,http://sample.com/input.json を /data/input.json
として保存し,Cloud Storage の a-project バケットにあるオブジェクト input/data を /tmp/data
として保存する.
最終的に保存されるファイルの拡張子が .zip
, .tar
, .tar.gz
の場合,展開される.この挙動を変える場合,--no-unzip
オプションを使用する.
run
実行するコマンドのリスト.上から順に実行していく.
各コマンドの標準出力は記録される.先頭コマンドの標準出力は stdout0.txt
,次のコマンドの標準出力は stdout1.txt
というように番号付けられ,result
で指定した場所へ保存される.標準エラー出力はコンテナの標準出力としてコンテナ外に出力される.したがって,処理結果など記録しておくべきものは標準出力に,実行時のログなどは標準エラー出力に書き出せば良い.
なお,標準出力の結果は /tmp/
に保存されるので,他のプログラムから利用することもできる.次の例は,/tmp/data
を引数に run.sh
を実行し,その標準出力の結果 /tmp/stdout0.txt
を引数に次のコマンド plot.sh
を実行している.
run:
- ./run.sh /tmp/data
- ./plot.sh /tmp/stdout0.txt
なお,apt パッケージ以外でプログラムの実行に必要なパッケージがある場合は,run
セクションに書けば良い.
result
result
セクションには,Cloud Storage の URL を指定する.そこに標準出力及び upload
セクションで指定したファイルがアップロードされる.
upload
upload
セクションには,Globパターンのリストを指定できる.ここで指定したパターンのいずれかにマッチしたファイルも,実行結果として result
セクションで指定した Cloud Storage のバケットへアップロードされる.
result: gs://a-project/result/
upload:
- "*.out"
上記の例では,gs://a-project/result/
に stdout0.txt
,stdout1.txt
に加えて /data/*.out
にマッチするファイルもアップロードする.
Roadie-GCP イメージの拡張
実行するプログラムの準備や必要なライブラリのインストールは,apt
や data
, run
を使えば行える.しかし,毎回同じ処理を行う場合,準備済みの Docker イメージを作成しておく方が早い.
例えば,次のような Dockerfile でイメージを作っておけば再利用しやすい.
FROM jkawamoto/roadie-gcp
# NumPy, SciPy, Matplotlib のインストール
RUN apt-get update && \
apt-get install -y python-numpy python-scipy python-matplotlib
# matplotlib の設定
RUN mkdir -p /root/.config/matplotlib && \
echo "backend: Agg" >> /root/.config/matplotlib/matplotlibrc
# 実行ファイルをコピー
ADD some_dir /root/
GCP インスタンスの作成と Roadie-GCP の実行
gcloud
コマンドを使ってインスタンスを作成し実行する.Roadie-GCP イメージを拡張した jkawamoto/run
というイメージが dockerhub にあるとする.
まず,script.yml を出力するスタートアップスクリプトを用意する.
#!/bin/bash
cd /root
cat <<EOF > script.yml
apt:
- unrar
source: https://github.com/abcdefg/some-program.git
data:
- http://mmnet.iis.sinica.edu.tw/dl/wowah/wowah.rar
run:
- unrar x -r wowah.rar
- ./analyze WoWAH
result: gs://somebucket/
upload:
- *.png
EOF
docker run -i jkawamoto/running < conf.yml
次に,gcloud コマンドでインスタンスを作成する.
$ gcloud compute --project "your_project_name" instances create "some_name" \
--zone us-central1-b --image coreos --metadata-from-file startup-script="./startup.sh" \
--machine-type "n1-standard-1" \
--scopes=https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/devstorage.read_write
結果を Cloud Storage にアップロードし,インスタンスを削除するために,
の権限が必要になる.
おわりに
Roadie-GCP を使えば,比較的簡単にバッチ処理が行えると思う.特に処理が終わったらインスタンスを削除させるので,無駄にコストを払わなくて済む.
もっと自動化するためには,スタートアップスクリプトを自動生成したり,コンテナのログを Cloud Logging へ投げることも考える必要がある.それらを代わりに行ってくれる アプリケーション も作成してある.
このアプリについては別の記事にまとめようと思う.