ユユユユユ

webエンジニアです

Digdag + Embulk を気持ちよく開発運用するためにやってみたこと

※2018/11/19投稿のQiita記事をエクスポートしたものです。

執筆背景

Digdag と Embulk による既存のバッチ処理をアップデートする機会があったのですが、あれこれつまずいて苦しい思いをしてしまいました。 あれこれ試行錯誤するに当たって、様々な方が蓄えてくださったオンラインの知見が大きな助けになりました。 この記事を読んでくださっている皆さんも何かしらの障害にぶつかっていたり、苦しい思いをされているのではないかと思いますが、私の経験がいくらかでも助けになれば素敵と思いながら執筆します。

この記事の想定読者

  • digdag のセットアップでハマってしまっている方
  • digdag + embulk の構成を検討していて、具体的な運用に関心がある方

この記事でわかること

個人的にハマった箇所に沿う形で、以下の4つの項目を解説しています。

  1. 共通の設定を一箇所にまとめたい
  2. 秘匿情報と環境変数を分けて管理したい
    1. 秘匿情報の定義
    2. 環境変数の定義
  3. Embulk の差分実行がうまくできない
  4. デーモン化したい

グローバルなパラメータを設定する方法

グローバルなパラメータは個別の .dig ファイルに記述しておいて、あとから !include : を利用して使いまわすことができます。 例として、以下は slack 通知プラグインの設定パラメータです。 同プラグインの README には、凡例として次のような設定が紹介されています。

_export:
  plugin:
    repositories:
      - https://jitpack.io
    dependencies:
      - com.github.szyn:digdag-slack:0.1.4
  # Set Reqired params
  webhook_url: https://hooks.slack.com/services/XXX/XXX/XXX
  # Set Option params
  workflow_name: slack
  ENV: develop

引用元: szyn/digdag-slack (2018/11/16時点)

上記の設定を設定ファイルとして共通化し、成功通知/失敗通知なと異なる通知で使い回せるようにしてみましょう。 シンプルに _export ブロックごと新規ファイルに切り分けてもいいのですが、可読性の観点からは以下のような形がベターです。

plugin:
  repositories:
    - https://jitpack.io
  dependencies:
    - com.github.szyn:digdag-slack:0.1.4
# Set Reqired params
webhook_url: https://hooks.slack.com/services/XXX/XXX/XXX
# Set Option params
workflow_name: slack
ENV: develop
_export:
  !include : config/slack.dig
  
+notify:
  +success:
    call>: ./templates/slack/success.yml
_export:
  !include : config/slack.dig
  
+notify:
  +error:
    call>: ./templates/slack/error.yml

この際の注意事項/ハマりポイントとしては、 設定ファイルには必ず名前空間を与えること が必要です(この場合は config/ 以下に配置すること)。 以下の公式リファレンスの !include の項目にこの規約は明記こそされていませんが、名前空間は分けられています。

筆者の場合、当初はこの規約に気づかないまま、ワークフローと同階層に設定ファイルを配置しようとして苦しんでしまいました。

参照 Workflow definition | !include another file digdagのincludeで_export | Qiita

環境によって異なるパラメータを管理する方法

digdag secrets の機能により、環境変数を定義することができます。 これによって定義したパラメータはログ等においても秘匿されるため、セキュアな運用ができるようになります。 他方で、例えば環境名 test/staging/production などといった情報を切り替えたい場合には、 secrets として定義してしまうと、ログや slack 通知に正しい値が記録されず、参照可能性が損なわれてしまいます。 かといって、実行パスや環境名といった情報をワークフロー定義にハードコーディングするのも開発速度を遅らせる原因となってしまい避けたいところです。

そこで私は以下のようにして、秘匿情報と環境変数を定義仕分けることで運用するようにしています。

秘匿情報の定義

データベースのパスワードや AWS のキーといった秘匿情報は、公式リファレンスにも記載されている digdag secrets の手順で定義しています。

{
  "pg.username": "your_name",
  "pg.password": "********"
}

上記のファイルに必要なパラメータを定義した上で、 digdag server を起動してから

