AnsibleでLinuxを再起動する

# はじめに
本記事はAnsibleでLinuxを再起動する手順について記載しています。

Ansibleのrebootモジュールを利用してサーバの再起動を自動化することが目的です。
本記事では例としてRaspberryPiやdebianを使用していますが、Windowsでも実行可能です。

Ansibleの基本的から知りたい方は以前書いた、[Ansibleとは何か　構成管理ツールの目的〜Ansible導入まで最速で理解する](https://qiita.com/Brutus/items/1894629105d61f4854bc)を参照。

## Ansibleのインストール
本記事のAnsibleを実行する環境は以下になります。

- 環境   
OS：macOS Big Sur 11.1  
Python：3.7.3 

Ansibleについては[公式ドキュメント](https://docs.ansible.com/ansible/2.9_ja/installation_guide/intro_installation.html#macos-ansible)の推奨手順に従い、pipでインストールします。
`--user`オプションを指定することで管理者権限を必要としないホームディレクトリ配下にパッケージをインストールします。

- Ansibleのインストール
`$ python3 -m pip3 install --user ansible`

- 環境変数PATHの追加
`$ vi ~/.bashrc`

```bash
export PATH=$PATH:/Users/＜ユーザー名＞/Library/Python/3.7/bin/
```

- 環境変数PATHの有効化  
`$ source ~/.bashrc `

## Ansibleの設定
Ansibleを実行するために、インベントリファイルとplaybookを作成します。
本記事では例としてplaybookに`reboot_timeout`のオプションを付与していますが、再起動のみの場合は不要です。

- インベントリファイルの作成    
`sudo mkdir /etc/ansible/`  
`cd /etc/ansible/`  
`sudo vi hosts`

```text
[localhost]
127.0.0.1 ansible_connection=local

[pi]
192.168.10.111
```

- playbookの作成

```text
- name: Reboot
  hosts: pi
  gather_facts: no
  remote_user: pi
  become: true
 
  tasks:
    - name: Reboot the machine (Wait for 5 min)
      reboot:
        reboot_timeout: 300
```

rebootモジュールを使用しないでコマンドを指定することもできます。
これは古いやり方です。

```text
- hosts: pi
  become: yes
  tasks:
    - name: reboot!
      command: /sbin/shutdown -r now
```

## playbookのテスト
### RaspberryPi
Macで`ansible-playbook`コマンドを実行し、RaspberryPiを再起動します。

- playbookの実行  
`$ ansible-playbook -i hosts -k -c paramiko playbook.yml `

`ansible-playbook`コマンドを実行すると、以下の様なエラーが出る場合があります。

```console
fatal: [192.168.10.111]: FAILED! => {"msg": "to use the 'ssh' connection type with passwords, you must install the sshpass program"}
```

sshpassがないため、インストールが必要と出力されました。sshpassはスクリプトなどでSSHパスワード認証を使用するときに使われるユーティリティです。

SSHv2プロトコルを実装しているparamikoを使用することで、SSHパスワード認証のエラーを回避することができます。

paramikoをインストールしていない場合は`pip`でインストールします。

- paramikoのインストール  
`$ python3 -m pip install --user paramiko`

再度、`ansible-playbook`コマンドを実行すると、RaspberryPiの再起動ができました。

```console
SSH password: 

PLAY [Reboot] ********************************************************************************************************************************************

TASK [Reboot the machine (Wait for 5 min)] ***************************************************************************************************************
```

### debian
Macで`ansible-playbook`コマンドを実行し、debianを再起動します。

debianはVirtualBox上に構築した仮想マシンになります。
インベントリファイルに追加及び、playbookの`hosts`と`remote_user`を修正します。

`ansible-playbook`コマンドを実行すると、以下の様なエラーが出る場合があります。

```console
fatal: [192.168.10.150]: FAILED! => {"msg": "Failed to determine system distribution. sudo: パスワードが必要です, "}
```

リモートホスト側でsudo実行時にパスワードが求めれられたため、エラーが発生しました。

本エラーについてはansible実行側または、リモートホスト側の対応で回避することができます。それぞの対応方法について以下に記載します。

ansible実行側で対応する場合は、かつては`--ask-sudo-pass`のオプションが使用できましたが現在は使用することはできません。代わりに`--ask-become-pass`を使用することができます。`--ask-become-pass`の場合は2回、パスワードを入力します。

- playbookの実行  
`$ ansible-playbook -i hosts -k -c paramiko playbook.yml --ask-become-pass`

```console
SSH password: 
BECOME password[defaults to SSH password]: 

PLAY [Reboot] ********************************************************************************************************************************************

TASK [Reboot the machine (Wait for 5 min)] ***************************************************************************************************************
```

リモートホスト側で対応する場合は、`sudo`を実行するユーザーに対してパスワードなしで`sudo`を実行できる設定が必要になります。

以下はdebianユーザーのみ、`sudo`実行時にパスワードなしでも実行出来る様に設定します。
（※）本設定を適用した場合は、システムを危険にするリスクが上がるためご注意ください。

```text
%debian	ALL=NOPASSWD: ALL
```

また、以下のエラーはリモートホスト側に`sudo`がインストールされていない場合に出力されます。その場合、リモートホスト側で`sudo`をインストールする必要があります。

```console
fatal: [192.168.10.150]: FAILED! => {"msg": "Failed to determine system distribution. /bin/sh: 1: sudo: not found, "}
```

# おわりに
上記、playbookを実行することで再起動のタスクは実行できますが、結果がfailed=1になります。

必要に応じて、再起動前または再起動後にタスクを追加して確認すると良いでしょう。

## 参考
- [SSH password automation in Linux with sshpass](https://www.redhat.com/sysadmin/ssh-automation-sshpass)
- [How to automate system reboots using the Ansible reboot module](https://www.redhat.com/sysadmin/automate-reboot-ansible)