GUIから理解するDigdagチュートリアル

こんにちは。DA事業本部の春田です。

今回は、OSSのワークフローエンジン Digdag を触っていきます。Digdagのやってみた系の記事は過去にもあったので、少し趣向を変えましてGetting started — Digdag 0.9.39 documentationをベースにしながらも、GUIを切り口にしてその特徴を把握していきたいと思います。

Digdag | 特集カテゴリー | Developers.IO

セットアップ

環境: macOS High Sierra 10.13.6

Digdagをインストールする前に、Digdagで指定されているバージョン 8u72 以上のJDK8(Java SE Development Kit 8)がインストールされているかどうか確認します。なければ、公式ページからインストーラをダウンロードするなり、MacならHomebrewを使うなりしてインストールします。

If you got an error such as ‘Unsupported major.minor version 52.0’, please download and install the latest Java SE Development Kit 8 (must be newer than 8u72).

$ java -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)

その後、 ~/bin/ 配下にDigdagをインストールします。PATHも設定しておきます。

$ mkdir digdag
$ cd digdag/
$ curl -o ~/bin/digdag --create-dirs -L "https://dl.digdag.io/digdag-latest"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:04 --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:05 --:--:--     0
100 32.7M  100 32.7M    0     0  2587k      0  0:00:12  0:00:12 --:--:-- 5159k
$ chmod +x ~/bin/digdag
$ echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc

手始めに、 digdag init mydag でサンプルのワークフローを作成してみます。

$ digdag init mydag
2019-11-27 14:04:31 +0900: Digdag v0.9.39
  Creating mydag/mydag.dig
  Creating mydag/.gitignore
Done. Type `cd mydag` and then `digdag run mydag.dig` to run the workflow. Enjoy!
$ cd mydag
$ ls
mydag.dig

サンプルの mydag.dig の中身は以下のようになっていました。

timezone: UTC

+setup:
  echo>: start ${session_time}

+disp_current_date:
  echo>: ${moment(session_time).utc().format('YYYY-MM-DD HH:mm:ss Z')}

+repeat:
  for_each>:
    order: [first, second, third]
    animal: [dog, cat]
  _do:
    echo>: ${order} ${animal}
  _parallel: true

+teardown:
  echo>: finish ${session_time}

早速 digdag run mydag.dig で実行してみます。

$ digdag run mydag.dig
2019-11-27 14:06:18 +0900: Digdag v0.9.39
2019-11-27 14:06:19 +0900 [INFO] (main): Database migration started
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20151204221156
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160602123456
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160602184025
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160610154832
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160623123456
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160719172538
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160817123456
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160818043815
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160818220026
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160908175551
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160926123456
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20160928203753
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20161005225356
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20161028112233
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20161110112233
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20161209001857
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20170116082921
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20170116090744
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20170223220127
2019-11-27 14:06:19 +0900 [INFO] (main): Applying database migration:20190318175338
2019-11-27 14:06:19 +0900 [INFO] (main): Database migration successfully finished.
2019-11-27 14:06:19 +0900 [WARN] (main): Using a new session time 2019-11-27T00:00:00+00:00.
2019-11-27 14:06:19 +0900 [INFO] (main): Using session /Users/home/digdag/mydag/.digdag/status/20191127T000000+0000.
2019-11-27 14:06:19 +0900 [INFO] (main): Starting a new session project id=1 workflow name=mydag session_time=2019-11-27T00:00:00+00:00
2019-11-27 14:06:21 +0900 [INFO] (0017@[0:default]+mydag+setup): echo>: start 2019-11-27T00:00:00+00:00
start 2019-11-27T00:00:00+00:00
2019-11-27 14:06:21 +0900 [INFO] (0017@[0:default]+mydag+disp_current_date): echo>: 2019-11-27 00:00:00 +00:00
2019-11-27 00:00:00 +00:00
2019-11-27 14:06:22 +0900 [INFO] (0017@[0:default]+mydag+repeat): for_each>: {order=[first, second, third], animal=[dog, cat]}
2019-11-27 14:06:22 +0900 [INFO] (0017@[0:default]+mydag+repeat^sub+for-0=order=0=first&1=animal=0=dog): echo>: first dog
first dog
2019-11-27 14:06:22 +0900 [INFO] (0019@[0:default]+mydag+repeat^sub+for-0=order=1=second&1=animal=0=dog): echo>: second dog
second dog
2019-11-27 14:06:22 +0900 [INFO] (0020@[0:default]+mydag+repeat^sub+for-0=order=1=second&1=animal=1=cat): echo>: second cat
second cat
2019-11-27 14:06:22 +0900 [INFO] (0018@[0:default]+mydag+repeat^sub+for-0=order=0=first&1=animal=1=cat): echo>: first cat
first cat
2019-11-27 14:06:22 +0900 [INFO] (0021@[0:default]+mydag+repeat^sub+for-0=order=2=third&1=animal=0=dog): echo>: third dog
third dog
2019-11-27 14:06:22 +0900 [INFO] (0022@[0:default]+mydag+repeat^sub+for-0=order=2=third&1=animal=1=cat): echo>: third cat
third cat
2019-11-27 14:06:23 +0900 [INFO] (0022@[0:default]+mydag+teardown): echo>: finish 2019-11-27T00:00:00+00:00
finish 2019-11-27T00:00:00+00:00
Success. Task state is saved at /Users/home/digdag/mydag/.digdag/status/20191127T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.

