Ansible 勉強メモ (CentOS7セットアップ #2)

Ansible 勉強メモ (CentOS7セットアップ #2)
=========================================

構築内容を Ansible サーバ上に設定ファイルとして作成する 
-----------------------------------------------------------
まず "やること" を確認します。
今回は CentOS7 の初期設定として、以下のような設定をしてみたいと思います。

* hostname を "localhost.localdomain" に変更
* タイムゾーンを "Asia/Tokyo" に変更
* selinux を無効化する
* root ユーザのパスワードを既定のものに変更
* 管理ユーザ admin を作成し、パスワードを既定のものに設定
* 必要なパッケージをインストール
* 必要なサービスを起動し、自動起動を有効化する
* 不要なサービスを停止し、自動起動も無効化する
* IPv6 に関する設定を無効化する
* ネットワークインターフェース名を eth0 にし、既定の設定ファイルに差し替える
* kdump の設定を既定のものに変更
* sshd の設定を既定のものに変更
* rsyslog の設定を既定のものに変更
* logrotate の設定を既定のものに変更
* postfix の設定を既定のものに変更
* chrony をインストールし、設定を既定のものに変更
* epelリポジトリをインストールし、設定を既定のものに変更

結構ありますが、順にやっていきたいと思います。

> * hostname を "localhost.localdomain" に変更

これは localhost 用の playbook 同様 "hostname" モジュールを使います。

``` 
    - name: Change hostname
      hostname: name=localhost.localdomain
``` 

> * タイムゾーンを "Asia/Tokyo" に変更

これは "/etc/localtime" を "/usr/share/zoneinfo/Asia/Tokyo" へのシンボリックリンクに置き換えます。
使うモジュールは "file"。 "force" を yes にして、既存の "/etc/localtime" へ上書きしてしまいましょう。

``` 
    - name: Change TimeZone to Asia/Tokyo
      file: path=/etc/localtime state=link src=/usr/share/zoneinfo/Asia/Tokyo force=yes
``` 

* [file - Sets attributes of files](http://docs.ansible.com/ansible/file_module.html)


> * selinux を無効化する

"setenforce 0" をして /etc/selinux/config を書き換えることで、無効としたいと思います。
"shell" でコマンドを実行し、"relpace" でファイルを書き換えます。

"register" はモジュールの実行結果の返り値を変数に格納します。
以下では "getenfoce" の返り値を "selinux_state" へ格納し、次のタスクの実行条件としています。
"when" は渡された式が真のときのみ、そのタスクを実行するためのもので、以下は前のタスクで selinux_state に格納された返り値の内
標準出力(selinux_state.stdout) が "Enforcing" であることが、実行条件になっています。

``` 
    - name: Check SElinux status
      shell: getenforce
      register: selinux_state

    - name: Turn off SELinux (when selinux not disabled)
      shell: setenforce 0
      when: selinux_state.stdout == "Enforcing"

    - name: Disable SELinux on boot
      replace: dest=/etc/selinux/config regexp='^SELINUX=.*' replace='SELINUX=disabled'
``` 

* [Register Variables](http://docs.ansible.com/ansible/playbooks_conditionals.html#register-variables)
* [The When Statement](http://docs.ansible.com/ansible/playbooks_conditionals.html#the-when-statement)


> * root ユーザのパスワードを既定のものに変更

"user" モジュールを使うことで、ユーザの設定が変更できます。
以下では XXXXXXXX という文字列をパスワードに設定しています。

``` 
    - name: Change root password
      user:
        name: "root"
        password: "{{ 'XXXXXXXX'|password_hash('sha512') }}"
``` 

* [user - Manage user accounts](http://docs.ansible.com/ansible/user_module.html)


> * 管理ユーザ admin を作成し、パスワードを既定のものに設定

こちらも同様に、"user" モジュールを使い、ユーザの作成、設定を行います。
管理用のディレクトリを作成し、sudo 権限もつけます。

"with_items" は for のような繰り返しをするためのものです。
以下の場合は "file" モジュールが {{ item }} の箇所を "backup_cnf", "bin" にそれぞれ読み替え 2 回実行されます。 
また "creates" で指定のファイルが既に存在する場合は、"shell" の実行をスキップします。

```
    - name: Create Administrator user
      user:
        name: "admin"
        uid: 1000
        password: "{{ 'XXXXXXXX'|password_hash('sha512') }}"

    - name: Create Administration directorys
      file: path=/home/admin/{{ item }} state=directory owner=admin group=admin
      with_items:
        - backup_cnf
        - bin

    - name: Grants sudo for Administrator user
      shell: echo "%admin  ALL=(ALL)       ALL" > /etc/sudoers.d/admin
      args:
        creates: /etc/sudoers.d/admin
```

* [Loops](http://docs.ansible.com/ansible/playbooks_loops.html)


> * 必要なパッケージをインストール

初期構築時に入れておくパッケージを "yum" モジュールを使ってインストールします。

```
    - name: Install util packages
      yum: name={{ item }} state=present
      with_items:
        - telnet
        - elinks
        - whois
        - screen
        - ftp
        - expect
        - nfs-utils
        - net-snmp
        - wget
        - bash-completion
        - bind-utils
        - sysstat
        - tcpdump
        - net-tools
```

* [yum - Manages packages with the *yum* package manager](http://docs.ansible.com/ansible/yum_module.html)


> * 必要なサービスを起動し、自動起動を有効化する

"service" モジュールを使って有効化します。
ただし、今回はデフォルトで入っている場合のみ有効化し
入っていない場合は特に何もしないという風にしたいと思います。

```
    - name: Check lvm2-monitor is exist
      shell: systemctl list-unit-files | grep "lvm2-monitor" >/dev/null ; echo $?
      register: service_exist

    - name: Turn on lvm2-monitor service ( if exist )
      service: name=lvm2-monitor state=started enabled=yes
      when: service_exist.stdout == "0"

    - name: Check lvm2-lvmetad is exist
      shell: systemctl list-unit-files | grep "lvm2-lvmetad" >/dev/null ; echo $?
      register: service_exist

    - name: Turn on lvm2-lvmetad service ( if exist )
      service: name=lvm2-lvmetad state=started enabled=yes
      when: service_exist.stdout == "0"
```


> * 不要なサービスを停止し、自動起動も無効化する

前項目同様 "Service" モジュールを使い、今度は無効化します。
こちらも、インストールされていれば無効化するようにし、デフォルトで入っていない場合でも
"Service" モジュールがエラーを返さないようにします。

```
    - name: Check abrt-xorg is exist
      shell: systemctl list-unit-files | grep -w "abrt-xorg" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off abrt-xorg service ( if exist )
      service: name=abrt-xorg state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check dmraid-activation is exist
      shell: systemctl list-unit-files | grep -w "dmraid-activation" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off dmraid-activation service ( if exist )
      service: name=dmraid-activation state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check firewalld is exist
      shell: systemctl list-unit-files | grep -w "firewalld" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off firewalld service ( if exist )
      service: name=firewalld state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check kpatch is exist
      shell: systemctl list-unit-files | grep -w "kpatch" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off kpatch service ( if exist )
      service: name=kpatch state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check libstoragemgmt is exist
      shell: systemctl list-unit-files | grep -w "libstoragemgmt" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off libstoragemgmt service ( if exist )
      service: name=libstoragemgmt state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check mdmonitor is exist
      shell: systemctl list-unit-files | grep -w "mdmonitor" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off mdmonitor service ( if exist )
      service: name=mdmonitor state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check NetworkManager-dispatcher is exist
      shell: systemctl list-unit-files | grep -w "NetworkManager-dispatcher" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off NetworkManager-dispatcher service ( if exist )
      service: name=NetworkManager-dispatcher state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check NetworkManager is exist
      shell: systemctl list-unit-files | grep -w "NetworkManager" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off NetworkManager service ( if exist )
      service: name=NetworkManager state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check nfs-rquotad is exist
      shell: systemctl list-unit-files | grep -w "nfs-rquotad" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off nfs-rquotad service ( if exist )
      service: name=nfs-rquotad state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check rpc-rquotad is exist
      shell: systemctl list-unit-files | grep -w "rpc-rquotad" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off rpc-rquotad service ( if exist )
      service: name=rpc-rquotad state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check rpcbind is exist
      shell: systemctl list-unit-files | grep -w "rpcbind" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off rpcbind service ( if exist )
      service: name=rpcbind state=stopped enabled=no
      when: service_exist.stdout == "0"

    - name: Check ntpd is exist
      shell: systemctl list-unit-files | grep -w "ntpd" >/dev/null ; echo $?
      register: service_exist

    - name: Turn off ntpd service ( if exist )
      service: name=ntpd state=stopped enabled=no
      when: service_exist.stdout == "0" 
```


> * IPv6 に関する設定を無効化する

"/etc/sysctl.d/disable_ipv6.conf" が無かったら作成し、/etc/hosts の "::1" の行をコメントアウトします。
デフォルトの "/etc/hosts" は管理ディレクトリにバックアップを取得しておきましょう。

```
    - name: Disable IPv6
      shell: echo -e "net.ipv6.conf.all.disable_ipv6 = 1\nnet.ipv6.conf.default.disable_ipv6 = 1" > /etc/sysctl.d/disable_ipv6.conf
      args:
        creates: /etc/sysctl.d/disable_ipv6.conf

    - name: Create /etc/hosts backup directory
      file: path=/home/admin/backup_cnf/etc state=directory owner=root group=root

    - name: Keep default /etc/hosts
      shell: cp -a /etc/hosts /home/admin/backup_cnf/etc/hosts_org
      args:
        creates: /home/admin/backup_cnf/etc/hosts_org

    - name: CommentOut IPv6 row at /etc/hosts
      replace: dest=/etc/hosts regexp='^::1' replace='#::1'

```

> * ネットワークインターフェース名を eth0 にし、既定の設定ファイルに差し替える

"/etc/sysconfig/network-scripts" 配下のネットワークスクリプトを、"copy" モジュールを使って事前に用意したものに差し替えます。
"src" オプションに Ansible サーバ上にあるファイルを渡し "dest" には、構築対象サーバ上のパスを渡します。
今回は "/etc/ansible/roles/files/ifcfg-eth0" を用意し、これを送ることにします。

その後 grub 設定ファイルを変更し、次回起動時ネットワークデバイス名が eth0 になるように設定します。

```
    - name: Create network-script backup directory
      file: path=/home/admin/backup_cnf/etc/sysconfig/network-scripts state=directory owner=admin group=admin

    - name: Keep default network-script
      shell: find /etc/sysconfig/network-scripts -name "ifcfg*" | grep -v "ifcfg-lo" | xargs -I@@ mv @@ /home/admin/backup_cnf/etc/sysconfig/network-scripts
      args:
        creates: /home/admin/backup_cnf/etc/sysconfig/network-scripts/ifcfg*

    - name: Rename default network-script
      shell: find /home/admin/backup_cnf/etc/sysconfig/network-scripts -name "ifcfg*" | grep -v "*_org$" | xargs -I@@ mv @@{,_org}

    - name: Put new ifcfg-eth0 network-script
      copy: src=/etc/ansible/roles/files/ifcfg-eth0 dest=/etc/sysconfig/network-scripts/ifcfg-eth0

    - name: Create defarult grub backup directory
      file: path=/home/admin/backup_cnf/etc/default state=directory owner=root group=root

    - name: Keep defarult grub
      shell: cp -a /etc/default/grub /homeadmin/backup_cnf/etc/default/grub_org
      args:
        creates: /home/admin/backup_cnf/etc/default/grub_org

    - name: Check setting for ethXX in /etc/default/grub
      shell: grep "biosdevname=0 net.ifnames=0" /etc/default/grub; echo $?
      register: grub_grep

    - name: Clean "biosdevname" setting
      replace: dest=/etc/default/grub regexp="biosdevname=[0-1]" replace=""
      when: grub_grep.stdout == "1"

    - name: Clean "net.ifnames" setting
      replace: dest=/etc/default/grub regexp="net.ifnames=[0-1]" replace=""
      when: grub_grep.stdout == "1"

    - name: Setting grub ( change device name to ethXX on next boot)
      shell: sed -i "s/^\(GRUB_CMDLINE_LINUX=.*\)\"$/\1 biosdevname=0 net.ifnames=0\"/g" /etc/default/grub
      register: grub_conf_update
      when: grub_grep.stdout == "1"

    - name: Generate grub config
      shell: grub2-mkconfig -o /boot/grub2/grub.cfg
      when: grub_grep.stdout == "1" and grub_conf_update.stdout == "0" 
```

[/etc/ansible/roles/files/ifcfg-eth0]

```
TYPE=Ethernet
BOOTPROTO=none
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=yes
IPV6INIT=no
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR="10.210.104.24"
PREFIX="24"
GATEWAY="10.210.104.1"
DNS1="8.8.8.8"
```

* [copy - Copies files to remote locations.](http://qiita.com/volanja/items/54a7dbc75b909e89d8fc)


> * kdump の設定を既定のものに変更

kdump に関する設定を既定のものに書き換えます。

``` 
    - name: Keep default kdump.confn
      shell: cp -a /etc/kdump.conf /home/admin/backup_cnf/etc/kdump.conf_org
      args:
        creates: /home/admin/backup_cnf/etc/kdump.conf_org

    - name: Setting kdump
      replace:
        dest=/etc/kdump.conf regexp='#default shell' replace='default reboot'

    - name: Create defarult grub backup directory
      file: path=/home/admin/backup_cnf/etc/default state=directory owner=root group=root

    - name: Keep defarult grub
      shell: cp -a /etc/default/grub /home/admin/backup_cnf/etc/default/grub_org
      args:
        creates: /home/admin/backup_cnf/etc/default/grub_org

    - name: Setting crashkernel size
      shell: sed -i "s/\(crashkernel=\)[^ ]*/\1256M/g" /etc/default/grub; echo $?
      register: grub_conf_update

    - name: Generate grub config
      shell: grub2-mkconfig -o /boot/grub2/grub.cfg
      when: grub_conf_update.stdout == "0"
```


> * sshd の設定を既定のものに変更

sshd の設定ファイルを編集しますが
設定ファイルの編集が行われたら、サービスの reload が必要になります。

"notify" を使うと、そのタスクが実行され "change:" が返された場合
指定のハンドラタスクを、最後に呼び出すようにすることができます。

``` 
    - name: Create sshd_config backup directory
      file: path=/home/admin/backup_cnf/etc/ssh state=directory owner=root group=root

    - name: Keep default sshd_config
      shell: cp -a /etc/ssh/sshd_config /home/admin/backup_cnf/etc/ssh/sshd_config_org
      args:
        creates: /home/admin/backup_cnf/etc/ssh/sshd_config_org
    
    - name: Listen to only IPv4 address setting
      replace:
        dest=/etc/ssh/sshd_config regexp='^#ListenAddress 0.0.0.0' replace='ListenAddress 0.0.0.0'
      notify: 
        - Check syntax sshd config
        - Reload ssh daemon

    - name: Deny remote login for root user
      replace:
        dest=/etc/ssh/sshd_config regexp='^#PermitRootLogin yes' replace='PermitRootLogin no'
      notify:
        - Check syntax sshd config
        - Reload ssh daemon
``` 

上記では、設定ファイルのシンタックチェックとサービスの reload を行うよう
別途 "Check syntax sshd config" , "Reload ssh daemon"  の二つのハンドラを用意し、それを呼びだすようにします。

[handler]

``` 
    - name: Check syntax sshd config
      shell: sshd -t

    - name: Reload ssh daemon
      service: name=sshd state=reloaded
```


> * rsyslog の設定を既定のものに変更

前項目の sshd と同じように、rsyslog の設定を変更します。

```
    - name: Keep default rsyslog.conf
      shell: cp -a /etc/rsyslog.conf /home/admin/backup_cnf/etc/rsyslog.conf_org
      args:
        creates: /home/admin/backup_cnf/etc/rsyslog.conf_org

    - name: Setting rsyslog
      replace:
        dest=/etc/rsyslog.conf regexp='/var/log/{{ item }}$' replace='/var/log/{{ item }}/{{ item }}'
      with_items:
        - messages
        - secure
        - maillog
        - cron
        - spooler

    - name: Create firstboot logs backup directory
      file: path=/home/admin/backup_cnf/var/log state=directory owner=root group=root

    - name: Keep firstboot logs
      shell: cp -a /var/log/{{ item }} /home/admin/backup_cnf/var/log/{{ item }}_first_boot
      args:
        creates: /home/admin/backup_cnf/var/log/{{ item }}_first_boot
      with_items:
        - messages
        - secure
        - maillog
        - cron
        - spooler

    - name: Delete old logs path
      shell: rm -f /var/log/{{ item }}
      args:
        creates: /var/log/{{ item }}/{{ item }}
      with_items:
        - messages
        - secure
        - maillog
        - cron
        - spooler

    - name: Create new logs path
      file: path=/var/log/{{ item }} state=directory owner=root group=root
      with_items:
        - messages
        - secure
        - maillog
        - cron
        - spooler

    - name: Create empty logs file
      file: path=/var/log/{{ item }}/{{ item }} state=touch owner=root group=root
      with_items:
        - messages
        - secure
        - maillog
        - cron
        - spooler

    - name: Create defarult syslog (logrotate.d) backup directory
      file: path=/home/admin/backup_cnf/etc/logrotate.d state=directory owner=root group=root

    - name: Keep defarult syslog (logrotate.d)
      shell: cp -a /etc/logrotate.d/syslog /home/admin/backup_cnf/etc/logrotate.d/syslog_org
      args:
        creates: /home/admin/backup_cnf/etc/logrotate.d/syslog_org

    - name: Put new syslog (logrotate.d) file
      copy: src=/etc/ansible/roles/files/syslog dest=/etc/logrotate.d/syslog
      notify: 
        - Check syntax rsyslog config
        - Restart rsyslog daemon ( rsyslog not support reload ) 
```

[/etc/ansible/roles/files/syslog]

```
/var/log/cron/cron
/var/log/maillog/maillog
/var/log/messages/messages
/var/log/secure/secure
/var/log/spooler/spooler
{
    daily
    rotate 92
    nocompress
    sharedscripts
    postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    endscript
}
```

[handler]

``` 
    - name: Check syntax rsyslog config
      shell: rsyslogd -N1 2>&1 | egrep -v "version [0-9].[0-9].[0-9], config validation run|End of config validation run. Bye." | wc -l
      register: rsyslog_syntax
      failed_when: rsyslog_syntax.stdout != "0"

    - name: Restart rsyslog daemon ( rsyslog not support reload )
      service: name=rsyslog state=restarted
```


> * logrotate の設定を既定のものに変更

logrotate の実行時間を 23:59 に固定します。

```
    - name: Create defarult syslog (logrotate.d) backup directory
      file: path=/home/admin/backup_cnf/etc/logrotate.d state=directory owner=root group=root

    - name: Keep default logrotate.conf
      shell: cp -a /etc/logrotate.conf /home/admin/backup_cnf/etc/logrotate.conf_org
      args:
        creates: /home/admin/backup_cnf/etc/logrotate.conf_org

    - name: Setting logrotate
      replace:
        dest=/etc/logrotate.conf regexp='#compress' replace='compress'

    - name: move logrotate script (cron.daily)
      shell: mv /etc/cron.daily/logrotate /home/admin/bin
      args:
        creates: /home/admin/bin/logrotate

    - name: Set logrotate task at just 23:59
      shell: echo "59 23 * * * root /home/admin/bin/logrotate > /dev/null 2>&1" > /etc/cron.d/logrotate_cron
      args:
        creates: /etc/cron.d/logrotate_cron
```



> * postfix の設定を既定のものに変更

こちらも sshd, rsyslog と同様に設定変更します。

```

    - name: Create defarult main.cf (postfix) backup directory
      file: path=/home/admin/backup_cnf/etc/postfix state=directory owner=root group=root

    - name: Keep defarult main.cf (postfix)
      shell: cp -a /etc/postfix/main.cf /home/admin/backup_cnf/etc/postfix/main.cf_org
      args:
        creates: /home/admin/backup_cnf/etc/default/main.cf_org

    - name: Setting postfix ( protocols only ipv4 )
      replace:
        dest=/etc/postfix/main.cf regexp='inet_protocols = all' replace='inet_protocols = ipv4'
      notify: 
        - Check syntax postfix config
        - Reload postfix daemon

    - name: Setting postfix ( maildir enable )
      replace:
        dest=/etc/postfix/main.cf regexp='#home_mailbox = Maildir' replace='home_mailbox = Maildir'
      notify:
        - Check syntax postfix config
        - Reload postfix daemon

```

[handler]

``` 
    - name: Check syntax postfix config
      shell: postfix check

    - name: Reload postfix daemon
      service: name=postfix state=reloaded
```


> * chrony をインストールし、設定を既定のものに変更

こちらは、インストールされていなければインストールした上で
設定ファイルを書き換えるようにします。

```
    - name: install chronyd servicem ntpdate command
      yum: name={{ item }} state=present
      with_items:
        - chrony
        - ntpdate

    - name: Turn on chronyd service
      service: name=chronyd state=started enabled=yes

    - name: Keep defarult chrony.conf
      shell: cp -a /etc/chrony.conf /etc/chrony.conf_org
      args:
        creates: /etc/chrony.conf_org

    - name: Put standard chrony config file
      copy: src=/etc/ansible/roles/files/chrony.conf dest=/etc/chrony.conf
      notify: Restart chrony daemon
```

[/etc/ansible/roles/files/chrony.conf]

```
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
pool ntp.nict.jp iburst
stratumweight 0
driftfile /var/lib/chrony/drift
rtcsync
makestep 10 3
port 0
bindcmdaddress 127.0.0.1
#bindcmdaddress ::1
keyfile /etc/chrony.keys
commandkey 1
generatecommandkey
noclientlog
logchange 0.5
logdir /var/log/chrony
```

[handler]

``` 
    - name: Restart chrony daemon
      service: name=chronyd state=restarted
``` 


> * epelリポジトリをインストールし、設定を既定のものに変更

インストールした後、デフォルトでは無効にしておきます。

```
    - name: install epel yum repo
      yum: name=epel-release state=present

    - name: Create defarult epel repo file backup directory
      file: path=/home/admin/backup_cnf/etc/yum.repos.d state=directory owner=root group=root

    - name: Keep defarult epel repo file
      shell: cp -a /etc/yum.repos.d/epel.repo /home/admin/backup_cnf/etc/yum.repos.d/epel.repo_org
      args:
        creates: /home/admin/backup_cnf/etc/yum.repos.d/epel.repo_org

    - name: Setting epel repo file ( default disable )
      replace:
        dest=/etc/yum.repos.d/epel.repo regexp='enabled=1' replace='enabled=0'
```



最後に yum update をしてサーバを reboot するタスクを入れることにします。

``` 
    - name: Update all yum package
      yum: name=* state=latest
      notify:
        - OS reboot
        - Waiting for server to down
        - Waiting for server to up
``` 

ハンドラは以下のようにします。
reboot を発行した段階で、ssh が切れるため、エラー回避のために
"async: 1", "poll: 0" を設定しタスクを非同期実行します。

その後、対象サーバが一度落ちてから立ち上がる事を確認します。
"local_action" に指定されたタスクは Ansible サーバ上で実行されるため
以下では Ansible サーバから対象サーバへ ping で疎通断、再疎通を確認する動作となります。

[handler]

``` 
      - name: OS reboot
        shell: sleep 3 && reboot
        async: 1
        poll: 0

      - name: Waiting for server to down
        local_action: shell ping -c 1 target > /dev/null ; echo $?
        register: ping_state
        until: ping_state.stdout == "1"
        retries: 30
        delay:  1

      - name: Waiting for server to up
        local_action: shell ping -c 1 target
        register: ping_state
        until: ping_state.rc == 0
        retries: 30
        delay:  10
``` 



さて、長くなりましたがやることは以上です。
これを一つのファイルに書いてしまうと、管理が大変そうなので
以下のようにファイルを分割し、メインの playbook で切り出したタスク・ハンドラ は include するようにします。


こんな感じで分けて

```
* hostname を "localhost.localdomain" に変更                                     : メインの playbook にそのまま書く
* タイムゾーンを "Asia/Tokyo" に変更                                             : メインの playbook にそのまま書く
* selinux を無効化する                                                           : disable_selinux.yaml に分割
* root ユーザのパスワードを既定のものに変更                                      : setup_unix_users.yaml に分割
* 管理ユーザ admin を作成し、パスワードを既定のものに設定                      : setup_unix_users.yaml に分割
* 必要なパッケージをインストール                                                 : install_utill_packages.yaml に分割
* 必要なサービスを起動し、自動起動を有効化する                                   : enable_necessary_daemons.yaml に分割
* 不要なサービスを停止し、自動起動も無効化する                                   : disable_unnecessary_daemons.yaml に分割
* IPv6 に関する設定を無効化する                                                  : disable_ipv6.yaml に分割
* ネットワークインターフェース名を eth0 にし、既定の設定ファイルに差し替える     : setup_eth0_interface.yaml に分割
* kdump の設定を既定のものに変更                                                 : setup_kdump.yaml に分割 
* sshd の設定を既定のものに変更                                                  : setup_sshd.yaml に分割
                                                                                 : ハンドラは reload_sshd_config.yaml に分割
* rsyslog の設定を既定のものに変更                                               : setup_rsyslog.yaml に分割
                                                                                 : ハンドラは reload_rsyslog_config.yaml に分割
* logrotate の設定を既定のものに変更                                             : setup_logrotate.yaml に分割
* postfix の設定を既定のものに変更                                               : setup_postfix.yaml に分割
                                                                                 : ハンドラは reload_postfix_config.yaml に分割
* chrony をインストールし、設定を既定のものに変更                                : install_and_setup_chrony.yaml に分割
                                                                                 : ハンドラは reload_chrony_config.yaml に分割
* epelリポジトリをインストールし、設定を既定のものに変更                         : install_and_setup_epel.yaml に分割
* yum update をしてサーバを reboot                                               : メインの playbook にそのまま書く
                                                                                 : ハンドラは reboot_os.yaml に分割
```

こんな感じに配置します。

``` 
/etc/ansible/
        |------ ansible.cfg
        |------ hosts_org        ## デフォルトのものは保持しておく
        |------ hosts
        '------ roles/
                   |------ files/                              ## 構築対象のリモートホストに配置したいファイルを置く場所
                   |         |------ chrony.conf 
                   |         |------ ifcfg-eth0 
                   |         '------ syslog
                   |------ handlers/                           ## 構築中特定の状態になった時に呼び出される処理の設定ファイル
                   |         |------ reboot_os.yaml
                   |         |------ reload_chrony_config.yaml
                   |         |------ reload_postfix_config.yaml
                   |         |------ reload_chrony_config.yaml
                   |         |------ reload_rsyslog_config.yaml
                   |         '------ reload_sshd_config.yaml
                   |------ setup_CentOS7.yaml                  ## 実行する設定ファイル (playbook) の大本となるファイル
                   '------ tasks/                              ## 実行する処理を大本のファイルから切り出したもの
                             |------ disable_unnecessary_daemons.yaml
                             |------ enable_necessary_daemons.yaml
                             |------ disable_ipv6.yaml
                             |------ disable_selinux.yaml
                             |------ install_and_setup_chrony.yaml
                             |------ install_and_setup_epel.yaml
                             |------ install_utill_packages.yaml
                             |------ setup_eth0_interface.yaml
                             |------ setup_kdump.yaml
                             |------ setup_logrotate.yaml
                             |------ setup_postfix.yaml
                             |------ setup_rsyslog.yaml
                             |------ setup_sshd.yaml
                             '------ setup_unix_users.yaml
```



ではいよいよ実行してみましょう。