ansibleで変数を共通使いにして、inventoryを環境毎に使い分ける方法

2021年11月23日2022年11月03日

ansibleでplaybookを流す対象を指定するときはinventoryを宣言することになる。

ansible-playbook playbook.yml -i inventory.yml

inventoryはホスト情報を定義しており、roleで使える変数を定義することができる。

inventory.yml
all:
  children:
    web:
      hosts:
        httpd-1:
          ansible_host: 192.168.1.1
        httpd-2:
          ansible_host: 192.168.1.2
      vars:
        config:
          logs_enable: true
          process_enable: true
    db:
      hosts:
        mysql-1:
          ansible_host: 192.168.2.1
        mysql-2:
          ansible_host: 192.168.2.2
      vars:
        mount:
          path: "/data"
        config:
          logs_enable: true
          process_enable: true

本番環境ではこのinventoryだが、開発環境ではホストの定義情報が変わる。
しかし変数は各環境で共通して使いたい場合、inventoryを複製すると変数を2重に管理することになってしまう。

そこで変数の2重管理にならないようgroup_varsディレクトリに、group名.ymlを配置する。
inventoryを読み込んだときに自動でgroup名.ymlの変数を取り込んでくれる仕様のようだ。

https://docs.ansible.com/ansible/2.9_ja/user_guide/intro_inventory.html#id29

変数の切り出し前後は変数の抜けがないよう、ansible-inventoryを使うことで差分を確認することができる。

ansible-inventory -i inventories/inventory.yml --list --yaml

切り出し前の確認

切り出し前に確認をします。

$ ansible-inventory -i inventories/inventory.yml --list --yaml 
all:
  children:
    db:
      hosts:
        mysql-1:
          ansible_host: 192.168.2.1
          config:
            logs_enable: true
            process_enable: true
          mount:
            path: /data
        mysql-2:
          ansible_host: 192.168.2.2
          config:
          mount:
    ungrouped: {}
    web:
      hosts:
        httpd-1:
          ansible_host: 192.168.1.1
          config:
            logs_enable: true
            process_enable: true
        httpd-2:
          ansible_host: 192.168.1.2
          config:

最後にdiffるのでファイルに書き出しておきます。

ansible-inventory -i inventory.yml --list --yaml >> diff/before.yml

切り出し作業

切り出し前の構成です。

before

$ tree
.
├── inventories
│   └── inventory.yml
└── roles
    ├── role1
    │   ├── files
    │   │   └── index.html
    │   └── tasks
    │       └── main.yml
    └── role2
        ├── tasks
        │   └── main.yml
        └── templates
            └── index.html.j2

8 directories, 5 files

それでは切り出して行きましょう。

group_varsディレクトリの作成

  • web.ymlの作成
  • db.ymlの作成

inventoryからvars部分のみ切り出し

切り出し後の構成です。

$ tree
.
├── group_vars
│   ├── db.yml
│   └── web.yml
├── inventories
│   └── inventory.yml
└── roles
    ├── role1
    │   ├── files
    │   │   └── index.html
    │   └── tasks
    │       └── main.yml
    └── role2
        ├── tasks
        │   └── main.yml
        └── templates
            └── index.html.j2

9 directories, 7 files

続いてinventoryとgroup_varsの内容です。
ちなみにvars: という宣言は、group_varsに移動したタイミングで不要になるため削除しています。

inventories/inventory.yml
all:
  children:
    web:
      hosts:
        httpd-1:
          ansible_host: 192.168.1.1
        httpd-2:
          ansible_host: 192.168.1.2
    db:
      hosts:
        mysql-1:
          ansible_host: 192.168.2.1
        mysql-2:
          ansible_host: 192.168.2.2
group_vars/web.yml
config:
  logs_enable: true
  process_enable: true
group_vars/db.yml
mount:
  path: "/data"
config:
  logs_enable: true
  process_enable: true

切り出し後の確認

いよいよ確認していきます。

$ ansible-inventory -i inventories/inventory.yml --list --yaml 
all:
  children:
    db:
      hosts:
        mysql-1:
          ansible_host: 192.168.2.1
          config:
            logs_enable: true
            process_enable: true
          mount:
            path: /data
        mysql-2:
          ansible_host: 192.168.2.2
          config:
          mount:
    ungrouped: {}
    web:
      hosts:
        httpd-1:
          ansible_host: 192.168.1.1
          config:
            logs_enable: true
            process_enable: true
        httpd-2:
          ansible_host: 192.168.1.2
          config:

ファイルに書き出してdiffって見ましょう。

ansible-inventory -i inventories/inventory.yml --list --yaml >> diff/after.yml

差分確認

$ diff diff/before.yml diff/after.yml 
$ echo $? 
0

ということで差分も出てなく、無事に切り出し完了です。

ステージング環境のinventoryを作って確認
次にステージング環境のinventoryを作ります。

inventories/inventory_staging.yml
all:
  children:
    web:
      hosts:
        httpd-1:
          ansible_host: 192.168.11.1
        httpd-2:
          ansible_host: 192.168.11.2
    db:
      hosts:
        mysql-1:
          ansible_host: 192.168.12.1
        mysql-2:
          ansible_host: 192.168.12.2

ステージング環境をdiffってみる

まずは同じようにinventoryを出力します。

ansible-inventory -i inventories/inventory_staging.yml --list --yaml >> diff/after_staging.yml

想定はホストのみ変更しており、変数は共通で使えるはずです。

$ diff diff/after.yml diff/after_staging.yml
6c6
<           ansible_host: 192.168.2.1
---
>           ansible_host: 192.168.12.1
13c13
<           ansible_host: 192.168.2.2
---
>           ansible_host: 192.168.12.2
20c20
<           ansible_host: 192.168.1.1
---
>           ansible_host: 192.168.11.1
25c25
<           ansible_host: 192.168.1.2
---
>           ansible_host: 192.168.11.2

ホストだけが変更になっていることが確認できました。

[注意]変数の上書きはできない

ちなみに共通の変数から本番環境だけ「この値にしたい」というとき、今まで通り直接inventoryにvarsを追加しても変数をオーバーライドすることができません。
理由はinventory host_varsよりinventory group_varsの方が優先度が高いためです。

  1. command line values (for example, -u my_user, these are not variables)
  2. role defaults (defined in role/defaults/main.yml) 1
  3. inventory file or script group vars 2
  4. inventory group_vars/all 3
  5. playbook group_vars/all 3
  6. inventory group_vars/* 3
  7. playbook group_vars/* 3
  8. inventory file or script host vars 2
  9. inventory host_vars/* 3
  10. playbook host_vars/* 3
  11. host facts / cached set_facts 4
  12. play vars
  13. play vars_prompt
  14. play vars_files
  15. role vars (defined in role/vars/main.yml)
  16. block vars (only for tasks in block)
  17. task vars (only for the task)
  18. include_vars
  19. set_facts / registered vars
  20. role (and include_role) params
  21. include params
  22. extra vars (for example, -e "user=my_user")(always win precedence)

https://docs.ansible.com/ansible/latest/userguide/playbooksvariables.html#understanding-variable-precedence

まとめ

inventoryから変数を切り分けることで環境に応じたinventoryを作成することが出来ました。
切り出し前後にはansible-inventory --list --yamlをすることでinventoryを事前に確認することができます。

環境毎による管理の複雑性を取り除くことができました。
絶対に2重管理したくないマン!