LoginSignup
5
5

More than 5 years have passed since last update.

Ansible2.3->2.4でgroup_vas/host_varsの参照パスが変わっていた件について

Last updated at Posted at 2018-12-05

はじめに

Ansibleを2.3から2.4にバージョンアップしたら既存のPlaybookが動かなくなった!
group_vars/host_varsに定義してある変数が読み込めてないらしい。

エラー
"VARIABLE IS NOT DEFINED!"

Ansible2.3までは問題なく読み込めていたのに。。。

原因はgroup_varshost_varsのディレクトリのパスでした。
個人的にハマったので書いておきます。

Summary

  • Ansible2.3->2.4でgroup_vars,host_varsの参照パスが変わった

    • 2.3まで
      • 起点となるplaybook(site.yml)からの相対パス
    • 2.4以降
      • インベントリファイルからの相対パス
    • 公式ドキュメント
  • group_vars/host_varsにグループ名/ホスト名のサブディレクトリを置くと、配下の任意のファイルに定義した変数を読み込める

本題

問題が発生した環境

ディレクトリ構成

インベントリを環境ごとに分けているので、inventories配下に環境名としてインベントリファイルを置いていました。
group_varsやhost_varsなどのファイルの内容はイメージです。Roleは省略。

問題発生時のディレクトリ構成
├── ansible.cfg
├── group_vars
│   ├── web.yml
│   ├── db.yml
│   └── ...
├── host_vars
│   ├── staging-web01.yml
│   ├── staging-db01.yml
│   └── ...
├── inventories
│   ├── staging
│   ├── production
│   └── ...
├── playbooks
│   ├── web.yml
│   ├── db.yml
│   └── ...
└── site.yml

ansible.cfg

ansible.cfg
[defaults]
hash_behaviour = merge
gathering = false

[privilege_escalation]
become = True

インベントリ

inventories/staging
[web]
staging-web01

[db]
staging-db01

group_vars

group_vars/web.yml
---
my_vars:
  nginx:
    server_name: www.example.com

host_vars

host_vars/staging-web01.yml
---
my_vars:
  db:
    host: staging-db01
    user: dbuser
    pass: STAGING_PASS

実行コマンド

$ ansible-playbook -i inventories/staging -l web site.yml

実行するとエラー

エラーメッセージ
"VARIABLE IS NOT DEFINED!"

検証

結論から言うと、公式ドキュメントに書いてありました。

Similar functionality can still be achieved by using vars_files, include_vars, or group_vars and host_vars placed relative to the inventory file.

インベントリファイルからの相対パスになった模様。。。

また、こちらには

As an advanced use case, you can create directories named after your groups or hosts, and Ansible will read all the files in these directories in lexicographical order.

group_vars/host_varsディレクトリ配下にグループ名/ホスト名のサブディレクトリがあれば、その中に置いた複数のファイルの読み込みも可能とあります。これは知らなかった。

せっかくなのであわせて各バージョンでの挙動を調べてみます。

検証用環境

検証用の環境は以下の通り。
- 起点となるplaybook(site.yml)と同じ階層にインベントリファイルとgroup_vars, host_varsディレクトリを置く
- サブディレクトリにインベントリファイルとgroup_vars, host_varsディレクトリを置く
上記2パターンを同居させ、それぞれに書いたvarsがどう読み込まれるか試してみました。

それぞれの変数には読み込まれたファイルがわかるように、自身のパスを書いておきます。

ディレクトリ構成

├── ansible.cfg
├── group_vars
│   ├── group1
│   │   └── any.yml
│   └── group1.yml
├── host_vars
│   ├── host1
│   │   └── any.yml
│   └── host1.yml
├── hosts           
├── inventories
│   ├── group_vars
│   │   ├── group1
│   │   │   └── any.yml
│   │   └── group1.yml
│   ├── host_vars
│   │   ├── host1
│   │   │   └── any.yml
│   │   └── host1.yml
│   └── hosts       
├── playbooks
│   └── load_vars_test.yml
└── site.yml

ansible.cfg

ansible.cfg
[defaults]
display_skipped_hosts = True
display_args_to_stdout = True
hash_behaviour = merge
gathering = false

[privilege_escalation]
become = True

インベントリ(hosts, inventories/hosts)

hosts,inventories/hosts
[group1]
host1 ansible_host=localhost

site.yml

site.yml
---
- include: playbooks/load_vars_test.yml

playbook

debugモジュールで、実行時に読み込んだgroup_varsとhost_varsを表示させます。

playbooks/load_vars_test.yml
---
- name: load vars test
  hosts: all
  tasks:
    - name: load group_vars
      debug: var=groupvar
    - name: load host_vars
      debug: var=hostvar

site.ymlと同階層のgroup_vars

group_vars/group1.yml
---
groupvar: group_vars/group1.yml

site.ymlと同階層のgroup_vars(グループ名サブディレクトリ配下のファイル)

group_vars/group1/any.yml
---
groupvar: group_vars/group1/any.yml

site.ymlと同階層のhost_vars

host_vars/host1.yml
---
hostvar: host_vars/host1.yml

site.ymlと同階層のhost_vars(ホスト名サブディレクトリ配下のファイル)

host_vars/host1/any.yml
---
hostvar: host_vars/host1/any.yml

インベントリファイルを置いたサブディレクトリのgroup_vars

inventories/group_vars/group1.yml
---
groupvar: inventories/group_vars/group1.yml

インベントリファイルを置いたサブディレクトリのgroup_vars(グループ名サブディレクトリ配下のファイル)

