AWS
Ansible

Ansible dynamic inventory

More than 3 years have passed since last update.


Inventoryファイルは

Ansibleでターゲットとなるホストを書いておくファイルです。

つまり必要なだけホストを書かないといけない、数が多いとめんどいですよね。

そこでググってたら出会った"Dynamic Inventory"を試したみました。

まず、実行ファイルとなる2つのファイルをダウンロードしておきます。


ec2.py
ec2.ini

よく張られているこちらのリンクは切れてます

https://github.com/ansible/ansible/blob/devel/plugins/inventory/ec2.py

https://github.com/ansible/ansible/blob/devel/plugins/inventory/ec2.ini

こっち

https://github.com/ansible/ansible/blob/stable-1.9/plugins/inventory/ec2.py

https://github.com/ansible/ansible/blob/stable-1.9/plugins/inventory/ec2.ini


環境を整える

ec2.pyの中に書かれてる事に従いパスを通したり環境変数をセットしたりします。


[root@ansible-server]# head -20 ec2.py
#!/usr/bin/env python

'''
EC2 external inventory script
=================================

Generates inventory that Ansible can understand by making API request to
AWS EC2 using the Boto library.

NOTE: This script assumes Ansible is being executed where the environment
variables needed for Boto have already been set:
export AWS_ACCESS_KEY_ID='AK123'
export AWS_SECRET_ACCESS_KEY='abc123'

This script also assumes there is an ec2.ini file alongside it. To specify a
different path to ec2.ini, define the EC2_INI_PATH environment variable:

export EC2_INI_PATH=/path/to/my_ec2.ini

まず、botoをインストール


yum install python-boto

キーまわり


$ export AWS_ACCESS_KEY_ID='foo'
$ export AWS_SECRET_ACCESS_KEY='bar'

iniファイルの場所(ec2.pyと同じ場所にしといた場合)


export EC2_INI_PATH=./ec2.ini


iniファイルの修正

デフォルトでキャッシュする(300s)ので、最新の情報が欲しい場合は無効に


#cache_max_age = 300
cache_max_age = 0

プライベートIPで通信したい場合

デフォルトだとpublic IPになってるので修正


#destination_variable = public_dns_name
destination_variable = private_dns_name

iniファイルの中でも対象インスタンスをフィルタできるが、今回iniではせず、Playbookの方で行う

Playbookのsite_TestEC2.ymlファイルを以下のように書く


[root@ansible-server]# cat site_TestEC2.yml
---
- hosts: tag_Name_stg-*
tasks:
- action: ec2_facts

これで、AWS上のインスタンスに付けたNameタグが"stg-"のサーバー全て対象となる

ステージング全部とか、あとは命名規則しだいだけど、プロダクト名もサーバーの名前に入ってれば後はよしなに絞りを入れていけば十分静的Inventoryファイルにあるグループの機能も吸収してくれそう。

※stg-servicename-web01だったら、tag_Name_stg-servicename-* とか


実行しましょう

-iでインベントリファイルを指定するが、Dynamic inventoryの場合はec2.pyを指定

ec2.iniはec2.pyと同じ場所においてあげる(上述で定義したパス通り)


[root@ansible-server]# ansible-playbook -vv -i ec2.py site_TestEC2.yml

実行結果

ec2.factsなのでいろいろ出ちゃうので割愛しますが、静的なinventoryファイルを作らなくもちゃんと想定したターゲットホストに対して実行されました。


PLAY [tag_Name_stg-*] *****************************************************

GATHERING FACTS ***************************************************************
<192.168.1.1> REMOTE_MODULE setup CHECKMODE=True
ok: [192.168.1.1]

TASK: [ec2_facts] *************************************************************
<192.168.1.1> REMOTE_MODULE ec2_facts CHECKMODE=True
ok: [192.168.1.1] => {"ansible_facts": {"ansible_ec2_ami_id": "foobar", "ansible_ec2_ami_launch_index": "0", "ansible_ec2_ami_manifest_path": "(unknown)", "ansible_ec2_block_device_mapping_ami": "/dev/sda1", "ansible_ec2_block_device_mapping_root": "/dev/sda1", "ansible_ec2_hostname": "foobar", "ansible_ec2_instance_action": "none", "ansible_ec2_instance_id": "foobar", "ansible_ec2_instance_type": "t2.small", "ansible_ec2_local_hostname": "foobar", "ansible_ec2_local_ipv4": "192.168.1.1", "ansible_ec2_mac": "foobar", "ansible_ec2_metrics_vhostmd": "",



PLAY RECAP ********************************************************************
192.168.1.1 : ok=3 changed=0 unreachable=0 failed=0


上記の通り残念なのがIPで出力されちゃってます。。

本来はこういう人に優しい感じのはず・・


PLAY RECAP ********************************************************************
stg-web01 : ok=3 changed=0 unreachable=0 failed=0

静的inventoryファイルの場合はファイルに記載したホスト名で表示されてたのですが残念・・・と言うかこれ大量に実行した時はまったく何のサーバーかわからん。。

とりあえずベストな回答ではないですが↓

ec2_factsかGATHERING FACTSで取ってきてる変数があるようで(http://docs.ansible.com/intro_dynamic_inventory.html)


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_tag_Nameを使って出力に表示させるようにしました。

Playbookを以下に修正


[root@ansible-server]# cat site_TestEC2.yml
---
- hosts: tag_Name_stg-*
tasks:
- action: ec2_facts
- name: Server Name
action: debug msg={{ ec2_tag_Name }}

実行結果



TASK: [Server Name] ***********************************************************
ok: [192.168.1.1] => {
"msg": "stg-web01"
}

PLAY RECAP ********************************************************************
192.168.1.1 : ok=3 changed=0 unreachable=0 failed=0

これぞワークアラウンド(ノД`)

誰かベストソリューションくださいm(_ _)m

普通にec2_tag_Nameを出力する設定があってほしい・・