無事に実行が完了ました。

GUIから操作する

Digdagにはサーバーが内蔵されているので、ブラウザからGUIで操作することができます。

Command reference: server-mode-commands — Digdag 0.9.39 documentation

まずは何も考えずに digdag server を実行してみます。

$ digdag server
2019-11-27 14:15:31 +0900: Digdag v0.9.39
Usage: digdag server [options...]
  Options:
    -n, --port PORT                  port number to listen for web interface and api clients (default: 65432)
    -b, --bind ADDRESS               IP address to listen HTTP clients (default: 127.0.0.1)
    --admin-port PORT                port number to bind admin api on (default: no admin port)
    --admin-bind ADDRESS             IP address to bind admin api on (default: same address with --bind)
    -m, --memory                     uses memory database
    -o, --database DIR               store status to this database
    -O, --task-log DIR               store task logs to this path
    -A, --access-log DIR             store access logs files to this path
        --max-task-threads N         limit maximum number of task execution threads
        --disable-executor-loop      disable workflow executor loop
        --disable-scheduler          disable scheduler
        --disable-local-agent        disable local task execution
        --enable-swagger             enable swagger api
    -p, --param KEY=VALUE            overwrites a parameter (use multiple times to set many parameters)
    -H, --header KEY=VALUE           a header to include in api HTTP responses
    -P, --params-file PATH.yml       reads parameters from a YAML file
    -c, --config PATH.properties     server configuration property path
    -L, --log PATH                   output log messages to a file (default: -)
    -l, --log-level LEVEL            log level (error, warn, info, debug or trace)
    -X KEY=VALUE                     add a performance system config
    -c, --config PATH.properties     Configuration file (default: /Users/haruta.takumi/.config/digdag/config)
    --version                        show client version

error: --database, --memory, or --config option is required

サーバーの立ち上げには、オプションで --database--memory--config のいずれかを指定する必要があるみたいです。データを残したいので、カレントディレクトリを --datebase に指定してサーバーを立ち上げます。

$ digdag server -o ./ -n 8081
2019-11-27 14:34:49 +0900: Digdag v0.9.39
2019-11-27 14:34:50 +0900 [INFO] (main): secret encryption engine: disabled
2019-11-27 14:34:50 +0900 [INFO] (main): Database migration started
2019-11-27 14:34:50 +0900 [INFO] (main): Applying database migration:20151204221156
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160602123456
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160602184025
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160610154832
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160623123456
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160719172538
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160817123456
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160818043815
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160818220026
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160908175551
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160926123456
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20160928203753
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20161005225356
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20161028112233
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20161110112233
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20161209001857
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20170116082921
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20170116090744
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20170223220127
2019-11-27 14:34:51 +0900 [INFO] (main): Applying database migration:20190318175338
2019-11-27 14:34:51 +0900 [INFO] (main): Database migration successfully finished.
2019-11-27 14:34:51 +0900 [INFO] (main): XNIO version 3.3.6.Final
2019-11-27 14:34:51 +0900 [INFO] (main): XNIO NIO Implementation Version 3.3.6.Final
2019-11-27 14:34:51 +0900 [INFO] (main): Starting server on 127.0.0.1:8081
2019-11-27 14:34:51 +0900 [INFO] (main): Bound on 127.0.0.1:8081 (api)

無事立ち上がりました。ブラウザのURLから http://localhost:8081 を叩くと、次のホーム画面が表示されます。

画面は WorkflowsProjects の2つで構成されており、どちらのページにも Sessions という項目が見えます。まっさらな状態からクリックできるのは New project しか見当たらないので、まずはプロジェクトから作成していきます。

新規プロジェクトを作成後、ファイル(ワークフロー)を追加できます。先ほどの mydag.dig の中身をそのまま貼り付けます。

