ansible dynamic inventoryの日本語の翻訳っぽいもの

雑だけれども読み通した。使って覚えるのが早い。。

http://docs.ansible.com/ansible/intro_dynamic_inventory.html


Dynamic Inventory
- 例: Cobbler 外部インベントリスクリプト
- 例: AWS EC2 外部インベントリスクリプト
- その他の在庫スクリプト
- 複数のインベントリリソースの使用
- 動的グループの静的グループ

構成管理システムのユーザは別のソフトウェアシステムにインベントリを保持しておきたいものだ。
AnsibleはInventoryというテキストベースの管理システムを提供している。もし他のものを使いたい時は
どうするか。

よくある例としてはcloudからinventoryを取得するというものだ。LDAP,Cobblerや高価なCMDBといったソフトウェアからなど。

Ansibleはこれらの外部インベントリシステムからデータ取得するオプションをサポートしている。https://github.com/ansible/ansible/tree/devel/contrib/inventory を確認すればオプションを確認できる。

Ansible Towerを使えばInventoryのデータベース管理ができ、WEBからのアクセスとRESTでのアクセスが可能になる。TowerはDynamic Inventoryを同期しGUIからのInventoryエディタを提供する。全てのホストをDB管理でき過去のイベント履歴やplaybookの実行結果を保持しておくこともできる。

自身のdynamic inventoryソースを記述する場合はhttp://docs.ansible.com/ansible/developing_inventory.html を参考にすること



☆Cobblerは個人的に使う予定はないので「例: Cobbler 外部インベントリスクリプト」は省略


■■■例: AWS EC2 外部インベントリスクリプト■■■

もしAWSでEC2を使うような場合はinventoryファイルを管理するのはベストアプローチではないかもしれない。autoscalingを使ったり、インスタンスの管理アプリケーションを使っていれば時間の経過とともにホストは起動したり停止したりするからだ。そういう場合はEC2外部Inventoryスクリプト
利用することができる。

このスクリプト(ec2.py)の使い方は2通りある。1つ目はansibleコマンドの-iオプションの引数に使う方法。

$ ansible -i ec2.py -u ubuntu us-east-1d -m ping

2つ目はコンフィグで設定中のinventory(see: ansible.cfg, default.inventory)にec2.pyを設置(/etc/ansible/hostsにrename)し、実行権限を付与しておく。また、ec2.iniを同じパス(/etc/ansible/ec2.ini)に設置しておく。そうすれば通常のstatic inventoryを扱うのと変わりなく扱える。

ec2.pyとec2.iniは下記のURLにある。
https://raw.github.com/ansible/ansible/devel/contrib/inventory/ec2.py
https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/ec2.ini

