初めてのAnsible（3章：インベントリ:サーバーの記述）


[「初めてのAnsible」](https://www.oreilly.co.jp/books/9784873117652/)を読み進めながらのメモ

前掲
[初めてのAnsible（1章：イントロダクション）](http://qiita.com/c0tt0n-candy/items/512049586f5a1f1279f3)
[初めてのAnsible（2章：Playbook:始めてみよう）](http://qiita.com/c0tt0n-candy/items/36b4eb2717447071ad21)


# インベントリファイル

* 管理対象とするサーバー（ホスト）を明示するファイル
	* `.ini` ファイルフォーマットで記述される

[公式ドキュメント](http://docs.ansible.com/ansible/intro_inventory.html)にあるように、デフォルトでは `/etc/ansible/hosts` がインベントリファイルの場所となる

### インベントリファイルを指定する場合

* コマンドラインから `-i <path>` オプションで指定
* `ansible.cfg` で指定[^1]
	* `ansible.cfg` ファイルの中で `inventory = <path>` のような記述をしてインベントリファイルの場所を明示
	* バージョン1.9までは `hostfile` が利用されていたが現在は非推奨（[hostfile](http://docs.ansible.com/ansible/intro_configuration.html#hostfile)）

## 振る舞い型のインベントリパラメータ

[List of Behavioral Inventory Parameters](http://docs.ansible.com/ansible/intro_inventory.html#list-of-behavioral-inventory-parameters) にまとまってる

* これらのうち `ansible.cfg` ファイル内の [defaults] セクションでデフォルト値をオーバーライドできるものが下記

| 振る舞い型のインベントリパラメータ | `ansible.cfg` のオプション |
| --- | --- |
| ansible_ssh_port | remote_port |
| ansible_ssh_user | remote_user |
| ansible_ssh_private_key | private_key_file |
| ansible_shell_type | executable |

**`ansible.cfg`ファイル内** といっている通り以下のような場合には利用できない

```:ansible.cfg
[defaults]
inventory = inventory		// インベントリファイルの場所を明示
remote_user = vagrant		// ansible_ssh_user をオーバーライド
private_key_file = ~/.vagrant.d/insecure_private_key	// ansible_ssh_private_key をオーバーライド
```

※ 上記のように `inventory = <path>` ではインベントリファイルを含むディレクトリを指定してもよい

```:inventory/hosts
[vagrant]
vagrant1 ansible_ssh_host=127.0.0.1 remote_port=2222
vagrant2 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2200
vagrant3 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2201
```

`ansible.cfg` で指定されたインベントリファイル（`hosts`）が上記のようであった場合、
各ホストのうち、`vagrant2` と `vagrant3` にはアクセスできるが `vagrant1` にはアクセスできない

`vagrant up` で3台のホストを立ち上げた上で検証を行うと以下のような結果になった

```
$ ansible all -a "date"	// 全てのホストで date コマンドを実行
vagrant1 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 127.0.0.1 port 22: Connection refused\r\n",
    "unreachable": true
}

vagrant2 | SUCCESS | rc=0 >>
Sat Nov 12 12:27:09 UTC 2016

vagrant3 | SUCCESS | rc=0 >>
Sat Nov 12 12:27:09 UTC 2016
```

# グループ

* インベントリファイル内で複数のホストのグループを独自に定義できる
* 定義したグループごとに設定のタスクなどを実行させる

本番環境、ステージング環境、ローカルのVagrant環境を利用するのであれば下記のような設定が可能

```inventory/hosts
[production]
production1
production1
  :

[staging]
staging1
staging2

[vagrant]
vagrant1 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2222
vagrant2 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2200
vagrant3 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2201

[web]
production1
staging1
vagrant1

[db]
production2
staging2
vagrant2

  :
```

* [production]/[staging]/[vagrant] というグループを定義し、それらに含まれるホストを明示
* [web]/[db] のようなそのホストの機能ごとにもグループを定義
	* 振る舞い型のインベントリパラメータは 一度指定すれば済む -> エイリアスの利用

### こんな書き方もできる

```
// webとdb2つのグループを含んだwebdbというグループを定義
[webdb:children]
web
db

// ホストごとに変数を定義
// 定義した変数はplaybook中で利用可
[production]
production1 color=red
production2 color=blue
  :

// グループごとに変数を定義
// 定義した変数はplaybook中で利用可
[production:vars]
db_name=hoge_production
db_user=hoge

[staging:vars]
db_name=hoge_staging
db_user=hoge

// 番号付きホストを簡潔に定義
[web]
web[1:20].example.com

// 0 つけておきたい場合
[web]
web[01:20].example.com

// アルファベットも使える
[web]
web-[a-t].example.com
```

上記で紹介したインベントリファイル内の変数はファイルへ分配していくことも可能

playbook のあるディレクトリ もしくは インベントリファイルの置いてあるディレクトリ に以下のディレクトリを作成し、その中に変数の設定ファイルを置けばよい

* ホスト変数 : `host_vars`
* グループ変数 : `group_vars`

単純にファイルに追い出してもいいし

```:group_vars/production
db_name=hoge_production
db_user=hoge
  :
```

YAML形式で記述してもいい

```:group_vars/production
db:
  name: hoge_production
  user: hoge
    :
```

## 動的インベントリ

* Ansible の外部にホストを管理しているシステムがある場合、インベントリファイルに実行可能属性を付与しておくことで、そのファイルを動的インベントリとみなし実行する
	* `daynamic.py` のようなスクリプト

動的インベントリスクリプトは以下2つのコマンドラインフラグをサポートする必要がある

* `--host <hostname>` : ホストの詳細を返す
* `--list` : グループのリストを返す

### 複数のインベントリファイルを持つ場合

静的なインベントリファイルと動的インベントリファイルの両方を持っておく必要がある場合、次のようにすることで、組み合わせて利用することができる

* 静的なインベントリファイル : `/inventory/hosts`
	* このとき静的なインベントリファイルに `.ini` 拡張子は使用できない（無視されちゃう）
* 動的インベントリファイル : `/inventory/dynamic.py`

```:ansible.cfg
[defaults]
inventory = inventory
```

インベントリファイルを含むディレクトリを明示しておくことで、すべてのインベントリファイルを処理し、結果をマージしてインベントリとする

### 実行時のエントリ追加

以下のモジュールを利用して playbook の実行時にエントリを追加することができる

#### add_host

* インベントリにホストを追加

#### group_by

* playbook の実行中にグループを作成

 

[^1]: `ansible.cfg` ファイルの置き場所は以下の順序で探される
 1. 環境変数 `ANSIBLE_CONFIG` で指定された場所
 2. カレントディレクトリ
 3. ユーザのホームディレクトリ
 4. `/etc/ansible/ansible.cfg`