LoginSignup
2

【Ansible備忘録1】「handler」と「notify」

Posted at

前書き

Ansibleを使う現場に参画して半年以上が経ちました。
当初は既に実装されているplaybookやroleを手順書に沿って実施するだけでしたが、徐々にplaybookやrole、host_varsなどを修正する機会が増えてきました。

その中で「はえ~なるほど:thinking:」となった知識を備忘録としてまとめます。
とは言っても熟練者からしたら「当たり前やろそんなん:angry:」くらいの内容になりますので、悪しからず。。

Ansible初学者の方が「なるほど:smile:」となれる記事になればと思います。

経緯

とある日、こんなやり取りがありました。

現場の人:「○○のファイルを更新したら、△△のサービスを再起動させてね:relaxed:
私:「かしこまり:wink:

どのファイルもGitHubで管理されているので、
①ローカルリポジトリでファイルを修正
②リモートリポジトリにプッシュ→レビュー→マージ
③playbookを実行し、更新したファイルを実機に反映
④"手動で"該当サービスを再起動
の流れで作業を進めようとしました。

この流れで良いかを作業依頼者へ確認したところ、

現場の人:「○○のファイルを更新したら△△サービスが再起動されるように作られているよ:sunglasses:

とアドバイスを貰いました。

これを知った時、
「便利~」と思いつつ、
「これがあればサービス再起動する時のあの妙なドキドキを無くせる…」
とも思いましたね。。

こんな経緯で知った「handler」と「notify」について以下に書いていきます。

"handler"と"notify"

基本、「handler」と「notify」はセットで使われます。

"notify"は「とある作業が行われた」という通知(notify) を行い、
"handler"はその通知を受け、「とある別の作業を実行する」のその作業内容を決めているものだと言えます。

今回、私が経験した例では、
○○ファイルを更新した時、△△サービスを再起動する
という流れでしたが、これを分別すると

notify→「○○ファイルを更新した時
handler→「△△サービスを再起動する

になります。

ただ、notifyの「とある作業が行われた時」というのは非常に抽象的なので、
もっと分かりやすく、そしてAnsible的に言うならば、

changedが発生した時

にhandlerに記載した動作を実行すると言えます。

今回の例では、「ファイルが更新された時」がトリガーとなりますが、
ファイル更新時だけでなく、changedが生じる作業であればトリガーとなるので、

「△△サービスのステータスが停止状態の時」

「~~ディレクトリの権限を変更した時」

などでもhandlerに記載した動作を実行するトリガーにできます。

上記の理屈でいけば、
handlerの「とある別の作業を実行する」も自由に動作内容を指定できる気がしますが、
「それなら条件式(when句)を使えば良い」
という結論になりますね。。
したがって、"handler"を使う場面としては、サービスの再起動・起動・停止という場面がほとんどかと思います。

冪等性

changedが発生した時

と上述しましたが、言い換えれば

okの時はhandlerに記載した動作は実行されない

とも言えます。

今回の例で言うならば、

「○○ファイルが更新されていない場合は、△△サービスは再起動されない」

ということになります。
何も手を加えていないのにplaybookを実行しただけでサービスが再起動されたら困りますよね:cold_sweat:

このように一回やろうが複数回やろうが、得られる結果は同じになる性質を
冪等性(べきとうせい)
と言います。

冪等性についての詳しい説明はここではしませんが、notifyの

changedが発生した時にhandlerに記載した動作を実行する

という性質は、この冪等性を保つ為に必要な性質であると言えます。

これにより、同じplaybook内に他のタスクが複数存在していても、
「○○ファイルを更新していない限り」、△△サービスが再起動されることはなくなります。
したがって、playbook内に記載された他のタスクにおいて、changedが発生する作業があっても問題はありません。

記載例

下記は「httpd.confに更新がある場合にapacheを再起動する」というタスクの記載例です。

▼tasks/main.yml

--- 
- name: Copy httpd.conf
  copy:
    src: <コピー元となるディレクトリパス>/httpd.conf
    dest: /etc/httpd/conf ←配布ノードのパス
  notify:
    - restart_apache

▼handlers/main.yml

---
- name: restart_apache
  service: 
    name: httpd
    state: restarted
    enabled: yes

後書き

ansibleに触れた当初は「何故サービス再起動されたんだ…」と不安になることもしばしばありました。:sweat_smile:
一つひとつ知識を身に着けていくことで自分の作業に“自信”を持って挑めるようになったので、構造を明確に理解することは非常に大切ということを再認識できました。

この記事を読んだansible初学者の方の“自信”に少しでも繋がれば嬉しいなと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2