既存環境のメンテナンス用にAnsibleを導入する

最近流行りのAnsibleですが、「Infrastructure as Code」を実現するためのツールとして、Vagrantと絡めた使い方を紹介されるケースが多いため、オンプレミス環境などで、すでに構築されているサーバに対して使うことがイメージしづらい部分があるかもしれません。

実際には「Python2.4以上が入っていてSSHがつながれば、管理対象にできる」ので、オンプレミスの実サーバ・仮想サーバの管理にも、普通に使えます。

以下、「冪等性」も「Immutable Infrastructure」も関係ない、古いタイプ（？）の人にとって、お気楽な使い方を紹介します。

# 想定する対象・環境
- 管理対象サーバが5台くらいから数十台程度ある（大量ではないが、個別作業はキツいかな、という程度）
- とりあえず、管理対象サーバのOSは再インストールしたくない
- 設定ファイルぐらいなら書いてもいいが、コードは書きたくない
- 暇がない or 新しく覚えることが多いのが嫌で、自動化ツールに手を出すことができていない
- CentOS系（6・7）を使っている ※CentOS5を管理対象とする場合、管理対象サーバにpython-simplejsonパッケージが必要
- 管理対象サーバへのSSH接続は公開鍵方式にしたい

# 管理サーバのインストール
各所で紹介されているので、簡潔に記します。

仮想環境であれば新たな仮想サーバを立てます。メモリ2GB・CPU1コアでも、十分快適に動きます。

実サーバ環境では、古いPCを転用するなりします。他サーバに同居させることもできますが、管理サーバに侵入されると、最悪、管理対象サーバの全てを乗っ取られることにもなりかねませんので、物理的・論理的に安全な場所に配置してください。

以下の手順は、CentOS7・Ansible2.0系のものです。CentOS6へのインストールもほぼ同じ手順です。

- EPELリポジトリを追加する

```
# yum install epel-release
```

- 関連パッケージをインストールする

```
# yum install python-jinja2 --enablerepo=epel
# yum install libyaml
```

- Ansible 2.0をインストールする

```
# yum install ansible --enablerepo=epel-testing
```

- 管理対象サーバ接続用のユーザを作成する（「ansible」としておきます）

```
# adduser ansible
# passwd ansible
```

- 公開鍵を生成する

```
# su - ansible
$ mkdir .ssh
$ chmod 700 .ssh
$ ssh-keygen -t rsa （~/.ssh/ に保存）
```

# 管理対象サーバを登録する
管理サーバの /etc/hosts ファイルに、管理対象サーバのIPアドレスと名前を登録しておきます。

```
# vi /etc/hosts
```

```text:/etc/hosts
192.168.0.1 s01web01.XXX.local
192.168.0.2 s01web02.XXX.local
192.168.1.1 s01db01.XXX.local
```

続いて、Ansibleのインベントリに、管理対象サーバを登録します。グループ分けして登録すると良いでしょう。同じサーバを複数のグループに所属させることも可能です。

```
# vi /etc/ansible/hosts
```

```text:/etc/ansible/hosts
[s01web]
s01web01.XXX.local
s01web02.XXX.local

[s01db]
s01db01.XXX.local
```

なお、接続用アカウントの情報（ユーザ名、sudoパスワード、公開鍵ファイルの場所）は、安全を考えて暗号化すべきですが、インベントリの中に直接書くと、インベントリを修正する度に暗号化／復号を意識する必要があり、少し面倒です。

ansible-vault edit コマンドで、暗号化したまま編集することもできますが、毎回パスワードを入れる必要があること、環境によってはうまく編集できないこともあることを考慮し、別ファイル（グループごとの変数ファイル）に記述しても良いでしょう。

たとえば、/etc/ansible 以下に、group_vars ディレクトリを作成し、この中に、グループ名と同じファイル名で接続用アカウント情報を登録します。「all」という名前のファイルを作成し情報を登録すると、全ての管理対象サーバ（グループ名と同じ名前のファイルを作成した場合は、それ以外のサーバ）に共通の接続用アカウント情報を登録することもできます。

```
# mkdir /etc/ansible/group_vars
# cd /etc/ansible/group_vars
# vi s01web
```

```text:s01web
ansible_ssh_user: ansible
ansible_become_pass: 【sudoパスワード】
ansible_ssh_private_key_file: ~/.ssh/id_rsa
```

保存したら、ansible-vault encrypt コマンドで暗号化します。

```
# ansible-vault encrypt s01web
# chown ansible.ansible s01web
```