AWSへのAPIコールを正常に動作させるには、aws sdkpython実装であるBotoを正常に設定する必要がある。設定の方法はこのURL(http://docs.pythonboto.org/en/latest/boto_config_tut.html)に説明があるが、一番簡単な方法としては2つの環境変数をexportしておくことだ。

export AWS_ACCESS_KEY_ID='AK123'
export AWS_SECRET_ACCESS_KEY='abc123'

正常に動作するかどうかはec2.py自体を実行してみることだ。

$ ./ec2.py --list

しばらくして全リージョンのEC2のInventory情報がJSONフォーマットで出力される。

複数のAWSアカウントを運用している場合は --profile PROFILEをec2.pyに渡すことで使い分けることができる。(see: $ aws configure help)

[profile dev]
aws_access_key_id =
aws_secret_access_key =

[profile prod]
aws_access_key_id =
aws_secret_access_key =


ec2.py --profile prodとすることでproductionアカウントのInventoryを取得することができる。playbooksを使うような場合は

$ ansible-playbook -i 'ec2.py --profile prod' myplaybook.yml

というようにすることもできるし環境変数AWS_PROFILEを使い

$ AWS_PROFILE=prod ansible-playbook -i ec2.py myplaybook.yml

とすることもできる。


各リージョンは独自のAPIコールを必要とする場合があるので、リージョンを限って使用したい場合はec2.iniを編集してリージョンを限定するなどしてもよいだろう。ec2.iniはその他にキャッシュコントロールdestination variablesなども設定することもできる。

Dynamic Inventoryはある名前(Key)から目的のアドレスを簡単にマッピングするようになっているのが肝だ。デフォルトのec2.iniはEC2の外部から(つまり自分のラップトップやAWSの外部(?)から)ansibleを動作することを前提にしている。そして、これは効果的なEC2の運用方法とはなっていない。

もしEC2上からansibleを動作させるなら、internal DNSやinternal IPを利用するのが効果的だ(public DNSを利用するよりは)。こういう場合はec2.iniのdestination_variableをprivate DNSに変更することができる。
この方法はVPC内部のprivate subnetでansibleを動作させるような場合(private IPでのみアクセスてきるような場合)に特に重要となる。
ec2.iniのvpc_destination_variableはboto.ec2.instanceの引数をよしなに?してくれる。

ec2.pyは複数のグループ指定を利用してのインスタンスへのマッピングを提供する。

  • Global

全てのインスタンスは 'ec2'グループに入る

$ ./inventory/ec2.py | jq .ec2
[
"172.31.2.232",
"172.31.10.107",
"172.31.30.229"
]

  • Instancd ID

これは一つのインスタンスのみが所属するグループとなる。(インスタンスIDはユニークだから。)

  • Region

指定したリージョンに所属する全てのインスタンス

$ ./inventory/ec2.py | jq '."ap-northeast-1"'
[
"172.31.2.232",
"172.31.10.107",
"172.31.30.229"
]

  • Availability Zone

$ ./inventory/ec2.py | jq '."ap-northeast-1a"'
[
"172.31.2.232",
"172.31.10.107"
]

  • Security Group

インスタンスが所属しているセキュリティグループを指定することもできる。alphanumericsを除き、全てのdash(-)はunderscore(_)に変換される。各セキュリティグループはsecurity_group_というprefixが付与される。

$ ./inventory/ec2.py | jq .security_group_redmine
[
"172.31.30.229"
]

  • Tags

全てのインスタンスはkey/valueでタグを様々に付与することができる。付与したタグでグループを指定することができ、Name/redis-master-001というタグはtag_Name_redis_master_001という具合で指定できる。


ansibleが特定のサーバーとやり取りしている時、ec2.pyは--hostオプションを付与して呼ばれる。instance IDを取得するのにindex cacheのホスト情報を利用するためだ。特定インスタンスの情報を取得するのにAPIコールを作成し、playbook上で利用可能となる変数を作成する。playbook上でex2_をprefixとして利用可能になる変数は下記の通りだ。

ec2_architecture
ec2_description
ec2_dns_name
ec2_id
ec2_image_id
ec2_instance_type
ec2_ip_address
ec2_kernel
ec2_key_name
ec2_launch_time
ec2_monitored
ec2_ownerId
ec2_placement
ec2_platform
ec2_previous_state
ec2_private_dns_name
ec2_private_ip_address
ec2_public_dns_name
ec2_ramdisk
ec2_region
ec2_root_device_name
ec2_root_device_type
ec2_security_group_ids
ec2_security_group_names
ec2_spot_instance_request_id
ec2_state
ec2_state_code
ec2_state_reason
ec2_status
ec2_subnet_id
ec2_tag_Name
ec2_tenancy
ec2_virtualization_type
ec2_vpc_id


ec2_security_group_idsとec2_security_group_namesは全てのセキュリティグループのカンマ区切りのリスト。EC2タグはec2_tag_KEYのフォーマットとなっている。

インスタンスで利用できる変数は下記コマンドで確認できる。

$ ./ec2.py --host PRIVATE_OR_PUBLIC_ADDRESS

ec2.pyはAPIコールを繰り返さないように結果をキャッシュする。設定はec2.iniでできる。明示的にキャッシュクリアしたい場合は下記のようなコマンドで対応する

$ ./ec2.py --refresh-cache



■■■その他の在庫スクリプト■■■
その他のInventory Scriptには下記のようなものがある。

BSD Jails
DigitalOcean
Google Compute Engine
Linode
OpenShift
OpenStack Nova
Red Hat's SpaceWalk
Vagrant (not to be confused with the provisioner in vagrant, which is preferred)
Zabbix


利用に際しての詳細はコードを確認してください。contrib/inventory以下にあるスクリプトです。
ec2.pyもある。


■■■複数のインベントリリソースの使用■■■

  • i オプションでディレクトリが指定された場合、ansibleは同時に複数のInventoryリソースを使います。

その場合、dynamic inventoryとstatic inventoryを同時に使うこともできます。


■■■動的グループの静的グループ■■■

static inventoryでグループ内グループ定義する時、子グループが定義されていなければansibleはエラーを返す。
もし動的グループの子グループを静的に作るときはstatic inventoryファイル内で動的グループを空で定義しておけばよい。

[tag_Name_staging_foo]

[tag_Name_staging_bar]

[staging:children]
tag_Name_staging_foo
tag_Name_staging_bar