ansibleで疎通確認とplaybookの実行

#ansibleとは
サーバやクラウドインフラの構成管理ツールです。
PlaybookというYAMLファイルにタスクを記述して、ansibleに実行させることにより様々な処理を行えるようになります。
Playbookには冪等性があるため、何回同じファイルを実行しても同じ結果になります。
(冪等性はある操作を1回行っても複数回行っても結果が同じであることをいう概念)

##YAMLとは
YAML(YAML Ain't Markup Language)とは、構造化されたデータを表現するためのフォーマットです。
インデントを使ってデータ構造を表しており非常に読みやすくなっています。
また、YAMLではデータを配列、ハッシュ、スカラー(数値や文字列や真偽値)だけで表しています。

##Infrastructure as Code
インフラの構成を管理したり、プロビジョニングを自動化するためにコードで書きましょうという概念です。
バージョン管理ができたり、CIだったりとソフトウェア開発と同じ要領でインフラの構築も行えるようになります。
このような概念があるから、ansibleのようにコードで設定を書いておくのが良いのだなとわかりました。

# 実際に使ってみる
業務で何度か使ったことある程度だったのですが、そのコードを見よう見まねで自分の環境でやってみたらいろいろと躓きました。。
これから始める方は[ansibleのチュートリアル](http://yteraoka.github.io/ansible-tutorial/#install-ansible)があるのでこれ通り進めると良いと思います。
下記躓いた部分になるのですが、チュートリアル通りにやればこうはならないはず。

## やったこと
ansible用のディレクトリを作成して、そこに下記のファイルを作成後、webサーバに適用させます。
やろうとしていることは`file:~`に書かれていることそのままで、
/tmpにhogeディレクトリを作成するということで、パーミッションは775でowner,groupはapacheにしてねってことです。

```/ansible/site.yml
- hosts: all
  user: root
  tasks:
    - name: Create hoge directory
      file: path=/tmp/hoge state=directory mode=0775 owner=apache group=apache
```

普段使うコマンドで実行！(いろいろと設定不足)

```command
$ ansible-playbook site.yml -i "0.0.0.0"(適用させたいサーバのipアドレス)

[WARNING]: Host file not found: 0.0.0.0

[WARNING]: provided hosts list is empty, only localhost is available


PLAY RECAP *********************************************************************
```

調べてみるとインベントリファイルにホストを書かないといけないそうです。
インベントリファイルはデフォルトでは`/usr/local/etc/ansible/hosts`らしいのですが、-iオプションで指定ができるので、ansibleディレクトリにhostsファイルを作成して対応します。

```
$ ansible --help                                                                                                                                    (git)-[master]
Usage: ansible <host-pattern> [options]
(省略)
Options:
-i INVENTORY, --inventory-file=INVENTORY
                        specify inventory host path
                        (default=/usr/local/etc/ansible/hosts) or comma
                        separated host list.
```

```/ansible/hosts.
[適当な名前]
0.0.0.0(適用させたいサーバのipアドレス)
```

### チュートリアル確認しつつ進める
ここら辺からチュートリアルを確認し始めましたので、チュートリアル通りに疎通確認です。
hostsファイルを作成したのですが、今度はパーミッションが。。

```
$ ansible -i hosts 0.0.0.0 -m ping
0.0.0.0 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: Permission denied (publickey).\r\n",
    "unreachable": true
}
```

どうやらhostsファイルにユーザーとプライベートキーを設定すれば良いらしい。

```/ansible/hosts.
[適当な名前]
0.0.0.0 ansible_ssh_user=ec2-user ansible_ssh_private_key_file=~/.ssh/id_rsa
```

pingpongできた！

```
$ ansible -i hosts 0.0.0.0 -m ping                                                                                                            (git)-[master]
0.0.0.0 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
```
### dry-run
これで準備ができたので実際に作成したplaybookを試してみます。
ansibleを使用する際には、実行する前にdry-runを行うと良いです。
下記チュートリアルからの引用ですが。
> --check オプションを指定することで変更は行わないが、実際に実行するとこうなるという出力がされます

```
$ ansible-playbook site.yml -i hosts -C                                                                                                             

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [0.0.0.0]

TASK [Create hoge directory] ***************************************************
changed: [0.0.0.0]

PLAY RECAP *********************************************************************
0.0.0.0              : ok=2    changed=1    unreachable=0    failed=0
```

--checkと-Cは同じです。
これをみると変更(changed)が1箇所で、`TASK [Create hoge directory] `がchangedとなっているので、想定通りのようですね。
今はtaskが1つなので良いのですが、多くなってきた場合や複数人で扱う場合には、
適用させてないタスクがあったり、ansibleを使用しないで直接変更を加えたりする人がいる可能性もあるので、
実行前にdry-runを行って、想定外の変更がないかを確認すると良いと思います。


### playbookの実行
じゃあ最後に実行して終了です。
と思いきや失敗しました。

```
$ ansible-playbook site.yml -i hosts                                                                                                                

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [0.0.0.0]

TASK [Create hoge directory] ***************************************************
fatal: [0.0.0.0]: FAILED! => {"changed": false, "failed": true, "gid": 500, "group": "ec2-user", "mode": "0775", "msg": "chown failed: failed to look up user apache", "owner": "ec2-user", "path": "/tmp/hoge", "size": 4096, "state": "directory", "uid": 500}
	to retry, use: --limit @/Users/username/workspace/aws/ansible/site.retry

PLAY RECAP *********************************************************************
0.0.0.0              : ok=1    changed=0    unreachable=0    failed=1
```

chownできないとか言われてるので、ec2-userに変更します。

```
/ansible/site.yml
- hosts: all
  user: root
  tasks:
    - name: Create hoge directory
      file: path=/tmp/hoge state=directory mode=0775 owner=ec2-user group=ec2-user # ここのownerとgroupを修正
```

### 補足
dry-runで問題なかったじゃんと思われるかもしれません。ただ、dry-runでは実際に実行しているわけではないため、実行しないとわからないエラーまでは検知できません。
また今回のケースとは逆で、dry-runでこけているのに、実行すると問題がないケースもあります。
例えば`パッケージのインストール → インストールしたパッケージの設定を変更`のようなtasksを作成する場合がそうです。
dry-runではパッケージのインストールは行わないため、`インストールしたパッケージの設定を変更`でそんなパッケージねーよ！って怒られますが、実際に実行するとパッケージのインストールは行われるため問題ないった具合です。


### 再度実行
やっとできました。以上！

```
$ ansible-playbook site.yml -i hosts

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [0.0.0.0]

TASK [Create hoge directory] ***************************************************
changed: [0.0.0.0]

PLAY RECAP *********************************************************************
0.0.0.0              : ok=2    changed=1    unreachable=0    failed=0
```