EmbulkをFargateのタスクスケジューリングで定期的に実行してMySQLからS3へファイルを出力するコンテナ作った


修正中。ですます調がおかしかったりします。

構成

RDS → Fargate(embulk) → S3

メリット

動的な設定はすべてFargateの環境変数から取得するので、異なるクエリで異なるファイルに出力したいといった場合でも、Dockerをビルドし直すことなく、AWSのコンソールからFargateの新しいタスクを作成するだけで、実現可能です。

デメリット

Lambdaでもそうですが、Fargateもサーバレスなしくみなので、同時実行数が増えると、DB負荷は上がります。
短い間隔でファイル出力するタスクを複数並列で設定したら、DB負荷を気にしてあげてください。

モチベーション

RDS(Amazon Aurora≒MySQL) からS3にcsvを出力する要件があったけど、
・開発はしたくない
・バッチサーバにembulk入れたくない
・DataPipeline とかGlueを使うほどでもない
・Lambdaを作りたくない & 実行制限気にしたくない
のないない尽くしで、embulkをDockerコンテナ化して、FargateでRDSに取得しにいってS3に出力する運用にしてみました。

最近Fargateがタスクスケジューリングをサポートしたのもあって触ってみたかった。
ファーストインプレッションは設定項目たくさんあって心理的障壁高かったですが、やってみたら汎用的に使えるものができました。

AWS Fargate が時間とイベントベースのタスクスケジューリングをサポート
https://aws.amazon.com/jp/about-aws/whats-new/2018/08/aws-fargate-now-supports-time-and-event-based-task-scheduling/

意外といい感じに一連の流れがわかるような記事がなかったので、Dockerfileをリポジトリで公開してみて、Dockerhubに登録してみました。
一度一連の流れがわかれば、何となく掴めるので、この記事で少しでも心理的障壁下がればと。

embulk-from-mysql-to-s3

変数は全部環境変数を見てます。あとOSは、Amazon Linux 2 です。 Fargateで動かすし、なんとなくAmazon Linuxで揃えてみました。

https://github.com/akitana-airtanker/embulk-from-mysql-to-s3
(すみません。ファイルの拡張子と環境変数を間違えています。正しいファイル名は、config.yml.liqudです。後日修正予定です。)

Dockerhub
https://hub.docker.com/r/airtank/embulk-from-mysql-to-s3/

テスト実行

テスト実行としてローカルや開発サーバなどでコマンド実行する方法です。

githubからcloneして使う

cloneしてdocker buildして、runするだけ。あとはお好みに書き換えてもらえれば。
※ 記号とかあるときはシングルクオートでくくると良いです。クエリはスペースが含まれるのでダブルクオーテーションでくくりましょう。

git clone [email protected]:akitana-airtanker/embulk-from-mysql-to-s3.git
cd embulk-from-mysql-to-s3
docker build -t embulk-from-mysql-to-s3 .

docker run \
-e DB_HOST=xxxx \
-e DB_USER=xxxx \
-e DB_PASS='xxxx' \ 
-e DB_NAME=xxxx \
-e DB_QUERY="xxxx" \
-e S3_PREFIX=xxxx \
-e S3_BUCKET=xxxx --rm -it embulk-from-mysql-to-s3

dockerhubからpullして使う

pullして実行するだけ

docker pull airtank/embulk-from-mysql-to-s3

docker run -e DB_HOST=xxxx -e DB_USER=xxxx -e DB_PASS=xxxx -e DB_NAME=xxxx -e DB_QUERY=xxxx -e S3_PASS=xxxx -e S3_PREFIX=xxxx -e S3_BUCKET=xxxx --rm -it embulk-from-mysql-to-s3

Fargateで動かす

いよいよFargateで動かす部分です。動かすまでは設定多すぎてなんじゃこれって思ったけど、だいたいデフォルトでOK。(というか設定多すぎて面倒だったから、デフォルトのままで動くようにDockerfile作った)

ECRにpush

とりあえずECRにリポジトリ作ってpushしておきます。プライベートレジストリの認証がSecretManagerでできるようだけど、知らんです。

クラスタ作る

キャプチャ貼るので、だいたいこの通りにすればOK.



クラスタできた。

タスク定義作る



ロール設定しますが、ちゃんとS3にアクセスできるポリシーをロールにアタッチしてあげてください。ecsTaskExecutionRoleというデフォルトロールが作られますが、ちゃんと分けたロールを作ってあげたほうが実行するFargateのタスクごとに権限分離できます。

タスク定義にコンテナを追加する

ここが多分キモの部分。呼び出すコンテナとそのコンテナのつなぎのDocker周りの設定をします。

コンテナ名とリポジトリのURLを入力。メモリは適当。(ソフト制限なら超えたら勝手に拡張してくれるらしい)

結構いろいろコンテナの設定項目あるけど今回は環境変数さえ登録しておけば無問題。環境変数はここでステージングや本番のパラメータ値を入力してもいいですし、タスクのスケジューリングを設定する部分で上書きもできます。
あとの項目は全部デフォでOK。

タスクのスケジューリングを設定

左カラムからクラスタを選択して、さっき作ったクラスタを選択。
そしたら「タスクのスケジューリング」タブを選択して作成します。あとは、いい感じにネットワーク情報等を入力します。
ここで環境変数が上書きできるので、デフォルトは開発環境にして、本番用のタスクのスケジューリングは環境変数上書きという運用が楽で良さそう。

これで実行されます。スケジュールを待たずに、手動で実行を試してみたい場合は、クラスタのタスクタブからタスクを作成することで手動実行することができます。

感想

アプリケーションに依存しない定期的に動かす系システムをどのサーバで動かそうか問題に悩んでいる方はぜひ参考にしてみてください。
個人的にはFargateかなり好きになりました。(いままでも期待値高かったけど、スケジューリングとか辛そうだったのが、一気に敷居下がって好感度ウナギ登り)
あと本当はパラメータ(DBのパスワード等)は、パラメータストアやシークレットマネージャーで管理するのが正しいですが、とりあえず今回はここまで。

参考

https://qiita.com/hoto17296/items/a7d69172050fa9aab045
https://blog.amedama.jp/entry/2018/01/30/230221
https://qiita.com/kon_yu/items/7c40f4dfbd1cce006ce7
https://qiita.com/t-yotsu/items/559731aca6300eef78ec
https://qiita.com/reflet/items/5dbfcfc99d9b1edf2a3a
http://a-auto50.blogspot.com/2015/05/ossembulkmysqlcsv.html
https://qiita.com/reflet/items/beb67359d6796a0c8b78
https://qiita.com/hoto17296/items/a7d69172050fa9aab045