どーも、アンバサダーです。
このエントリはMackerel Advent Calendar 2020 の 20日目です。


Rundeckについては前回の記事で触れているので、興味のある方はそちらも見てください。


構成

私のプロジェクトではデプロイにRundeckのワークフローを利用するようにしている、ということを合同勉強会の発表で触れました。
そのおかげで、社外のパートナーでもRundeckのアカウントを発行すればAWSのアクセス権限を与えなくてもステージングにデプロイできるようになっています。
で、誰がいつデプロイしたのか、を確認できるようにするためデプロイを開始した時間、終了した時間、実行したアカウント名をMackerelのグラフアノテーションに投稿するようにしています。

そのあたりが発表スライドの以下のページ部分になります。
デプロイ用にEC2を構築していて、RundeckからこのEC2に対してジョブを実行するようなイメージです。
このデプロイ用のEC2にmackerelのCLIツールであるmkrをインストールしています。
なお、このEC2はデプロイのタイミングで起動するため、mackerel-agentはインストールしておらず、API Keyは環境変数として設定しています。
ちなみに、Dockerイメージのビルドとかする関係上強めのEC2を利用していますが、費用削減のためAWSのステートマネージャーとオートメーションを利用して毎日19時くらいに自動的にシャットダウンする処理を仕込んでいます。



Rundeckジョブ・ワークフロー

Rundeckは複数のジョブを直列 / 並列に実行することもできます。
そのため、私のプロジェクトでは細かい粒度でジョブを作成して、ワークフローでつなげるようにしています。
具体的なケースを紹介すると、2種類のDockerイメージを作成する必要があるので、それぞれをジョブとして作成し、その2つのジョブを並列に実行するジョブを作成、デプロイのワークフローに組み込むことでデプロイ時間の短縮をはかっていたりします。
Mackerelにグラフアノテーションを投稿する、という処理についても単独のジョブを作成して各デプロイのワークフローに組み込んでいます。
ジョブにはパラメータを設定することができ、ジョブ内のスクリプトから参照することができます。
また、各パラメータにデフォルト値をセットしておくこともできます。デプロイのジョブでは全パラメータにデフォルト値をセットしていて、実行ボタンをクリックするだけでデプロイできるように設定しています(ステージングなのでカジュアルにデプロイできていいのですが、本番はもう少し考える必要がありそうです)。

Mackerelにグラフアノテーションを投稿するRundeckジョブ

実際にどのようなジョブを作成しているかですが、グラフアノテーションのドキュメントを見ると以下を指定する必要があります。
  • タイトル
  • description(オプション)
  • 開始時刻
  • 終了時刻
  • サービス名
  • ロール名(オプション)
タイトルやサービス名、ロール名あたりは固定でも大丈夫な気もします(一応変更可能なようにパラメータにしています)。
開始時刻や終了時刻はジョブごとに変更する必要があります。
終了時刻についてはジョブの中のスクリプトで date とか使って取得してやればよさそうですが、開始時刻はジョブをキックした時刻が必要です。
ここが一番苦労したところですが、調べたところRundeckのパラメータには ${DATE:format}記法をセットすることでジョブのキック時刻が取得できることがわかりました。
しかし、Rundeck(3.0.8)のバグなのか、時刻の区切りとして「:」を指定するとパースエラーを吐いてジョブ自体がコケるので、「-」区切りで指定してスクリプト内で変換するようにしました。

実際に作成したスクリプトは以下になります。
#!/bin/bash -l
set -e

JOB_START_TIME=$(echo "@option.job_start_time@")

start_time=$(date -d "${JOB_START_TIME//-/:}" +%s)
mkr annotations create \
    --service @option.mackerel_service_name@ \
    --role @option.mackerel_role_name@ \
    --title "Deploy" \
    --from ${start_time} \
    --to `date +%s` \
    --description "by @job.username@"
ちょいちょい見慣れない記法があるのと、開始時刻の変換処理が入っている以外はごくごく普通のコマンドだと思います。
スクリプト内の @option.~~~@ という部分がジョブのパラメータを参照している箇所になります。
今回は ジョブの開始時間、Mackerelのサービス名 / ロール名をパラメータとして指定するようにしました。
タイトルは「Deploy」固定になっています。
また、descriptionに指定している 「@job.username@」というのがこのジョブをキックしたRundeckのユーザー名になります。これを投稿することで、デプロイしたのが誰かを追跡できるようにしました。

ワークフローにジョブを組み込む

デプロイジョブでは、作成した各ジョブをつないでいって、最後にグラフアノテーションを投稿するジョブで終了するようなワークフローを作成しています。
Mackerel用のジョブに開始時刻のパラメータをセットするようにしていますが、ここのパラメータでは該当のジョブがキックされた時刻になるため、ワークフローがキックされた時刻を取得する必要があります。
幸い、ワークフローのステップにジョブを指定した場合、同名のパラメータをインポートする(ワークフローに同名のパラメータがあると、子のジョブのパラメータを上書きする)オプションがあるため、これを利用することでワークフローの開始時刻が取得できます。

結果

実際に投稿されたグラフアノテーションです。
フルでデプロイ(EC2を起動→gitから最新ソース取得→ECSのタスク定義更新→2種類のDockerイメージをbuildしてECRにpush→3種類のECSサービスをデプロイ)しているので10分程度かかっていますね。

mackerel-graph-annotation

終わり

デプロイパイプラインにグラフアノテーションを投稿する処理を仕込むことで、いつ誰がデプロイしたのか、そのデプロイにどの程度時間がかかっているのかが追跡しやすくなりました。
今後はデプロイのワークフローが色々ある(全デプロイから個別のサービスのみをデプロイするようなものまで数種類)ので、どれをキックしたのかも投稿してもいいかもしれないですね。
それでは残りのAdvent Calendarも楽しみましょう!