結果、新規にワークフローとプロジェクトが追加された状態になりました。

プロジェクトは、先ほど追加したワークフローを一部として構成されています。

ワークフローの詳細画面に Run のボタンがあるので、実際に動かしてみます。

実行が完了すると、画面すぐ下の Sessions の項目にログが追加されました。 Success をクリックすると実行ログのページに飛びます。

Attempt ではワークフローの概要、 Timeline では各ジョブの実行フローとタイミングのグラフ、 Tasks では各ジョブの詳細ログが把握できます。

サーバー側のログを確認してみると、画面の Tasks と同じようなログが吐き出されていました。

2019-11-27 14:36:58 +0900 [INFO] (XNIO-1 task-14): Starting a new session project id=1 workflow name=new session_time=2019-11-27T05:36:58+00:00
2019-11-27 14:36:59 +0900 [INFO] (0059@[0:new-project-test]+new+setup): echo>: start 2019-11-27T05:36:58+00:00
start 2019-11-27T05:36:58+00:00
2019-11-27 14:36:59 +0900 [INFO] (0059@[0:new-project-test]+new+disp_current_date): echo>: 2019-11-27 05:36:58 +00:00
2019-11-27 05:36:58 +00:00
2019-11-27 14:37:00 +0900 [INFO] (0059@[0:new-project-test]+new+repeat): for_each>: {order=[first, second, third], animal=[dog, cat]}
2019-11-27 14:37:00 +0900 [INFO] (0059@[0:new-project-test]+new+repeat^sub+for-0=order=0=first&1=animal=0=dog): echo>: first dog
first dog
2019-11-27 14:37:00 +0900 [INFO] (0062@[0:new-project-test]+new+repeat^sub+for-0=order=1=second&1=animal=1=cat): echo>: second cat
second cat
2019-11-27 14:37:00 +0900 [INFO] (0060@[0:new-project-test]+new+repeat^sub+for-0=order=0=first&1=animal=1=cat): echo>: first cat
first cat
2019-11-27 14:37:00 +0900 [INFO] (0063@[0:new-project-test]+new+repeat^sub+for-0=order=2=third&1=animal=0=dog): echo>: third dog
third dog
2019-11-27 14:37:00 +0900 [INFO] (0064@[0:new-project-test]+new+repeat^sub+for-0=order=2=third&1=animal=1=cat): echo>: third cat
third cat
2019-11-27 14:37:00 +0900 [INFO] (0061@[0:new-project-test]+new+repeat^sub+for-0=order=1=second&1=animal=0=dog): echo>: second dog
second dog
2019-11-27 14:37:01 +0900 [INFO] (0061@[0:new-project-test]+new+teardown): echo>: finish 2019-11-27T05:36:58+00:00
finish 2019-11-27T05:36:58+00:00

先ほど digdag server を実行する際に、カレントディレクトリをデータベースに指定して実行しましたが、データはどこに残っているのでしょうか?確認してみます。

$ ls
digdag.mv.db    digdag.trace.db mydag.dig

GUIで作成したワークフローは、デフォルトではdigファイルとして保存されるわけではなく、 digdag.mv.db の中に格納されるようです。ということは、Digdagは何かしらのDBMSとも連携ができるということでしょうか。調べてみたところ、PostgreSQLが対応していました。

Internal architecture: database — Digdag 0.9.39 documentation

さて、カレントディレクトリに配置してあった mydag.dig は、サーバーの立ち上げによって自動でインポートされるわけではないみたいです。ファイルをサーバーに追加するには、 digdag push コマンドを実行します。

$ digdag push mydag -e localhost:8081
2019-11-27 15:49:36 +0900: Digdag v0.9.39
Creating .digdag/tmp/archive-5823894585702082404.tar.gz...
  Archiving digdag.trace.db
  Archiving digdag.mv.db
  Archiving mydag.dig
Workflows:
  mydag.dig
Uploaded:
  id: 2
  name: mydag
  revision: 6629223f-ee82-4380-a652-c46b2e1fb0ae
  archive type: db
  project created at: 2019-11-27T06:49:38Z
  revision updated at: 2019-11-27T06:49:38Z

Use `digdag workflows` to show all workflows.

mydag と命名されたプロジェクトとワークフローが追加されました。なんとなくGUIとCLIの繋がりを把握することができましたね。

感想

ファーストインプレッションでは、作りが非常にシンプルだなと感じました。参入障壁が低そうなので、簡単に導入しやすいかと思います。

.dig ファイルの中身はDigdag独自のDSLですが、YMAL拡張なので至ってシンプルです。次回はDigdagのDSLを掘り下げていきたいと思います。

参照