BLOG

Ansibleの変数定義の優先順位について

kuroda

今回のお話

前回の記事でも軽く触れましたが、Ansibleで使える変数はいくつかの場所で定義を書くことができ、それには優先順位があります。同じ名前の変数を2ヶ所で定義した時には、優先順位が低い方の値が高い方の値で上書きされます。

今回は実際に変数をあちこちで定義して、どのように上書きされるかを試してみます。

サンプル・プレイブック

サンプルとして作ったプレイブックをこちらからダウンロードできます。

このプレイブックでは、いくつかの変数をそれぞれ2ヶ所で定義していて、最終的には以下の roles/foo/template/variables.txt.j2 で値を展開します。

var_role_defaults        : {{ var_role_defaults }}
var_inventory_group_vars : {{ var_inventory_group_vars }}
var_inventory_host_vars  : {{ var_inventory_host_vars }}
var_group_vars_hosts     : {{ var_group_vars_hosts }}
var_group_vars_group     : {{ var_group_vars_group }}
var_host_vars_group      : {{ var_host_vars_group }}
var_host_vars_hosts      : {{ var_host_vars_hosts }}
var_role_vars            : {{ var_role_vars }}

プレイブックを次の要領で実行すると、

$ ansible-playbook -i hosts book.yml 

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

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

TASK [foo : write to /tmp/variables.txt] ***************************************
ok: [localhost]

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

/tmp/variables.txt に変数を展開した結果が書き出されます。

var_role_defaults        : value of roles/foo/defaults/main.yml
var_inventory_group_vars : value of [foo:vars]
var_inventory_host_vars  : value of hosts
var_group_vars_hosts     : value of hosts
var_group_vars_group     : value of group_vars/foo/main.yml
var_host_vars_group      : value of host_vars/localhost/main.yml
var_host_vars_hosts      : value of host_vars/localhost/main.yml
var_role_vars            : value of roles/foo/vars/main.yml

それぞれの変数は2ヶ所で定義されていて、定義した場所を含む文字列を値に指定しています。
grepで検索するとどこで定義されてどこで使われているかが分かります。

例えば var_inventory_group_vars 変数の場合は、

$ grep -nr var_inventory_group_vars *
README.md:13:|var_inventory_group_vars| hostsのグループ変数行 | roles/foo/defaults/main.yml |
hosts:5:var_inventory_group_vars="value of [foo:vars]"
roles/foo/templates/variables.txt.j2:2:var_inventory_group_vars : {{ var_inventory_group_vars }}
roles/foo/defaults/main.yml:2:var_inventory_group_vars: value of roles/foo/defaults/main.yml

この結果から以下の2ヶ所で定義されていることが分かります。

  • hostsファイルの5行目([foo:vars]セクションの中)
  • roles/foo/defaults/main.ymlの2行目

そして展開された値が value of [foo:vars] なので、roles/XXX/defaults/ での定義よりもhostsのグループ変数定義の方が優先される事が分かります。

実験結果

先述した要領で、それぞれの変数についてどちらの定義が優先されるかをまとめた表がこちらです。

変数名 優先度高い 優先度低い
var_role_defaults roles/foo/defaults/main.yml
var_inventory_group_vars hostsのグループ変数行 roles/foo/defaults/main.yml
var_inventory_host_vars hostsのホスト名行 hostsのグループ変数行
var_group_vars_hosts hostsのホスト名行 group_vars/foo/main.yml
var_group_vars_group group_vars/foo/main.yml hostsのグループ変数行
var_host_vars_group host_vars/localhost/main.yml group_vars/foo/main.yml
var_host_vars_hosts host_vars/localhost/main.yml hostsのホスト名行
var_role_vars roles/foo/vars/main.yml host_vars/localhost/main.yml

この表を元に変数の定義場所を優先度が低い順に並べると、次のようになります。

  1. roles/ROLENAME/defaults/ 以下のyaml (優先度低)
  2. inventory(hosts)のグループ変数行 ([group:vars]セクションの内側)
  3. group_vars/GROUPNAME/ 以下のyaml
  4. inventory(hosts)のホスト名行(hostname varname=valueの行)
  5. host_vars/HOSTNAME/ 以下のyaml
  6. roles/ROLENAME/vars/ 以下のyaml (優先度高)

注目したいのは group_vars/GROUPNAME/ の位置で、inventory(hosts)のホスト行に書くよりも優先度が低くなっています。
Ansibleの公式ドキュメントでは次のような順番であると書かれていますが、

  • inventory vars
  • inventory group_vars
  • inventory host_vars
  • playbook group_vars
  • playbook host_vars

group_vars/GROUPNAME/ 以下のファイルを “playbook group_vars” だと認識していると矛盾することになります(ということに、今回初めて気がつきました…)が、どうもこのディレクトリに書いた変数は “inventory group_vars”と理解するのが正解のようです。

まとめ

今回の検証で、group_vars/ディレクトリは”inventory group_vars”、host_vars/ディレクトリは”inventory host_vars”を定義するためのディレクトリだと分かりました。
でもそうすると、”playbook group_vars”とは一体なんなのでしょうか…。

謎を残したまま終わります。それでは皆さん良いお年を!!?