AWS Data Pipelineをcron代替のジョブスケジューラとして利用、AWS外のワーカーで動かす
AWS Data Pipelineをスケジューラとして使う - Qiita やクラスメソッドさんのブログなどを読み、前から気になってた AWS Data Pipeline を利用してみました。
無理やりDocker使ってますが、ワーカーを複数立ち上げるためのツールとして使ってるだけなので、Dockerはあまり関係ありません。
1日しか触ってないので、なにか間違いとかあれば、教えて欲しいです(いつものことながらすいません)
使う前の印象
- 「 … Google Cloud Dataflowみたいなやつ?」
- 「でも AWS Data Pipelineをスケジューラとして使う - Qiita とか読むと、『 Crondの代替としてスケジューラとしても使える』のかな?」
使った後の印象
「完全にCrondの代替です 本当にありがとうございました」
↑これは言い過ぎかもしれませんが。
先述した記事にもあったとおり、ShellCommandActivity というのがとても強力で、このような印象を持ちました。
以下、自分なりに説明を試みます
例えばこんなことができる
または
という感じのことが出来ます。
前者もかなり魅力的なのですが、今回は後者のシンプルなデモを示したいと思います。
Pipelineの設定
「Pipeline」とは、『一連のタスクをひとかたまりにしたもの』 みたいな理解で大丈夫だと思います。
さきに、デモにあたり、以下のポリシーをユーザにアタッチしておきます。
- AWSS3FullAccess
- AWSDataPipelineFullAccess
Pipelineを編集する画面は、謎のGUIで、architect
という名前です。architect
のなんとなくの使い方はこちら。↓ architect
はこんな感じのイメージです。
Pipelineの設定: Activity
今回設定したサンプルのActivityを見てみます。
Activityとは、Pipelineの中の中核となる処理です。
Data Pipelineでは、「Redshiftにファイルをロードする」とか「データベースをコピーする」などの便利Activityが、事前にいろいろ定義されているのですが、
今回はなんでもアリの「ShellCommandActivity
」を利用しています。
「ShellCommandActivity
」とは、「与えたシェルコマンドを実行する」というActivityのタイプの1種です。なんでもアリのすごいやつです!!!
Activity内でのその他の項目については、今回は下記のように設定しました。
Output
- アウトプットです。今回はアウトプット先はS3を指定します。
Input
- インプットです。今回は簡単にするためにインプット不要なコマンドにしたため、設定しませんでした。
Stage
- 特に
true
のままいじってませんが、true
にすると、シェルからインプット/アウトプットのディレクトリを変数として参照できるそうです。(${OUTPUT1_STAGING_DIR}
みたいな感じにして参照できる)
- 特に
Command
- 実行するシェルコマンド。
#{myShellCmd}
と書いてありますが、myShellCmd
の中身は別途パラメタとして渡しています。
- 実行するシェルコマンド。
WorkderGroup
- 実行するワーカーのグループ名です。自分で適当に命名します(あとでワーカー側にも設定します)。
RunsOn
- EC2やEMRなどのリソースを起動するときに指定します。
WorkerGroup
と両方設定した場合、RunsOn
のほうが優先されるらしいです。今回は設定しません。
- EC2やEMRなどのリソースを起動するときに指定します。
Pipelineの設定: Parameter
実行するシェルコマンド(#{myShellCmd}
)を定義しています。今回はワーカーが自分のhostnameを吐く簡単なスクリプトを用意しました。
echo "I am $(hostname)." > ${OUTPUT1_STAGING_DIR}/output.txt
Pipelineの設定: その他
他には、Schedule
で実行時刻等を、Precondition
で前提条件等を、設定できるようです。あまりちゃんと見ませんでした。省略。
Pipelineの設定: 今回の全容
今回の全容です。Exportボタンでjsonを出力できます。
{ "objects": [ { "directoryPath": "#{myS3OutputLoc}/#{format(@scheduledStartTime, 'YYYY-MM-dd-HH-mm-ss')}", "name": "S3OutputLocation", "id": "S3OutputLocation", "type": "S3DataNode" }, { "failureAndRerunMode": "CASCADE", "schedule": { "ref": "DefaultSchedule" }, "resourceRole": "DataPipelineDefaultResourceRole", "role": "DataPipelineDefaultRole", "pipelineLogUri": "s3://hoshino-sample-bucket/logs/", "scheduleType": "cron", "name": "Default", "id": "Default" }, { "output": { "ref": "S3OutputLocation" }, "stage": "true", "name": "ShellCommandActivityObj", "id": "ShellCommandActivityObj", "workerGroup": "my_worker_group", "type": "ShellCommandActivity", "command": "#{myShellCmd}" }, { "occurrences": "4", "period": "1 days", "name": "Every 1 day", "id": "DefaultSchedule", "type": "Schedule", "startAt": "FIRST_ACTIVATION_DATE_TIME" } ], "parameters": [ { "description": "S3 output folder", "id": "myS3OutputLoc", "type": "AWS::S3::ObjectKey" }, { "default": "デフォルトの値がここに入る。今回はオーバーライドするのであまり関係ない", "description": "S3 input folder", "id": "myS3InputLoc", "type": "AWS::S3::ObjectKey" }, { "default": "デフォルトのコマンドがここに入る。今回はオーバーライドするのであまり関係ない", "description": "Shell command to run", "id": "myShellCmd", "type": "String" } ], "values": { "myShellCmd": "echo \"I am $(hostname).\" > ${OUTPUT1_STAGING_DIR}/output.txt", "myS3InputLoc": "s3://hoshino-sample-bucket/input-test", "myS3OutputLoc": "s3://hoshino-sample-bucket/dir1" } }
ワーカー側の設定
次に、ワーカー側の設定です。
AWS以外でも実行できることを示すため、(なんでもいいのですが)今回はVultrVPSを使いました。
関係無いですがVultr、以下のリンクから契約していただけると私に$10分のポイントが入るのでよろしくお願い申し上げます。
また、複数個のワーカーで動くことを簡単に示すため、今回はコンテナをラクに立ち上げるためにDockerとCoreOSを使いました。
CoreOSではユーザ core
なので ホームディレクトリ(/home/core
) に AWSの認証情報credentials.json
を置きます。
今回は以下のようなcredentials.json
で動作しました。
{ "access-id": "AKIA****", "private-key": "シークレットキー", "region": "ap-northeast-1" }
次に以下の様なDockerfileを用意します。
Dockerfileで記録を残しておくと、再現性があってべんりです。
コンテナの中のOSは、なんでもいいのですが、今回は慣れてるCentOSにしました。
FROM centos RUN echo "yum update -y; yum install -y java sudo;" | sh # rootで走らせたくないのでユーザ準備する # デバッグ用途でも使うのでパスワード不要でsudoできるようにする(ほんとうはいらない) RUN useradd hoshino RUN echo "hoshino:hoshino" | chpasswd RUN usermod -g wheel hoshino; chmod o+w /etc/sudoers; echo "%wheel ALL=(ALL) ALL" >> /etc/sudoers; echo "%wheel ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers; chmod o-w /etc/sudoers; WORKDIR /home/hoshino USER hoshino # Data Pipeline用のタスクランナー(java実行ファイル)のダウンロード # see http://aws.amazon.com/developertools/AWS-Data-Pipeline/1920924250474601 RUN curl -LO "https://s3.amazonaws.com/datapipeline-us-east-1/us-east-1/software/latest/TaskRunner/TaskRunner-1.0.jar" ENTRYPOINT ["java", "-jar", "TaskRunner-1.0.jar", "--config=/var/volume1/credentials.json", "--region=ap-northeast-1", "--logUri=s3://hoshino-sample-bucket/local_logs"] CMD ["--workerGroup=my_worker_group"]
ポイントとしては
という感じです。
docker build
でイメージを作ります。イメージの名前はもちろんなんでもいいです。
$ docker build -t hoshino/taskrunner .
docker run
します。ワーカーが複数個走っても大丈夫なのを示すため、3つ走らせます。Volume(-v
)でcredential.json
が置いてある場所をコンテナと共有しています。
$ docker run --name test1 -d -v /home/core:/var/volume1 hoshino/taskrunner $ docker run --name test2 -d -v /home/core:/var/volume1 hoshino/taskrunner $ docker run --name test3 -d -v /home/core:/var/volume1 hoshino/taskrunner
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 355018eab46c hoshino/taskrunner:latest "java -jar TaskRunne 3 seconds ago Up 2 seconds test3 39cc7e823227 hoshino/taskrunner:latest "java -jar TaskRunne 8 seconds ago Up 7 seconds test2 231b5f0034c6 hoshino/taskrunner:latest "java -jar TaskRunne 12 seconds ago Up 12 seconds test1
ワーカーにあたるコンテナが、3つ走りました。
結果を見てみる
設定したDataPipelineを Activate
にして、実行してみます。
S3に出力された結果を見てみます。
hostnameが出力されています!成功です!
今回は3つのコンテナのうちの2番めのコンテナ(39cc7e823227)がスクリプトを実行したようです!
以上で今回のデモは終わりです!
まとめとか感想とか
疲れたのでまとめです。
AWS DataPipeline
は、わりとなんでもできるスケジューラ として利用できる!ShellCommandActivity
がなんでもできて強力
Activity
の設定項目でWorkerGroup
を指定すると、自前のワーカー でジョブを動かせる- (今回のパターンとは別に)「一時的にEC2インスタンスを立ててスクリプトを実行する」も簡単にできそう。
- これは
rundeck
より楽にできそう - これは時間なかったので別途。。
- 夢が広がりんぐ
- これは