# 管理サーバから管理対象サーバに接続する
ここからの手順については、せっかくAnsibleがあるのだから、Ansibleで実行したい…ところですが、接続ユーザの作成のために一旦別のユーザでSSH接続するのもややこしいので、格好よさよりも分かりやすさを重視（？）し、個々の管理対象サーバで実行する手順を紹介します。

- 接続ユーザ（ansible）を登録する

```
# adduser ansible
# passwd ansible
```



- sudoできるようにする

visudoコマンドを使うか、/etc/sudoers.d ディレクトリにファイルを追加します。

```
# vi /etc/sudoers.d/ansible
```

```text:ansible
ansible ALL=(ALL)       ALL
```

ファイルを追加した場合は、アクセス権を変更します。

```
# chmod 440 /etc/sudoers.d/ansible
```


- 公開鍵方式で接続できるようにする

/etc/ssh/sshd_config を確認し、公開鍵方式接続が無効になっている場合は、有効にしてsshdを再起動します。

```
# vi /etc/ssh/sshd_config
```

```text:sshd_config
PubkeyAuthentication yes
```

※systemctl restart sshd.service （CentOS7）または service sshd restart （CentOS6）で再起動します。

- 公開鍵を保存する

管理サーバの公開鍵（~/.ssh/id_rsa.pub）の内容（テキスト）を、管理対象サーバに保存します。scpコマンドで管理対象サーバに転送するかテキストを直接コピー＆ペーストして、~/.ssh/authorized_keys に保存します。

```
# su - ansible
$ mkdir .ssh
$ chmod 700 .ssh
$ vi .ssh/authorized_keys
```

```text:authorized_keys
ssh-rsa 【中略】 ansible@管理サーバのホスト名
```

アクセス権を変更します。

```
$ chmod 600 .ssh/authorized_keys
```

- 接続テストする

管理サーバから、Ansibleコマンドで管理対象サーバにpingを送ってみます。

なお、設定後、最初に接続するときに限り、管理サーバの ~/.ssh/known_hosts に管理対象サーバが登録されていないので、管理対象サーバに接続するごとに「yes」を入力する必要があります。

```
$ ansible all -i /etc/ansible/hosts -m ping --ask-vault-pass
```

※暗号化（Vault）パスワードを入力します。

全ての管理対象サーバから「pong」が返れば設定完了です。

# 実際のメンテナンスに活用する

Ansibleの本来の使い方は、Playbookに手順を記述して実行するスタイルだと思いますが、

- 単純にrebootする
- yumで単一または少数のパッケージだけをupdateする
- 実行中のkernelバージョン、javaバージョンなどを見る

程度であれば、Playbookを作らなくても、ansibleコマンドでそのまま実行できてしまいます。

- 単純にrebootする

```
ansible all -i /etc/ansible/hosts -b -m shell -a 'reboot' --ask-vault-pass
```

- yumで単一のパッケージだけをupdateする

```
ansible all -i /etc/ansible/hosts -b -m yum -a 'name=【パッケージ名】 state=latest' --ask-vault-pass
```

- サービスを再起動する

```
ansible all -i /etc/ansible/hosts -b -m yum -a 'name=【サービス名】 state=restarted' --ask-vault-pass
```

- 実行中のkernelバージョンを確認する

```
ansible all -i /etc/ansible/hosts -m shell -a 'uname -a' --ask-vault-pass
```

- 実行中のjavaバージョンを確認する（グループ「s01web」限定）

```
ansible s01web -i /etc/ansible/hosts -m shell -a 'java -version' --ask-vault-pass
```

もう少し複雑なことをやってみたくなったら、参考文献などを見ながらPlaybookを作成してみてください。

# 参考文献

[サーバ/インフラエンジニア要請読本 DevOps編](http://www.amazon.co.jp/%E3%82%A4%E3%83%B3%E3%83%95%E3%83%A9%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E9%A4%8A%E6%88%90%E8%AA%AD%E6%9C%AC-DevOps%E7%B7%A8-Infrastructure-%E3%82%92%E5%AE%9F%E8%B7%B5%E3%81%99%E3%82%8B%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%E3%81%8C%E6%BA%80%E8%BC%89-Software/dp/4774179930)【書籍】
[ansibleでLinuxユーザーの作成と鍵認証を設定する](http://qiita.com/komitomo/items/e78855fa1ccee1737ac7)
[Centos6でAnsibleを1から2にしたら 「ERROR! Unexpected Exception: 'AnsibleLoader' object has no attribute 'dispose'」](http://pioho.hatenablog.com/entry/2016/03/07/160555)
[[Ansible] コマンドチートシート](http://qiita.com/moriteru/items/45d69a5744d658ce5c6e)