AWXサーバの外からansibleでジョブを実行する
この記事は MicroAd Advent Calendar 2021 の20日目 と Ansible Advent Calendar 2021 - Adventarの 7日目の記事です(空いててもったいないので埋めました)。
はじめに
以下の記事の補足になります。
yassan.hatenablog.jp
yassan.hatenablog.jp
PRをベースとしたダッシュボード運用をしていると任意のタイミングでリポジトリの状態とダッシュボードを同期したい場合が出てきます。
例えば以下。
- CIジョブが失敗して再実行したい
- 本番ダッシュボードを削除・壊して復元できない
上記などの状況からどうしても同期取りたい場合が出てきます。
その場合、空コミットを追加しPR作成することで同期できますが、コミットログも汚れてしまいます。
また、ローカルからansible-playbookコマンドを実行する場合、Vault変数を復号するために復号用パスワードが必要になります。
その場合、Grafana運用者以外のユーザにも復号用パスワードを公開することになり具合が悪いです。さらに、ローカルから実行してしまうと「いつ・誰が・何を」と言った大事な実行履歴も残らないので困りものです。
そこで、AWXのジョブテンプレートを用意して、ユーザ及びCIサーバからの実行をAWX経由で実行するようにしてみます。
環境
前提となる環境は以下の通りです。
- ansible-core v2.11(v2.9でも動きます)
- AWX v13.0.0 (多分、v13以降でも大丈夫)
- Jenkins(CircleCIやGitHub ActionsでもOK)
概要
今回は以下のAnsible Collectionの awx.awxを使います。
こちらを利用することで、CIサーバからAWXのジョブを実行出来るようになります。 また、AWXにジョブを作成する事でAWXのWebUIからユーザーが任意のタイミングで実行も可能になります。
前準備
AWXのCollectionを利用できるようにするためのセットアップを行います。
まず、 collections/requirements.yml
に以下のようにして追加。
--- collections: - name: awx.awx version: "13.0.0" # 利用しているAWXに合わせて指定
上記のversionは、 galaxyの awxのページ の Install Version
にあるドロップダウンリストのVersionを指定してください。
また、指定するVersionは、利用しているAWXのVersionに合わせて近いものを使うのが良いです(互換性の問題を回避する目的で)。
collections/requirements.yml
に定義するのは、AWXがデフォルトで参照するCollectionのパスとなっています1。
また、ローカルで実行したい場合は以下のコマンドでinstall出来ます2。
# ansible-core v2.11以降 ansible-galaxy collection install -r collections/requirements.yml
Playbookの作成
awx_launch_job.yml
を以下の様に作成します。
--- - hosts: "{{ grafana_group }}" gather_facts: false connection: local tasks: - name: ジョブの起動 awx.awx.tower_job_launch: # v19の場合は tower_job_launch→job_launch tower_host: "{{ awx_host }}" tower_username: "{{ awx_user }}" tower_oauthtoken: "{{ vault_awx.awx_oauth_token }}" name: "{{ job_name }}" extra_vars: revision: "{{ revision }}" grafana_group: "{{ grafana_group }}" register: job - name: "Wait for job max {{ job_timeout }}s" awx.awx.tower_job_wait: # v19の場合は tower_job_wait→job_wait tower_host: "{{ awx_host }}" tower_username: "{{ awx_user }}" tower_oauthtoken: "{{ vault_awx.awx_oauth_token }}" job_id: "{{ job.id }}" timeout: "{{ job_timeout }}"
モジュール awx.awx.tower_job_launch
を使うことでAWXのジョブを実行出来ます3。
また、 awx.awx.tower_job_wait
を使って待っているのは、CIジョブを以下の順番で実行するので、各ジョブが終わるのを待ち合わせするために設定しています4。
import-datasources
import-notification-channels
import-dashboards
どちらのモジュールでも利用している tower_oauthtoken
に指定する値は、事前にVaultの暗号化変数として{{ vault_awx.awx_oauth_token }}
に格納します5。
また、実行する際は、Makefileに以下を定義して実行を簡略化します。
SHELL=/bin/bash REVISION := $(shell git rev-parse --short HEAD) # Grafanaにダッシュボードを反映する # AWX job: grafana-import-dashboard を実行する # 例: make import-dashboards group=prod .PHONY: import-dashboards import-dashboards: ansible-playbook -i inventories/inventory \ --vault-id .vault_password \ awx_launch_job.yml \ --extra-vars role_name=import_dashboard \ --extra-vars job_name=grafana-import-dashboard \ --extra-vars grafana_group=$(group) \ --extra-vars revision=$(REVISION) \ --extra-vars job_timeout=600;
※他にも role_name
や job_name
を変更して他のロール分(import-datasources
やimport-notification-channels
)も定義します。
AWX側の設定
以下のようにしてAWXからジョブテンプレートを作成します。
また以下は import_dashboard
の分ですが、別途、他のロール分(import-datasources
やimport-notification-channels
)も作成します。
注意点としては、上図の右下隅にある「起動プロンプト」にチェックを入れないと実行出来ないので忘れずにチェックしてください。
また、手動で実行したい場合は、追加変数に grafana_group
と revision
を追加して実行してやればOK。
CI側のフローの設定
特に前回から変更は無いです。Makefileでダッシュボードやデータソース、通知チャンネルのimportを実行するMakeターゲットをAWXジョブからの実行に変更しているので特にここでは変更点がありません。
詳細は前回の記事を参照して下さい。
最後に
これでPRを使わずに実行履歴を残しつつダッシュボードの更新が出来るようになりました。
とは言え、PRベースに更新出来ないのでレビューが出来ず、また、更新意図を残せないのであくまで緊急事態用というところです。
全体を通した今後の改善点
現状、Grafanaのダッシュボード・データソース・通知チャンネルを毎回すべて更新してしまいます。 理想的には更新を検知して、更新ファイルだけ反映するような対応があるとより早く同期できたりします。 ただ、git diffで更新差分を使うアイディアもあるのですが差分をキレイに出すのが難しいです6。
他にも、今回の仕組みではダッシュボードを削除する仕組みが無いので、リポジトリから削除して後、GrafanaのWebUIから手動で削除する必要があるので若干面倒です。
改善ポイントについて良案があれば是非教えて下さい!
-
詳細は 14. Projects — Ansible Tower User Guide v3.8.5 を参照。
また、 GitHubのAWXのdoc にも説明があるので参考になります。↩ -
ansible-core v2.11未満の場合は、
install
オプションに-f
がないと2回目以降でエラーになります。
ただし、 ansible/ansible#65699 にて検討されて、ansible/ansible#73336で、v2.11より-u
オプションが追加されています。↩ -
パラメータの詳細は awx.awx.job_wait を参照下さい。↩
-
パラメータの詳細は awx.awx.job_launch を参照下さい。↩
-
この辺の説明は前回の記事を参照して下さい。
yassan.hatenablog.jp↩ -
mainブランチとの差分を使うと後から作成したPRを先にマージすると差分を取れなくなる問題があります(rebaseしたら治りますけど)。↩