🌟

Ansibleの変数の扱いが思うようにいかなかった件

2024/01/11に公開

ずっと下書きのまま温められてたので投下。

直面した事象

こんな感じのplaybookを書いた。

test_playbook.yml
- name: test_play
  hosts: localhost
  vars:
    test_var1: play1
    test_var2: play2
  roles:
   - role: test_role1
   - role: test_role2
   - role: test_role3
     vars:
       test_var1: role1
       test_var2: role2
roles/test_role1/tasks/main.yml, roles/test_role2/tasks/main.yml, roles/test_role3/tasks/main.yml
- name: print vars
  debug:
    msg: "{{ test_var1 }}, {{ test_var2 }}"

test_role3 実行時のみ別の変数を渡したかったのだが…
実行結果は以下のとおり、すべて roles: 配下で定義した変数で上書きされていた

$ ansible-playbook testplaybook.yml

PLAY [test_play] ************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************************
ok: [localhost]

TASK [test_role1 : print vars] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "role1, role2"
}

TASK [test_role2 : print vars] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "role1, role2"
}

TASK [test_role3 : print vars] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "role1, role2"
}

PLAY RECAP ******************************************************************************************************************************************************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

ちなみにAnsibleにおける変数の優先順位は以下のとおり。
※下にいくほど優先度高

command line values (eg “-u user”)
role defaults [1]_
inventory file or script group vars [2]_
inventory group_vars/all [3]_
playbook group_vars/all [3]_
inventory group_vars/* [3]_
playbook group_vars/* [3]_
inventory file or script host vars [2]_
inventory host_vars/* [3]_
playbook host_vars/* [3]_
host facts / cached set_facts [4]_
play vars
play vars_prompt
play vars_files
role vars (defined in role/vars/main.yml)
block vars (only for tasks in block)
task vars (only for the task)
include_vars
set_facts / registered vars
role (and include_role) params
include params
extra vars (always win precedence)

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html

Why?

調べてみると以下の記載があった。

When using vars: within the roles: section of a playbook, the variables are added to the play variables, making them available to all tasks within the play before and after the role. This behavior can be changed by DEFAULT_PRIVATE_ROLE_VARS.

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html

つまるところデフォルト設定だと roles: 配下の vars: で変数を定義すると、role params ではなく play vars 扱いとなる模様。。。

結局どうすりゃいいのよ

  • ansible.cfg で DEFAULT_PRIVATE_ROLE_VARS を True に設定する。
$ sudo vi /etc/ansible/ansible.cfg
--- snip
# by default, variables from roles will be visible in the global variable
# scope. To prevent this, the following option can be enabled, and only
# tasks and handlers within the role will see the variables there
#private_role_vars = yes ← このコメントアウトを外す
--- snip

実行結果確認

$ ansible-playbook testplaybook.yml

PLAY [test_play] ************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************************ok: [localhost]

TASK [test_role1 : print vars] **********************************************************************************************************************************************************************************ok: [localhost] => {
    "msg": "play1, play2"
}

TASK [test_role2 : print vars] **********************************************************************************************************************************************************************************ok: [localhost] => {
    "msg": "play1, play2"
}

TASK [test_role3 : print vars] **********************************************************************************************************************************************************************************ok: [localhost] => {
    "msg": "role1, role2"
}

PLAY RECAP ******************************************************************************************************************************************************************************************************localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  • roles: 配下の vars: を使わない
testplaybook.yml
- name: test_play
  hosts: localhost
  vars:
    test_var1: play1
    test_var2: play2
  roles:
   - role: test_role1
   - role: test_role2
   - role: test_role3
     test_var1: role1
     test_var2: role2

実行結果確認

$ ansible-playbook testplaybook.yml

PLAY [test_play] ************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************************ok: [localhost]

TASK [test_role1 : print vars] **********************************************************************************************************************************************************************************ok: [localhost] => {
    "msg": "play1, play2"
}

TASK [test_role2 : print vars] **********************************************************************************************************************************************************************************ok: [localhost] => {
    "msg": "play1, play2"
}

TASK [test_role3 : print vars] **********************************************************************************************************************************************************************************ok: [localhost] => {
    "msg": "role1, role2"
}

PLAY RECAP ******************************************************************************************************************************************************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Discussion