AnsibleのInventory Groupで環境毎に異なるlocalhostを構築する

AnsibleのInventory Groupで環境毎に異なるlocalhostを構築する

2016.03.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

渡辺です。

Ansibleでは、ホストをInventoryファイル(スクリプト)で定義します。 この時、次のようにグループ化することが可能です。

			
			
[prd]
10.0.0.10
10.0.0.20
[stg]
10.0.100.10
10.0.100.20

		

ここではprdグループとstgグループにホストを定義しています。 ホストをグループ化することで、グループ変数(group variable)が利用できるため、本番環境(prd)と検証環境(stg)における構成の差異を反映した構成管理を行えます。

ここまではよくある話。 今回、ハマったのは本番環境も検証環境もlocalhostの場合です。 すなわちAnsibleをローカル実行させる場合に期待通りのグループ変数が適用されなかったというお話です。

期待通りにいかないファイル構成

こちらは上手く動作しなかった構成です。

			
			
# hosts
[stg]
localhost
[prd]
localhost

		
			
			
# stg.yml
- hosts: stg
  connection: local
  tasks:
    - debug: var=stage

		
			
			
# prd.yml
- hosts: prd
  connection: local
  tasks:
    - debug: var=stage

		
			
			
# group_vars/stg.yml
stage: stg

		
			
			
# group_vars/prd.yml
stage: prd

		

実行してみます。

			
			
$ ansible-playbook -i hosts stg.yml 

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "stage": "stg"
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0  

		

期待通りです。

			
			
PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "stage": "stg"
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0 

		

あれ・・・prdのはずが・・・。

1

調査中...

対策後の構成

試行錯誤の結果、次のような構成としました。

			
			
# local
[local]
localhost

		
			
			
# local.yml
- hosts: local
  connection: local
  tasks:
    - group_by: key={{ env }}
    - debug: var=stage

		
			
			
# group_vars/stg.yml
stage: stg

		
			
			
# group_vars/prd.yml
stage: prd

		

実行してみます。

			
			
$ ansible-playbook --extra-vars "env=stg" -i local local.yml 
PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [group_by] ****************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "stage": "stg"
}

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

		
			
			
$ ansible-playbook --extra-vars "env=prd" -i local local.yml 

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [group_by] ****************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "stage": "prd"
}

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

		

期待通りです!

考察

最初の構成は、localhostという同一のホストが複数のグループに属している状態になります。 つまり、localhostはstgグループにもprdグループにも属しています。

Ansibleは、ホスト毎に実行を行います。 この時、属しているグループからグループ変数を適用する流れになります。 localhostは、stgグループにもprdグループにも属しているので、両方のグループ変数ファイルが適用されます 今回、優先されたのがstgグループのグループ変数だったわけです。

つまり、localhostを環境毎にグループ変数を適用するにはこの定義では上手くいきません。

--extra-varsオプションとgroup_byモジュールの利用

これらの問題を解決するために、--extra-varsオプションとgroup_byモジュールを利用しました。 他の方法もありますが、設定ファイルの数が少なく、重複も減らしたいとなると、この方法がベストだと思います。

--extra-varsオプションは次のようにansible-playbookのコマンド実行時に指定します。

			
			
$ ansible-playbook --extra-vars "env=prd" -i local local.yml 

		

これでenv=prdが変数として渡されることになります。

group_byモジュールは、playbook実行時に動的にグループを指定するモジュールです。 実行環境から取得する情報などかグループを指定しますが、ここでは--extra-varsオプションで指定されたenvを使い、prd(stg)グループに追加します。

			
			
  tasks:
    - group_by: key={{ env }}

		

prd(stg)グループに属すれば、それぞれのグループ変数が適用されることになります。

まとめ

Ansibleは、あくまでホストを主人公として実行されます。 同じホストに異なる設定を行いたい場合は、動的にグループを指定してください(inventoryファイル自体を環境分作成する方法もあります)。 動的なグループ追加はgroup_byモジュールで実現します。

localhostの時はご注意を!

この記事をシェアする

FacebookHatena blogX

関連記事