ワークフローエンジンdigdagで困ったこと


Tresure Data社のワークフローエンジンdigdagを使っていて困ったことがあったので、それのメモ

現象

エラーとならずに1週間以上も処理が走り続けていた。

No space left on device

digdagのログを確認すると、「No space left on device」というメッセージが表示されていました。
こちらはデバイスの容量がないときに出るエラーとのことですが、今回はinodeが足りていないようでした。
incodeとはUNIX系OSで使用されるファイルシステムの名称で、ファイルの所有者やアクセス権、サイズ、作成日時、場所などを管理しているものでそれが足りていない。つまりファイル数が多すぎたようでした!

$ df -i
Filesystem            Inodes   IUsed   IUse% Mounted on
/dev/xda1            1048756 1048755   100% /

原因

ファイルが多い原因を突き止めていたところdigdagのログファイルが溜まりに溜まっているということが原因のようでした。
ログはWebで以下のように確認することができますが、実ファイルは「~/log/digdag/yyyy-mm-dd/」以下に溜まり続けます。
スケジュールJOBで毎時間2つの処理が走っていてそれが4月から溜まりに溜まって1月に限界となったようです。

対策1:ログのアーカイブ

まずはログをアーカイブしました。月に1回ぐらいしていたら問題ないと思います。
注意点としてはログのアーカイブをするとWebでログが確認できなくなります。

対策2:timeoutの設定

今回エラーに気付くのが遅れた原因として、エラーメールが飛んでいなかったためです。
エラーの際にメールが飛ぶ設定はしていたのですが、そもそもエラーとならずに走り続けていたのでメールが飛んでいませんでした。
そこでtimeoutの設定をします。60分以内に終わらなければ、エラーとし、+noticeの処理を実行後、_errorの処理を実行します。

digdag
# 60分以内に終わらなければエラー
sla:
  duration: 00:60:00
  fail: true
  +notice:
    echo>: timeout err!!

_error:
  mail>: tmpl/error_timeout.txt
  subject>: timeout error!!
  to: [[email protected]]

追記:timeoutの処理

実際に上記で試していたらslaでfail:trueとしても処理自体は止まらないみたいです。

digdag
# 60分以内に終わらなければエラー
sla:
  duration: 00:60:00
  fail: true
  +notice:
    echo>: timeout err!!

+task:
  #処理の途中で60分を超えても
  #notice処理をしてから戻ってくる

_error:
  mail>: tmpl/error_timeout.txt
  subject>: timeout error!!
  to: [[email protected]]

そこで強制終了の処理を無理やり入れました。強制終了は

$ digdag kill <attempt-id>

で可能です。ただdigdagではsession-idは取得できるもののattempt-idは取得できません。(そもそもsessionは取れてattemptが取れないってどうなのと思いますが。。。)
そこでshで取得します。また強制終了をすると_errorの処理が走らないので、強制終了の前にメールを送信しておきます。

digdag
# 60分以内に終わらなければエラー
sla:
  duration: 00:60:00
  fail: true
  +notice:
    +mail:
      mail>: 
        data: timeout error
      subject: ERROR!! timeout error (session:${session_id})
      to: [[email protected]]
    +kill_task:
      sh>: tasks/_kill_job.sh ${session_id}

    echo>: timeout err!!

+task:
  #省略
_kill_job.sh
#!/bin/sh

session_id=$1
get_attempts=`digdag attempts ${session_id}`

echo $get_attempts

is_attempt=0
is_id=0
for i in $get_attempts; do

  if [ $is_attempt -eq 1 ] && [ $is_id -eq 1 ]; then
    attempt_id=$i

    #複数回処理をしている場合が、あるので初期化しておく
    is_attempt=0
    is_id=0
  fi

  if [ $i = "attempt" ]; then
    is_attempt=1
  fi
  #attempt idと続く場合にフラグを立てる
  if [ $is_attempt -eq 1 ] && [ $i = "id:" ]; then
    is_id=1
  fi
done

echo $attempt_id

digdag kill $attempt_id

shellはほぼ初めて書いたので、お粗末ですが、ご了承ください。

参考

No space left on device とエラーが出るときの対処法
「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
digdagのsla/fail/error/waitについてのメモ