本記事のターゲット
- Ansible初学者
- 実務でAnsibleを使用しているエンジニア
- サービス状態の確認を自動化したい方
- サービス状態の確認を一括で行いたい方
前書き
設定変更作業などを実施した後、対象のサービスが問題なく起動しているかを確認することが多いと思います。
その際、対象のサーバに接続し、systemctl status 〇〇(サービス名)
というコマンドでサービス状態を確認しますが、下記のような場合、その確認作業が面倒に感じることもあるのではないでしょうか。
- 対象サーバが複数ある場合
- 対象サービスが複数ある場合
今回は上記の課題を解決するようなAnsibleの使い方を紹介します。
記載例
2つの例を紹介します。
ご自身の環境に合わせて選択していただければと思います。
1. commandモジュールを用いた方法
- name: サービス状態確認(commandモジュール)
command:
cmd: systemctl is-active "{{ item }}"
loop:
- httpd.service
- tomcat.service
register: check_status
failed_when: "'active' not in check_status.stdout_lines"
changed_when: false
ignore_errors: true
▼commandモジュールに関する参考資料
commandモジュールを用いた方法は、簡単に言えば「systemctl status
コマンドを実行しているだけ」です。
以下に各行の記載内容について説明します。
①cmd: systemctl is-active "{{ item }}"
command:
cmd: systemctl is-active "{{ item }}"
loop:
- httpd.service
- tomcat.service
LinuxOSでは、systemctl is-active 〇〇(サービス名)
というコマンドを実行することでそのサービスの状態のみを標準出力として返します。
(稼働中であればactive
。停止中であればinactive
。)
systemctl status 〇〇(サービス名)
でも同様の情報を取得できますが、エラー(サービスが起動していない状態)の場合、エラーメッセージが長文で表示されてしまい視認性を下げてしまいます。そのため、今回はこの状態のみという出力結果を使用します。
また、サービス名(○○の部分)が"{{ item }}"
となっていますが、ここにはloop:
配下に記載したサービスが指定されます。
「loop」と言っているくらいなので、一般的に使われるループ処理と同じように繰り返し実行されます。1行目(httpd.service)を実行後、2行目(tomcat.service)を実行します。2つ以上ある場合は最終行まで繰り返します。
今回は例として「httpd.service」と「tomcat.service」の2つを指定していますが、対象サービスを増やしたい場合は同様の書き方で追記していけば実装可能です。
②register: check_status
7行目は、上記のcommandモジュールの実行結果をcheck_status
という変数に格納しています。変数名は任意です。
この変数は次の行で使用します。
③failed_when: "'active' not in check_status.stdout_lines"
8行目は、上記のcommandモジュールの実行結果を failed
とする条件を記載しています。
中身はシンプルで、
systemctl is-active 〇〇(サービス名)
の返り値が「activeではない」場合にfailed
とする。
という感じです。
activeかどうかの判断には、7行目で指定した変数を使用します。
この変数には、「active」「inactive」などの文字列が格納されるため、その文字列を比較してok
かfailed
かの判断をしている形となります。
④changed_when: false
9行目は、上記のcommandモジュールの実行結果をchanged
にしないように設定しています。
commandモジュールは実行結果を常にchanged
にするという特性を持っています。
今回であれば、対象のサービスが起動済みであるにも関わらずchanged
にしてしまいます。 問題なく起動しているのであればok
と出力してほしいですよね。
この課題を解決するためにchanged_when: false
を指定します。
▼changed_whenに関する参考資料
▼ changed_when: false
を付けてない場合
⇒このようにサービスが起動状態でもchanged
とされてしまう。
⑤ignore_errors: true
10行目は、タスクが失敗した(エラーコードを吐いた)場合でも、Ansibleの実行を続けるために設定しています。
ignore_errors=「エラーを無視する」というわけですね。
Ansibleはタスクが失敗(エラー)した場合、そのタスク内の処理を完遂した後、後続のタスクを中止します。
今回であれば、1つ目の「httpd.service」が起動していないことでエラーとなった場合、2つ目の「tomcat.service」の状態確認までは行われますが、それ以降のタスクは中止します。
状態確認のタスクの後に何かしらのタスクを記載する場合が多いと思います。必要に応じてignore_errors: true
を設定しておくことをおすすめします。
▼ ignore_errors: true
を付けている場合
⇒failed
となっているが、後続の「後続確認用タスク」が実行されている。
▼ ignore_errors: true
を付けてない場合
⇒後続タスクを実行する前に中断されている。
▼ignore_errorsに関する参考資料
以上がcommandモジュールを用いた方法となります。
簡単に言えば、返り値の文字列を利用しているだけです。そこにfailed_whenとchanged_whenを組み合わせて出力結果を変化させているという形です。
2. serviceモジュールを用いた方法
- name: サービス状態確認(serviceモジュール)
service:
name: "{{ item }}"
state: started
loop:
- httpd.service
- tomcat.service
check_mode: true
▼serviceモジュールに関する参考資料
serviceモジュールを用いた方法は、通常の使い方を少しアレンジした形です。
serviceモジュールは、name: 〇〇(サービス名)
とstate: △△(そのサービスに対して行いたい起動処理)
を指定するのが基本的な使い方です。
上記の例であれば、「httpd.service」と「tomcat.service」を起動させる(started) という処理を行います。
ただ、今回はあくまでも「サービスの状態を確認すること」が目的なので、「起動する」という処理は不要ですよね。
そこで使用するのが check_mode: true
というオプションです。
check_mode
は、簡単に言えば「実際に実行したらAnsibleがどんな風に動くかを教えてくれる機能」です。
あくまでも動き方を検証しているだけで、実際の変更は行いません。
▼check_modeに関する参考資料
serviceモジュールの性質を活用する
serviceモジュールは、上述の記載例のようにstate: started
と指定した場合、対象のサービスが起動している場合はそのまま、停止状態の場合は起動させます。
この場合のAnsibleの実行結果は、既に起動状態の場合はok
、停止→起動の処理を行った場合はchanged
となります。
この実行結果より、changed
と出力されたサービスは元々停止状態だったことがわかります。
これを利用し、「ok
なら起動済み、changed
なら停止状態」という確認観点を設けた上で、オプションとして check_mode: true
を付与すれば、サービスの起動を行わずにサービスの状態を判別することができます。
▼実行結果例
⇒ok
なら起動中。changed
なら停止状態。
check_mode: true
が付いているため、実際には起動処理は行われていない。
serviceモジュールを用いた方法の問題点
serviceモジュールを用いた方法の問題点は、停止状態がchanged
と表示されることです。
commandモジュールでは、起動状態はok
、停止状態はfailed
と出力するようにできましたが、serviceモジュールでは停止状態はchanged
と出力されてしまいます。
「changed
の場合は停止状態」という確認観点を設ければ特に問題はありませんが、停止状態だということが一目でわかるのは赤字でfailed
と記載されている方かなと思います。
終わりに
今回は、Ansibleを用いてサービスの状態を確認する方法を2つ紹介しました。見た目的に使いやすいのは1つ目のcommandモジュールを用いた方法かなと個人的には思います。ただ、やはりcommandやshellモジュールを使うことには少し躊躇いがありますね。もっと使いやすい方法があれば良いのですが。。
というかserviceモジュールで状態確認だけを行える方法を公式から追加実装してくれれば良いだけの話ですが。。