结合理解 ansible 变量和 vault 与 sub-plays
Tying to understand ansible variables and vault with sub-plays
我很难理解如何组织具有多个角色的大型剧本、使用具有多个“环境”的清单以及使用子剧本来尝试和组织事物。一直在父剧本中拥有公共变量,并与子剧本共享这些变量。我使用 ansible,但使用方式非常有限,所以我试图通过做这个练习来扩展我对它的了解。
目录结构(为测试而简化)
├── inventory
│ ├── dev
│ │ ├── group_vars
│ │ │ └── all.yml
│ │ └── hosts
│ └── prod
│ ├── group_vars
│ │ └── all.yml
│ └── hosts
├── playbooks
│ └── infra
│ └── site.yml
├── site.yml
└── vars
└── secrets.yml
secrets.yml 文件中有各种秘密,包括 ansible_ssh_user 和 ansible_become_pass。
all.yml
的内容
---
ansible_ssh_user: "{{ vault_ansible_ssh_user }}"
ansible_become_pass: "{{ vault_ansible_become_pass }}"
site.yml
的内容
---
- name: test plays
hosts: all
vars_files:
- vars/secrets.yml
become: true
gather_facts: true
pre_tasks:
- include_vars: secrets.yml
tasks:
- debug:
var: ansible_ssh_user
- import_playbook: playbooks/infra/site.yml
playbooks/infra/site.yml 的内容
---
- name: test sub-play
hosts: all
become: true
gather_facts: true
tasks:
- debug:
var: ansible_ssh_user
正在使用 ansible-playbook -i inventory/dev site.yml
调用主父 playbook。问题是,如果我不包含 var_files
AND,我将无法从子播放中访问 vault_ansible_ssh_user
或 vault_ansible_become_pass
(或保险库中的任何秘密) pre_tasks: - include_vars
如果删除 var_files
,我将无法访问父 playbook 中的机密。如果我删除 pre_tasks: - include_vars
,我将无法访问导入的子剧中的任何秘密。知道为什么我需要这两个变量包含语句才能工作吗?另外,这只是一个糟糕的设计,我做的事情完全错了吗?我很难想出用很多必需变量组织大型剧本的最佳方法,所以我最终得到了这样的目录结构来尝试划分变量以避免非常大的变量文件和需要到处都是重复的变量文件。这可能归结为我想在方孔中安装一个圆钉,但我找不到像这样的最佳实践示例。
这个问题也可能与我尝试将 ansible vault 变量放入清单 var 文件有关。如果是这样,那是我应该或不应该做的事情吗?在我写这篇文章的时候,我可能有过一个“灯泡”时刻,终于明白我应该如何处理这个,但我需要测试一些东西才能完全理解它,但无论如何,我仍然对 Whosebug 社区的内容非常感兴趣谈谈我目前是如何做的。
编辑:原来我的“灯泡”想法和我在这里的想法一样,只是以不同的方式四处走动,有同样的问题
问:“如果我删除...include_vars,我将无法访问导入的 sub-play. 中的任何机密”
A:要在剧本之间共享变量,请使用 include_vars 或 set_fact。引用自 Variable scope: how long is a value available?
Variable values associated directly with a host or group, including variables defined in inventory, by vars plugins, or using modules like set_fact and include_vars, are available to all plays. These ‘host scope’ variables are also available via the hostvars[] dictionary.
给出以下文件
shell> cat inventory/prod/hosts
test_01
test_02
shell> cat inventory/prod/group_vars/all.yml
ansible_ssh_user: "{{ vault_ansible_ssh_user }}"
ansible_become_pass: "{{ vault_ansible_become_pass }}"
shell> cat vars/secrets.yml
vault_ansible_ssh_user: ansible-ssh-user
vault_ansible_become_pass: ansible-become-pass
shell> cat site.yml
- name: test plays
hosts: all
gather_facts: false
vars_files: vars/secrets.yml
tasks:
- debug:
var: ansible_ssh_user
- debug:
var: ansible_become_pass
- import_playbook: playbooks/infra/site.yml
shell> cat playbooks/infra/site.yml
- name: test sub-plays
hosts: all
gather_facts: false
tasks:
- debug:
var: ansible_ssh_user
由vars_files声明的变量不在播放之间共享,第二个播放将失败。删节结果为
shell> ANSIBLE_INVENTORY=$PWD/inventory/prod/hosts ansible-playbook site.yml
PLAY [test plays] ****
TASK [debug] ****
ok: [test_01] => {
"ansible_ssh_user": "ansible-ssh-user"
}
ok: [test_02] => {
"ansible_ssh_user": "ansible-ssh-user"
}
TASK [debug] ****
ok: [test_01] => {
"ansible_become_pass": "ansible-become-pass"
}
ok: [test_02] => {
"ansible_become_pass": "ansible-become-pass"
}
PLAY [test sub-plays] ****
TASK [debug] ****
fatal: [test_01]: FAILED! => {"msg": "The field 'become_pass' has an invalid value, which includes an undefined variable. The error was: 'vault_ansible_become_pass' is undefined"}
fatal: [test_02]: FAILED! => {"msg": "The field 'become_pass' has an invalid value, which includes an undefined variable. The error was: 'vault_ansible_become_pass' is undefined"}
如果你使用include_vars或set_fact,问题就会消失,即“实例化”变量.注释 set_fact 并取消注释 include_vars,或同时取消注释两者,将得到相同的结果
- name: test plays
hosts: all
gather_facts: false
vars_files: vars/secrets.yml
tasks:
- debug:
var: ansible_ssh_user
- debug:
var: ansible_become_pass
# - include_vars: secrets.yml
- set_fact:
ansible_ssh_user: "{{ ansible_ssh_user }}"
ansible_become_pass: "{{ ansible_become_pass }}"
- import_playbook: playbooks/infra/site.yml
那么删节的结果就是
shell> ANSIBLE_INVENTORY=$PWD/inventory/prod/hosts ansible-playbook site.yml
PLAY [test plays] ****
TASK [debug] ****
ok: [test_01] => {
"ansible_ssh_user": "ansible-ssh-user"
}
ok: [test_02] => {
"ansible_ssh_user": "ansible-ssh-user"
}
TASK [debug] ****
ok: [test_01] => {
"ansible_become_pass": "ansible-become-pass"
}
ok: [test_02] => {
"ansible_become_pass": "ansible-become-pass"
}
TASK [set_fact] ****
ok: [test_01]
ok: [test_02]
PLAY [test sub-plays] ****
TASK [debug] ****
ok: [test_02] => {
"ansible_ssh_user": "ansible-ssh-user"
}
ok: [test_01] => {
"ansible_ssh_user": "ansible-ssh-user"
}
备注
在这个例子中,变量是否加密并不重要
成为和gather_facts不影响这个问题。
可能还有其他问题。最好回顾 include and import issues.
问:“为什么需要 vars_files?”
A: 当一个任务发送到远程主机时,需要变量ansible_become_pass来提升用户的权限。因此,当仅在任务 include_vars 中声明变量 vault_ansible_become_pass 时,该变量不会在任务执行之前可用,播放将失败并显示错误
fatal: [test_01]: FAILED! => {"msg": "The field 'become_pass' has an invalid value, which includes an undefined variable. The error was: 'vault_ansible_become_pass' is undefined"}
见
不需要vars_files如果只有user-defined个变量。例如,下面的剧本按预期工作
shell> cat inventory/prod/group_vars/all.yml
var1: "{{ vault_var1 }}"
var2: "{{ vault_var2 }}"
shell> cat vars/secrets2.yml
vault_var1: test-var1
vault_var2: test-var2
shell> cat site2.yml
- name: test plays
hosts: all
gather_facts: false
tasks:
- include_vars: secrets2.yml
- debug:
var: var1
- debug:
var: var2
- import_playbook: playbooks/infra/site2.yml
shell> cat playbooks/infra/site2.yml
- name: test sub-plays
hosts: all
gather_facts: false
tasks:
- debug:
var: var1
- debug:
var: var2
我很难理解如何组织具有多个角色的大型剧本、使用具有多个“环境”的清单以及使用子剧本来尝试和组织事物。一直在父剧本中拥有公共变量,并与子剧本共享这些变量。我使用 ansible,但使用方式非常有限,所以我试图通过做这个练习来扩展我对它的了解。
目录结构(为测试而简化)
├── inventory
│ ├── dev
│ │ ├── group_vars
│ │ │ └── all.yml
│ │ └── hosts
│ └── prod
│ ├── group_vars
│ │ └── all.yml
│ └── hosts
├── playbooks
│ └── infra
│ └── site.yml
├── site.yml
└── vars
└── secrets.yml
secrets.yml 文件中有各种秘密,包括 ansible_ssh_user 和 ansible_become_pass。
all.yml
的内容---
ansible_ssh_user: "{{ vault_ansible_ssh_user }}"
ansible_become_pass: "{{ vault_ansible_become_pass }}"
site.yml
的内容---
- name: test plays
hosts: all
vars_files:
- vars/secrets.yml
become: true
gather_facts: true
pre_tasks:
- include_vars: secrets.yml
tasks:
- debug:
var: ansible_ssh_user
- import_playbook: playbooks/infra/site.yml
playbooks/infra/site.yml 的内容
---
- name: test sub-play
hosts: all
become: true
gather_facts: true
tasks:
- debug:
var: ansible_ssh_user
正在使用 ansible-playbook -i inventory/dev site.yml
调用主父 playbook。问题是,如果我不包含 var_files
AND,我将无法从子播放中访问 vault_ansible_ssh_user
或 vault_ansible_become_pass
(或保险库中的任何秘密) pre_tasks: - include_vars
如果删除 var_files
,我将无法访问父 playbook 中的机密。如果我删除 pre_tasks: - include_vars
,我将无法访问导入的子剧中的任何秘密。知道为什么我需要这两个变量包含语句才能工作吗?另外,这只是一个糟糕的设计,我做的事情完全错了吗?我很难想出用很多必需变量组织大型剧本的最佳方法,所以我最终得到了这样的目录结构来尝试划分变量以避免非常大的变量文件和需要到处都是重复的变量文件。这可能归结为我想在方孔中安装一个圆钉,但我找不到像这样的最佳实践示例。
这个问题也可能与我尝试将 ansible vault 变量放入清单 var 文件有关。如果是这样,那是我应该或不应该做的事情吗?在我写这篇文章的时候,我可能有过一个“灯泡”时刻,终于明白我应该如何处理这个,但我需要测试一些东西才能完全理解它,但无论如何,我仍然对 Whosebug 社区的内容非常感兴趣谈谈我目前是如何做的。
编辑:原来我的“灯泡”想法和我在这里的想法一样,只是以不同的方式四处走动,有同样的问题
问:“如果我删除...include_vars,我将无法访问导入的 sub-play. 中的任何机密”
A:要在剧本之间共享变量,请使用 include_vars 或 set_fact。引用自 Variable scope: how long is a value available?
Variable values associated directly with a host or group, including variables defined in inventory, by vars plugins, or using modules like set_fact and include_vars, are available to all plays. These ‘host scope’ variables are also available via the hostvars[] dictionary.
给出以下文件
shell> cat inventory/prod/hosts
test_01
test_02
shell> cat inventory/prod/group_vars/all.yml
ansible_ssh_user: "{{ vault_ansible_ssh_user }}"
ansible_become_pass: "{{ vault_ansible_become_pass }}"
shell> cat vars/secrets.yml
vault_ansible_ssh_user: ansible-ssh-user
vault_ansible_become_pass: ansible-become-pass
shell> cat site.yml
- name: test plays
hosts: all
gather_facts: false
vars_files: vars/secrets.yml
tasks:
- debug:
var: ansible_ssh_user
- debug:
var: ansible_become_pass
- import_playbook: playbooks/infra/site.yml
shell> cat playbooks/infra/site.yml
- name: test sub-plays
hosts: all
gather_facts: false
tasks:
- debug:
var: ansible_ssh_user
由vars_files声明的变量不在播放之间共享,第二个播放将失败。删节结果为
shell> ANSIBLE_INVENTORY=$PWD/inventory/prod/hosts ansible-playbook site.yml
PLAY [test plays] ****
TASK [debug] ****
ok: [test_01] => {
"ansible_ssh_user": "ansible-ssh-user"
}
ok: [test_02] => {
"ansible_ssh_user": "ansible-ssh-user"
}
TASK [debug] ****
ok: [test_01] => {
"ansible_become_pass": "ansible-become-pass"
}
ok: [test_02] => {
"ansible_become_pass": "ansible-become-pass"
}
PLAY [test sub-plays] ****
TASK [debug] ****
fatal: [test_01]: FAILED! => {"msg": "The field 'become_pass' has an invalid value, which includes an undefined variable. The error was: 'vault_ansible_become_pass' is undefined"}
fatal: [test_02]: FAILED! => {"msg": "The field 'become_pass' has an invalid value, which includes an undefined variable. The error was: 'vault_ansible_become_pass' is undefined"}
如果你使用include_vars或set_fact,问题就会消失,即“实例化”变量.注释 set_fact 并取消注释 include_vars,或同时取消注释两者,将得到相同的结果
- name: test plays
hosts: all
gather_facts: false
vars_files: vars/secrets.yml
tasks:
- debug:
var: ansible_ssh_user
- debug:
var: ansible_become_pass
# - include_vars: secrets.yml
- set_fact:
ansible_ssh_user: "{{ ansible_ssh_user }}"
ansible_become_pass: "{{ ansible_become_pass }}"
- import_playbook: playbooks/infra/site.yml
那么删节的结果就是
shell> ANSIBLE_INVENTORY=$PWD/inventory/prod/hosts ansible-playbook site.yml
PLAY [test plays] ****
TASK [debug] ****
ok: [test_01] => {
"ansible_ssh_user": "ansible-ssh-user"
}
ok: [test_02] => {
"ansible_ssh_user": "ansible-ssh-user"
}
TASK [debug] ****
ok: [test_01] => {
"ansible_become_pass": "ansible-become-pass"
}
ok: [test_02] => {
"ansible_become_pass": "ansible-become-pass"
}
TASK [set_fact] ****
ok: [test_01]
ok: [test_02]
PLAY [test sub-plays] ****
TASK [debug] ****
ok: [test_02] => {
"ansible_ssh_user": "ansible-ssh-user"
}
ok: [test_01] => {
"ansible_ssh_user": "ansible-ssh-user"
}
备注
在这个例子中,变量是否加密并不重要
成为和gather_facts不影响这个问题。
可能还有其他问题。最好回顾 include and import issues.
问:“为什么需要 vars_files?”
A: 当一个任务发送到远程主机时,需要变量ansible_become_pass来提升用户的权限。因此,当仅在任务 include_vars 中声明变量 vault_ansible_become_pass 时,该变量不会在任务执行之前可用,播放将失败并显示错误
fatal: [test_01]: FAILED! => {"msg": "The field 'become_pass' has an invalid value, which includes an undefined variable. The error was: 'vault_ansible_become_pass' is undefined"}
见
不需要vars_files如果只有user-defined个变量。例如,下面的剧本按预期工作
shell> cat inventory/prod/group_vars/all.yml
var1: "{{ vault_var1 }}"
var2: "{{ vault_var2 }}"
shell> cat vars/secrets2.yml
vault_var1: test-var1
vault_var2: test-var2
shell> cat site2.yml
- name: test plays
hosts: all
gather_facts: false
tasks:
- include_vars: secrets2.yml
- debug:
var: var1
- debug:
var: var2
- import_playbook: playbooks/infra/site2.yml
shell> cat playbooks/infra/site2.yml
- name: test sub-plays
hosts: all
gather_facts: false
tasks:
- debug:
var: var1
- debug:
var: var2