$ cd config
$ digdag secrets --project <project> --set @secrets.json

とすることでサーバーで秘匿情報を保持できます。

参照 Command reference | digdag

環境変数の定義

実行環境によって異なるが実行ログには含めたいパラメータ、例えば実行環境やルートディレクトリの情報は上記の secrets とは分けて、 .dig ファイルとして管理しています。

APP_DIR: /path/to/local/digdag/repository
ENV: development

ワークフロー内でこの設定ファイルを !include しておくことで、ワークフロー側では追加の設定を必要とせずに運用することができます。
以下はその使い方の一例として紹介します。

_export:
  !include : config/env.dig
  
task:
  sh>: bundle exec rake some:task RAILS_ENV=${ENV}

tips

秘匿情報をバージョン管理システムに追加しないようにするのは言わずもがなですが、レポジトリ全体の可読性を高めるためにこれらの設定ファイルのテンプレートを作成してソースコードとして管理しています。

{
  "pg.username": "",
  "pg.password": ""
}
APP_DIR:
ENV: development

こうすることで、必要な秘匿情報のリストを一覧として管理することができ便利です。
また環境構築の際も

$ cp config/secrets.json.sample config/secrets.json
$ cp config/env.dig.sample config/env.dig

と叩いて値を埋めればすぐにでも実行できるようになります。

embulk -c による差分実行の方法

digdag から embulk を呼び出して実行する際、 -c オプションで差分情報をファイルに保存して実行することができます。

参照 Embulk 0.8.3で導入された-cオプションはLiquidを使った設定ファイルとの連携に便利 | Qiita

これによって日次のデータ連携の管理が容易になってくれるはずなのですが、 digdag からの実行の際には少々ハマりポイントがあるので解説します。

extract:
  sh>: embulk run embulk/users.yml.liquid -c embulk/diff/users.yml

上記のようなタスクを定義し、サーバーモードの digdag に実行させると、肝心の差分ファイル embulk/diff/users.yml作成されません。 これは digdag push でレポジトリをサーバーに反映させるたびに、ソースコードは新しく作成される実行ディレクトリにコピーされた上で実行されるためです。 そのため、単一の差分ファイルを指定して継続的に実行するためには embulk run の引数に 絶対パス を指定して常にオリジナルのディレクトリに差分ファイルが反映されるようにしなければなりません。

私の場合、前項で紹介した環境変数に実行パス APP_DIR を定義した上で、以下のようにリライトしました。

extract:
  sh>: embulk run ${APP_DIR}/embulk/users.yml.liquid -c ${APP_DIR}/embulk/diff/users.yml

デーモン化して /etc/init.d で管理する方法

デーモン化についてはいくつもの方法があり、それぞれ一長一短なのでしょうが、いかんせん私自身に触った経験があるのが /etc/init.d (aka rc-script) を利用したものだけであったため、そのスクリプトを紹介するに留めておきます。

参照 sato11/digdag.sh | Github Gist

補足 他の選択肢については様々な方が様々な箇所で言及しておられますため、そちらを参照していただければと思います。

蛇足かもしれませんがいくつかの記事について以下に紹介させていただきます。 Digdag serverを入れた際の躓きポイント(CentOS7対応) | Qiita - systemd による設定 CentOS6でDigdag ServerをDaemon化する - supervisor による設定

終わりに

digdag + embulk という、どちらも以前の私にとっては未知のツールを扱うにあたって、オンラインのリソースは非常に参考にさせていただいた一方で、痒いところに手が届かないなあと思う部分も大いにありました。 結果的にはその状況下で試行錯誤したことがこれらのツールへのより深い理解に繋がったという側面もあり、なんとか一つのプロジェクトとして整理することができましたので、せっかくの学びの機会ということでこのように公開させていただくことにしました。 もちろんここに記述した以外にも難儀な点は少なからずあり、その意味で網羅的な解説とは言い難いわけではありますが、皆さんにとって部分的にでも何かの助けになることができましたら素晴らしいと思っています。

ありがとうございました。