割と大量のデータを別の場所に転送したい。といった要件があり、諸々模索している最中で、先輩から教えてもらったEmbulkを触ってみたのでまとめました。
Embulkとは
GitHub - embulk/embulk: Embulk: Pluggable Bulk Data Loader.
さまざまなストレージ、データベース、NoSQL、クラウドサービス間のデータ転送を支援する並列バルクデータローダーです。
関数を追加するプラグインをサポートしており、インプット先/アウトプット先に沿ったプラグインを適宜使用する/作成することで、前述の様々なストレージやDBなどでデータ転送を行うことができます。
インストール
Brewでインストール可能です。
$ brew install embulk
# embulk: Java 1.8 is required to install this formula. と言われたらエラー文通り下記でJava入れてもう一回
$ brew cask install homebrew/cask-versions/adoptopenjdk8
必要だなと思ったプラグインをプラグイン一覧から確認してインストール。
# CSVインポート
$ embulk gem install embulk-input-jdbc
# mysqlインポート
$ embulk gem install embulk-input-mysql
# mysqlアウトプット
$ embulk gem install embulk-output-mysql
# などなど
チュートリアル
公式ドキュメントに乗っている、めちゃくちゃ簡単な動作確認チュートリアルです。
CSVを読み込んで画面に表示するだけの簡単なものになっています。
# サンプルCSVファイル、構成ファイルを作成
$ embulk example ./try1
# 推測プラグインを呼び出して適切な構成ファイル(提案)を出力。
$ embulk guess ./try1/seed.yml -o config.yml
# インプット側から引っ張ってこれるデータを確認
$ embulk preview config.yml
# 実行!(csvから読み込んで画面に表示するだけ)
$ embulk run config.yml
Embulkではバルクデータロードを定義するために、yamlファイルを使います。
サンプルはこんな感じ:
in: # インプットプラグインオプション
type: file
path_prefix: ./mydata/csv/
decoders:
- {type: gzip}
parser:
charset: UTF-8
newline: CRLF
type: csv
delimiter: ','
quote: '"'
escape: '"'
null_string: 'NULL'
skip_header_lines: 1
columns:
- {name: id, type: long}
- {name: account, type: long}
- {name: time, type: timestamp, format: '%Y-%m-%d %H:%M:%S'}
- {name: purchase, type: timestamp, format: '%Y%m%d'}
- {name: comment, type: string}
filters:
- type: speedometer
speed_limit: 250000
out: # アウトプットプラグインオプション
type: stdout
Liquidテンプレートエンジン を使用してこの構成ファイルに環境変数を埋め込むこともできるけど、実験的な機能なので変更される可能性があるとのこと。
また、同じように別の構成ファイルを含めることもできるらしいです。
これらのためにテンプレートエンジンを使用するには、設定ファイルの末尾をyml.liquid
にする必要があります。
(今回はこの二つは割愛)
embulk-input-dynamodbをローカルから試してみる
プラグインを作ってくださっている方がいらっしゃったので使わせていただきました!
GitHub - lulichn/embulk-input-dynamodb
構成ファイル
なぜかauth_method : env
とauth_method : profile
は上手く行かなかったので(後述)、ローカルでの動作確認時は直書きのauth_method : basic
でやってます。
IAMロールが設定されているものの上で動かすのであれば、credentials情報などは不要らしいです。
in:
type: dynamodb
auth_method: basic # IAMロールが設定されていればこの辺りは不要
access_key_id: *** # 同上
secret_access_key: *** # 同上
table: dynamodb-table-name
region: ap-northeast-1
scan:
total_segment: 20 # 要確認
scan_limit: 10000
record_limit: 10
columns:
- {name: user_id, type: long}
- {name: name, type: string}
out:
type: stdout # 画面に出力する
embulk preview
でインプット内容を確認します。
(今回は画面上にアウトプットするだけなので、embulk run
でも大丈夫だと思います)
$ embulk preview config.yml
# 上記でplugin is not found 的なエラーが出た時は下記を実行(<>内は適宜書き換えて下さい)
$ embulk preview -I /Users/<user>/.embulk/lib/gems/gems/embulk-input-dynamodb-<varsion>/lib config.yml
無事指定したテーブルの項目が表示されたら成功です!
ハマったところ
実行時にInputPlugin 'dynamodb' is not found
になる
最初は以下の方法でpreviewしようとしていましたが、エラーが出てしまいました。
$embulk preview config.yml
エラー:
Error: InputPlugin 'dynamodb' is not found.
org.jruby.proxy.org.embulk.config.ConfigException$Proxy1: Unknown input plugin 'dynamodb'. embulk/input/dynamodb.rb is not installed. Run 'embulk gem search -rd embulk-input' command to find plugins.
インストールはしているはずだけど、もしかして見にいっている場所が違う?と思ったら割とビンゴでした。
この実行時のログではGem's home and path are set by default: "/var/root/.embulk/lib/gems"
と出ていて、プラグインをインストールした先(私の場合は/Users/<user>/.embulk/lib/gems/
)とは異なる場所を参照していたため、そんなものはない!と認識されてしまっていたようです。
そのため、最初の一回は使用しているプラグインのパスを明示的に渡してあげる必要があります。
$embulk preview -I /Users/<user>/.embulk/lib/gems/gems/embulk-input-dynamodb-<varsion>/lib config.yml
一度実行が通ってくれた後は、Gem's home and path are set by default
が上記で設定したパスの方を見にいってくれるようになり、$ embulk preview config.yml
でも実行できるようになりました。
AWS認証情報渡す部分
embulk-input-dynamodb
ではAWS認証情報を受け取る方法を選ぶことができるのですが、やってみようと思ったenv, profile
でエラーが発生し、トラブルシューティングがしきれなかったので一旦上記のbasic
で試しました。
(結構初歩的な部分でつまづいている気もするました……)
最初profile
でAWS認証情報を取得しようとした構成ファイル:
in:
type: dynamodb
auth_method: profile
profile_file: ~/.aws/credentials
profile_name: default
table: dynamodb-table-name
region: ap-northeast-1
# 以下同じ
エラー:
Error: java.lang.IllegalArgumentException: ~/.aws/credentials
**追記:**こちらご指摘いただいて解決しました!ありがとうございます!
yamlファイルでは~/.aws/credentials
の~
の部分を解決してくれないので(これはシェル側の機能)、明示的に渡してあげる必要があります。
絶対パスで記述し直すか、環境変数を使用して~
の部分を渡してあげる形にすると通るようになります。
次env
で認証情報を取得しようとした構成ファイル:
in:
type: dynamodb
auth_method: env
table: dynamodb-table-name
region: ap-northeast-1
# 以下同じ
エラー:
Error: Unable to load AWS credentials from environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or AWS_SECRET_ACCESS_KEY))
($env
で確かめてみたけどちゃんと環境変数には定義できていた)
まとめ
めちゃくちゃ触りだけをやりましたが、Embulk素敵ですね。
あとはこれをAWS上で定期実行するためにどうするかを調べて行こうかなと思います。