【連載01】206.SELinux設定Diabledを適用する為サーバを再起動する【Ansible 非同期処理】

<b><font color="#ff6633">当記事はケーススタディの連載となっています。目次は[【こちら】](http://qiita.com/CsFactoryitter/items/6b8308b96afafd61ce5f
)です。</font></b>
<b><font color="#ff6633">最新のソースコードは[【GitHub】](https://github.com/csfactorygihubblog001/blogansible)で公開中です。</font></b>
サーバの責務は<b>[こちら](http://qiita.com/CsFactoryitter/items/032cc339048e52ee3586)</b>で確認ください。

##1.サーバ再起動概要
SELinuxのDiable設定を有効にする為、サーバを一度だけ再起動する。
![image](https://qiita-image-store.s3.amazonaws.com/0/98085/0510605b-570c-c9ad-a101-9824b3ef7f18.png)

##2.playbookファイルの相関
![image](https://qiita-image-store.s3.amazonaws.com/0/98085/daf3d7f3-0121-b512-6798-e015aa7af0e5.png)

##3.playbook(site.yml)
${ANSIBLE_HOME}/site.yml
[メインとなるplaybook(site.yml)](http://qiita.com/CsFactoryitter/items/3112c6d504d3b5a58011#3%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%A8%E3%81%AA%E3%82%8Bplaybooksiteyml)参照

##4.SELinux無効化適用のplaybook(/operations/0031_reboot.yml)

\${ANSIBLE_HOME}/operations/0031_reboot.yml

```yaml:
# ===================
# SELinuxのDisable設定を有効にするため再起動する(reboot.yml)
# ===================
# ===================
# 全てのサーバのSELinuxを無効設定を有効にするため再起動
# ===================
- hosts: adminserv01
  sudo: no
  remote_user: root
  tasks:
# ===================
# getenforeにてdisableが帰ってきた場合は再起動しないため確認
# regiter: selinux_resultはshellで表すと
# selinux_result = `getenforece`
# と同様
# registerが変数名でshellが実行したコマンド
# ===================
    - name: SELinuxのDisable状態の確認
      shell: "getenforce"
      register: selinux_result
 
  # ===================
  # (shellモジュール:)2秒スリープしたのち再起動する
  #
  # (async/pollモジュール:)「async=終了まで待つ時間」、「poll=終了までチェックする間隔」
  # asyncで指定しpollでのチェック間隔で終了チェックをし続け、終わらなければエラーとなる
  # 以下の場合、poll=0を設定しており、ポーリングは行われず且つasyncの時間を待たずに完全に非同期処理となり
  # 次のタスクを実行する
  #
  # (whenモジュール:)で上記で変数指定したselinux_resultのstdout(標準出力結果)
  # がdisable以外の場合のみ再起動する(whenはif文と同様)
  #
  # ignore_errorsは全てのサーバで【 shell: sleep 2 && shutdown -r now "サーバ再起動"】が失敗しても処理を終了せず
  # 次のタスクを実行するが、今回のようなshutdownは特別でSSH接続自体が出来なくなる為、ignore_errorsは効果が出ない
  #
  # 待たずに次のタスクを行う
  # ===================
     - name: SELinuxのDisableでない場合サーバ再起動
      shell: sleep 2 && shutdown -r now "サーバ再起動"
      async: 1
      poll: 0
#      ignore_errors: true
      when: selinux_result.stdout != "Disabled"
 
# ===================
# 上記のタスクはasyncモジュールを使用しているので完了前に当該タスクが呼ばれる事になる
# wait_for
# delayの値の間待機したのち
# hostの
# portに接続できるまで1秒(デフォルト)間隔で接続しに行く
# 以下の設定では
# inventory_hostname(Ansibleが設定しているサーバ)に対して20秒待ってから
# 22ポートに対して接続を300秒間(デフォルト)待ち続ける設定になる
# ただし、当該タスクも条件(whenモジュール)に指定の
# selinux_resultのstdout(標準出力結果)
# がdisable以外の場合のみ再起動する(whenはif文と同様)
# ===================
    - name: SELinuxのDisableでない場合サーバ再起動待ち
      local_action: wait_for host={{ inventory_hostname }} port=22 delay=10
      when: selinux_result.stdout != "Disabled"
```

<dl>
<dt><font color="#0066ff">shellモジュール</font></dt>
<br>
<dd>shellを実行する。commandモジュールより直感的に扱えたりパイプが使えたりするshellの方が高機能。
</dd>
</dl>
書式:
>shell : \${実行するシェルコマンド} chdir=${シェルを実行する際に事前にcdするパス

例:

```yaml:
shell: "getenforce" 
```

<dl>
<dt><font color="#0066ff">registerモジュール</font></dt>
<br>
<dd>変数設定する。shell等のコマンドの実行結果を変数として保存。<br>
保存した変数を使用して後続タスクを実行する/しないを判断するためのキーとして使用する。<br>
<br>
shellのリターンコードを取得したい場合、<br>
<b>\${変数名}.rc</b><br>
→実行したshellのリターンコードが返る<br>
※bashでの\$?を取得した場合と同様になる。<br><br>
<b>${変数名}.stdout</b><br>
→実行したshellの標準出力が返る<br>
※bashでのaaaa = `ls(等のコマンド)`と同様になる。
</dd>
</dl>
書式:
>register: \${変数名}

例:

```yaml:
register: selinux_lisult 
```

<dl>
<dt><font color="#0066ff">async/pollモジュール</font></dt>
<br>
<dd>該当タスクを指定間隔で指定時間終了を待って次のタスクを実行する<br>
通常Ansibleはタスク内のモジュールは同期処理（そのタスクを行うすべてのサーバが完了するまで待つ）だが、asyncで秒数を指定するとその秒数まで終了を待つ。<br>
終了したかのポーリングチェックはpollに秒数を指定する。<br><br>

async=10でpoll=<font color="#ff0000"><b>1の</b></font>場合、10秒間の間中1秒毎に終了をチェックし、終了したら後続のタスクを実行する。<font color="#ff0000"><b>終了しなかった場合はエラーとなる。</b></font><br>
(ignore_errors=trueの場合はエラーでも後続処理に移動する。但しshutdown(再起動)のようなSSH接続自体が行えない場合はエラーとなる）<br><br>

async=10でpoll=<font color="#ff0000"><b>0</b></font>の場合は10という数字は無視され poll=0(処理を待たない設定)
のみ効き、<font color="#ff0000"><b>完全なバックグラウンドでの非同期処理となる</b></font>。
shutdown(再起動)を実行する場合などは何を待つ必要はない為、async=1 poll=0が良い。
</dd>
</dl>
書式:
>async: \${当該タスクの終了まで待つ時間}

例:10秒間当該タスクの終了を待つ

```yaml:
async 10 
```

書式:
>poll: \${asyncの諸元となるshellが終了しているかpolling(ポーリングチェックを行う)間隔秒数}

例:3秒毎に終了したかチェック

```yaml:
poll 3
```

<dl>
<dt><font color="#0066ff">ignore_errorsモジュール</font></dt>
<br>
<dd>エラー発生時に後続タスクを続けるかを指定する。<br>
Ansibleデフォルトでは全てのサーバでエラーが発生した場合に処理が中断する為、通常はエラーがあっても無視をする場合に使う。
</dd>
</dl>
書式:
>ignore_errors: \${true エラーが発生しても後続タスクを続行する}

例:

```yaml:
ignore_errors: true
```

以下のようなタスクを指定した場合、後続タスクは実行される。
「igonore_errors:false」又は「ignore_errors」を指定をしていない場合はエラーで終了する。

- name: 存在しないファイルのmove

```yaml:
shell: mv /afdsdfdf/fdfsd /rwrwew/fdsfsd
ignore_errors:true
```

- name: 処理続行確認

```yaml:
debug:msg="処理続行確認"
```

<dl>
<dt><font color="#0066ff">whenモジュール</font></dt>
<br>
<dd>別のタスクで定義した(regsiter)変数の状態を評価し、当該タスクを実行するか判断する。<br>
whenモジュールはshellスクリプトや多数のプログラム言語で言うところのIF文。
</dd>
</dl>
書式:
>when: \${regsiterで登録した変数 (== または =!) 状態}

例:

```yaml:
# register_varが0の場合実行
when: register_var == 0
#register_varが標準出力を伴うコマンドの時に標準出力された文字がOKの場合実行
when: register_var.stdout == "OK"
#register_varのコマンドリターンコードが0の場合実行
when: register_var.rc = 0
```

<dl>
<dt><font color="#0066ff">local_action wait_forモジュール</font></dt>
<br>
<dd>Ansibleを起動する端末(今回で言えばmanageterm)の操作を行う。<br>
「local_action」の「wait_for」は対象のサーバを待つ処理となる。
</dd>
</dl>

例:

```yaml:
local_action: wait_for host={{ inventory_hostname }} port=22 delay=10
```

<dl>
<dt>local_action</dt>
<dd>ローカルの端末での操作を行うモジュール</dd>
<dt>wait_for</dt>
<dd>接続を行うサーバ名を指定</dd>
<dt>{{ inventory_hostname }}</dt>
<dd>Ansibleがもつマジック変数で実行しているサーバ名が入る</dd>
<dt>port</dt>
<dd>接続するサーバのポート</dd>
<dt>delay</dt>
<dd>指定秒間待機した後1秒間隔でwait_forのサーバのportにSSH接続を試みる</dd>
</dl>

次回は「[Firewalldを一時的にストップする](http://qiita.com/CsFactoryitter/items/377c81f2427fa606d779)」について。

<b><font color="#ff6633">連載の目次は[【こちら】](http://qiita.com/CsFactoryitter/items/6b8308b96afafd61ce5f
)です。</font></b>