inventories/group_vars/group1/any.yml
---
groupvar: inventories/group_vars/group1/any.yml

インベントリファイルを置いたサブディレクトリのhost_vars

inventories/host_vars/host1.yml
---
hostvar: inventories/host_vars/host1.yml

インベントリファイルを置いたサブディレクトリのhost_vars(ホスト名サブディレクトリ配下のファイル)

inventories/host_vars/host1/any.yml
---
hostvar: inventories/host_vars/host1/any.yml

group_vars/host_varsの参照パスについて検証

group_vars/host_vars内のサブディレクトリは一旦リネームして除外しておきます。

1. インベントリファイルをsite.ymlと同じディレクトリに格納している場合

Ansible2.3
$ ansible-playbook -i hosts site.yml

PLAY [load vars test] **********************************************************

TASK [load group_vars var=groupvar] ********************************************
ok: [host1] => {
    "groupvar": "group_vars/group1.yml"
}

TASK [load host_vars var=hostvar] **********************************************
ok: [host1] => {
    "hostvar": "host_vars/host1.yml"
}

site.ymlと同階層のgroup_vars/host_varsが読み込まれました。

Ansible2.4以降
$ ansible-playbook -i hosts site.yml

PLAY [load vars test] **********************************************************

TASK [load group_vars var=groupvar] ********************************************
ok: [host1] => {
    "groupvar": "group_vars/group1.yml"
}

TASK [load host_vars var=hostvar] **********************************************
ok: [host1] => {
    "hostvar": "host_vars/host1.yml"
}

こちらもsite.ymlと同階層のgroup_vars/host_varsが読み込まれました。
2.3と2.4以降で結果的に同じ挙動になります。

2. インベントリファイルをサブディレクトリに格納している場合

Ansible2.3
$ ansible-playbook -i inventories/hosts site.yml

PLAY [load vars test] **********************************************************

TASK [load group_vars var=groupvar] ********************************************
ok: [host1] => {
    "groupvar": "group_vars/group1.yml"
}

TASK [load host_vars var=hostvar] **********************************************
ok: [host1] => {
    "hostvar": "host_vars/host1.yml"
}

先ほどと同じく、site.ymlと同階層のgroup_vars/host_varsが読み込まれました。
つまりインベントリファイルのパスは無関係ということです。

Ansible2.4以降
$ ansible-playbook -i inventories/hosts site.yml

PLAY [load vars test] **********************************************************

TASK [load group_vars var=groupvar] ********************************************
ok: [host1] => {
    "groupvar": "inventories/group_vars/group1.yml"
}

TASK [load host_vars var=hostvar] **********************************************
ok: [host1] => {
    "hostvar": "inventories/host_vars/host1.yml"
}

たしかにインベントリファイルを置いたサブディレクトリ内のgroup_vars/host_varsが読み込まれています。

group_vars/host_varsにサブディレクトリを作り、group_varsを記載したファイルを置いた場合の検証

サブディレクトリはgroup_vars/GROUP_NAME,host_vars/HOST_NAMEのように、グループ名/ホスト名にする必要があります。サブディレクトリ内のファイル名は任意です。

サブディレクトリあり
$ ansible-playbook -i hosts site.yml

PLAY [load vars test] **********************************************************

TASK [load group_vars var=groupvar] ********************************************
ok: [host1] => {
    "groupvar": "group_vars/group1/any.yml"
}

TASK [load host_vars var=hostvar] **********************************************
ok: [host1] => {
    "hostvar": "host_vars/host1/any.yml"
}

サブディレクトリに置いたファイルの変数が読み込まれています。
ちなみに、この挙動はver2.3〜2.7まで共通でした。

ここで、group_vars/host_varsのサブディレクトリをグループ名/ホスト名からリネームすると

サブディレクトリをリネーム
$ ansible-playbook -i hosts site.yml

PLAY [load vars test] **********************************************************

TASK [load group_vars var=groupvar] ********************************************
ok: [host1] => {
    "groupvar": "group_vars/group1.yml"
}

TASK [load host_vars var=hostvar] **********************************************
ok: [host1] => {
    "hostvar": "host_vars/host1.yml"
}

group_vars/host_varsのファイルが読み込まれました。サブディレクトリの方が優先度が高いようです。

まとめ

Ansible2.3

  • トップレベルplaybookのディレクトリからの相対パス
  • インベントリファイルのパスは関係ない
  • group_vars,host_varsディレクトリのサブディレクトリ(グループ名/ホスト名)のYAMLファイル(ファイル名は任意)が優先、なければ直下のYAMLファイル(グループ名/ホスト名)を読む

group_vars

  1. TOPLEVEL-PLAYBOOK-DIR/group_vars/GROUP_NAME/ANY.yml
  2. TOPLEVEL-PLAYBOOK-DIR/group_vars/GROUP_NAME.yml

host_vars

  1. TOPLEVEL-PLAYBOOK-DIR/host_vars/HOST_NAME/ANY.yml
  2. TOPLEVEL-PLAYBOOK-DIR/host_vars/HOST_NAME.yml

Ansible2.4以降(2.5,2.6,2.7も同様の挙動)

  • インベントリファイルのディレクトリからの相対パス

group_vars

  1. INVENTORYFILE-DIR/group_vars/GROUP_NAME/ANY.yml
  2. INVENTORYFILE-DIR/group_vars/GROUP_NAME.yml

host_vars

  1. INVENTORYFILE-DIR/host_vars/HOST_NAME/ANY.yml
  2. INVENTORYFILE-DIR/host_vars/HOST_NAME.yml
5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5