[Ansible]複数ノードを一括でshutdownする

#はじめに
Kubernetesの検証をしているのですが、PC上のVM環境ですので毎日終わった後にクラスタノードをshutdownしています。Masterノード1台、workerノード2台の計3台なのですが、各サーバにログインして、shutdownするのが地味に面倒でした。
そこで、今回はAnsibleを使って複数ノードを一括でshutdownできるようにしたいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/4640c0e5-f1c3-7a6e-1142-ca95537ef5ab.png)

わざわざAnsible使わなくてもいいと思うのですが、せっかくなので使ってみようかなと。

#Ansibleのインストール
GatewayサーバにAnsibleをインストールします。

```
# cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
# yum install ansible
読み込んだプラグイン:fastestmirror, langpacks
Determining fastest mirrors
・・・
インストール:
  ansible.noarch 0:2.9.9-1.el7
・・・
依存性関連をインストールしました:
  python-babel.noarch 0:0.9.6-8.el7    python-cffi.x86_64 0:1.6.0-5.el7          python-enum34.noarch 0:1.0.4-1.el7     python-httplib2.noarch 0:0.9.2-1.el7
  python-idna.noarch 0:2.4-1.el7       python-jinja2.noarch 0:2.7.2-4.el7        python-markupsafe.x86_64 0:0.11-10.el7 python-paramiko.noarch 0:2.1.1-9.el7
  python-pycparser.noarch 0:2.14-1.el7 python2-cryptography.x86_64 0:1.7.2-2.el7 python2-jmespath.noarch 0:0.9.4-2.el7  python2-pyasn1.noarch 0:0.1.9-7.el7
  sshpass.x86_64 0:1.06-2.el7

完了しました!

# ansible --version
ansible 2.9.9
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/kosuke/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Apr  2 2020, 13:16:51) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
```

##初期設定
操作する対象ノードを/etc/ansible/hostsファイルに記載します。

```:/etc/ansible/hosts
・・・
# Here's another example of host ranges, this time there are no
# leading 0s:

## db-[99:101]-node.example.com

[k8s] #任意のグループ名
k8s-master #グループに属する対象サーバのホスト名、IPアドレス
k8s-worker01
k8s-worker02
```
なお、各サーバにはGatewayサーバの公開鍵を渡して、sshのパスワードなしでログインできるようにしてあります。

#パスワードの設定
shutdownコマンドを実行する際には、各サーバのrootパスワードが必要になります。
Ansibleでパスワードを設定するにはいくつか方法があるようなのですが、今回は平文で書いたパスワードを暗号化して、playbook実行時に指定するようにします。

##パスワードファイルの作成と暗号化
最初に平文でファイルを作成し、ansible-vaultコマンドで暗号化します。

```
$ vi passwd.yaml
$ ansible-vault encrypt passwd.yaml
New Vault password:
Confirm New Vault password:
Encryption successful
$ cat passwd.yaml
$ANSIBLE_VAULT;1.1;AES256
61653537356139333833333230306466396533646537623366643338643366623761666436343634
3434393962303631643231653663356232613533643233300a363835316336653065326430353534
・・・
```

ansible.cfgに以下の一部を追記します。

```/etc/ansible/ansible.cfg
[defaults]
ask_vault_pass = True #追記
```

#playbookの作成
以下のplaybookを作成しました。
shutdownは+1を指定して、1分後にshutdownするようにしています。nowだとshutdownはするのですが、「FAILED」と表示されます。タイミングの問題なのかも知れませんが、+1を指定して回避しています。

```shutdown.yaml
- hosts: k8s

  tasks:
  - name: shutdown
    command: /usr/sbin/shutdown -h +1
    become: yes
```

##実行
playbookを実行します。その際、パスワードファイルを指定します。

```
$ ansible-playbook shutdown.yaml --extra-vars="@passwd.yaml"
Vault password:

PLAY [k8s] ***********************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************
ok: [k8s-worker01]
ok: [k8s-master]
ok: [k8s-worker02]

TASK [shutdown] ******************************************************************************************************************************************************************************
changed: [k8s-worker02]
changed: [k8s-worker01]
changed: [k8s-master]

PLAY RECAP ***********************************************************************************************************************************************************************************
k8s-master                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
k8s-worker01               : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
k8s-worker02               : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```

成功しました！

#まとめ
Ansibleをちゃんと使うのは初めてでしたが、思ったよりも簡単にできました。地味に面倒だったshutdownが簡単にできるようになってよかったです。
Kubernetesと組み合わせても色々できそうですね。こちらもゆくゆくはやってみたいと思います。