如何在ansible中创建动态变量
How to create dynamic variables in ansible
真实场景,想获取AWS中sqs的资源id,执行playbook后返回。因此,在文件中使用此变量来配置应用程序。
将变量从一个剧本持久化到另一个剧本
查看文档,set_fact 和 register 等模块仅适用于该特定主机。使用从一台主机到另一台主机的变量有很多目的。
我能想到的替代方案:
使用命令模块并将变量回显到文件中。稍后,使用变量文件使用 vars 部分或 include.
设置环境变量然后访问它,但这会很困难。
那么解决方法是什么?
您可以将 "common" 变量写入 host_vars
或 group_vars
,这样所有服务器都可以访问它。
另一种方法可能是创建自定义 ansible module/lookup plugin
以隐藏所有样板代码并轻松灵活地访问您需要的变量。
如果您正在收集事实,您可以通过普通的 jinja2 + 变量查找访问 hostvars:
例如
- hosts: serverA.example.org
gather_facts: True
...
tasks:
- set_fact:
taco_tuesday: False
然后,如果这有 运行,在另一台主机上:
- hosts: serverB.example.org
...
tasks:
- debug: var="{{ hostvars['serverA.example.org']['ansible_memtotal_mb'] }}"
- debug: var="{{ hostvars['serverA.example.org']['taco_tuesday'] }}"
请记住,如果您有多个 Ansible 控制机器(从中调用 ansible
和 ansible-playbook
),您应该利用 Ansible 可以存储其 facts/variables in a cache(目前是 Redis 和 json),这样控制机器不太可能有不同的主机变量。有了这个,您可以将您的控制机器设置为使用共享文件夹中的文件(这有其风险——如果两台控制机器同时 运行 连接在同一主机上怎么办?),或者 set/get 来自 Redis 服务器的事实。
对于我对 Amazon 数据的使用,我更喜欢每次使用 tag/metadata 查找来获取资源。我写了一个 Ansible plugin 让我更容易做到这一点,因为我更喜欢这个而不是考虑 hostvars 和 运行 订购(但你的里程可能会有所不同)。
您可以在命令行上传递变量:http://docs.ansible.com/ansible/playbooks_variables.html#passing-variables-on-the-command-line
ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"
您可以使用本地连接到 运行 playbook = 获取变量并将其应用于另一个 playbook:
- hosts: 127.0.0.1
connection: local
- shell: ansible-playbook -i ...
register: sqs_id
- shell: ansible-playbook -i ... -e "sqs_id={{sqs_id.stdout}}"
在这种情况下委派也可能有用:
http://docs.ansible.com/ansible/playbooks_delegation.html#delegation
您也可以将输出存储在本地文件中并使用 (http://docs.ansible.com/ansible/playbooks_delegation.html#delegation):
- 名称:取一个 sqs id
local_action: 命令 cat ~/sqs_id
PS:
我不明白为什么你不能编写复杂的剧本,其中将包含许多共享变量的角色?
我对 azure DevOps 管道有类似的问题。
我使用 terraform、ssh-keys 创建了 VM:s,windows username/password 是由 terraform 生成的,并将其存储在 KeyVault 中。
所以我需要在 运行 Ansible 之前查询 KeyVault 对所有创建的 VM:s。我最终使用 Azure python SDK 来获取所有秘密。我还生成了一个清单文件和一个 host_vars 文件夹,每个 VM 都有一个文件。
实际的剧本现在非常基础并且可以完美地完成工作。 terraform 和 ansible 的所有变量都在 json 文件中。而python脚本不到30行。
真实场景,想获取AWS中sqs的资源id,执行playbook后返回。因此,在文件中使用此变量来配置应用程序。
将变量从一个剧本持久化到另一个剧本
查看文档,set_fact 和 register 等模块仅适用于该特定主机。使用从一台主机到另一台主机的变量有很多目的。
我能想到的替代方案:
使用命令模块并将变量回显到文件中。稍后,使用变量文件使用 vars 部分或 include.
设置环境变量然后访问它,但这会很困难。
那么解决方法是什么?
您可以将 "common" 变量写入 host_vars
或 group_vars
,这样所有服务器都可以访问它。
另一种方法可能是创建自定义 ansible module/lookup plugin
以隐藏所有样板代码并轻松灵活地访问您需要的变量。
如果您正在收集事实,您可以通过普通的 jinja2 + 变量查找访问 hostvars:
例如
- hosts: serverA.example.org
gather_facts: True
...
tasks:
- set_fact:
taco_tuesday: False
然后,如果这有 运行,在另一台主机上:
- hosts: serverB.example.org
...
tasks:
- debug: var="{{ hostvars['serverA.example.org']['ansible_memtotal_mb'] }}"
- debug: var="{{ hostvars['serverA.example.org']['taco_tuesday'] }}"
请记住,如果您有多个 Ansible 控制机器(从中调用 ansible
和 ansible-playbook
),您应该利用 Ansible 可以存储其 facts/variables in a cache(目前是 Redis 和 json),这样控制机器不太可能有不同的主机变量。有了这个,您可以将您的控制机器设置为使用共享文件夹中的文件(这有其风险——如果两台控制机器同时 运行 连接在同一主机上怎么办?),或者 set/get 来自 Redis 服务器的事实。
对于我对 Amazon 数据的使用,我更喜欢每次使用 tag/metadata 查找来获取资源。我写了一个 Ansible plugin 让我更容易做到这一点,因为我更喜欢这个而不是考虑 hostvars 和 运行 订购(但你的里程可能会有所不同)。
您可以在命令行上传递变量:http://docs.ansible.com/ansible/playbooks_variables.html#passing-variables-on-the-command-line
ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"
您可以使用本地连接到 运行 playbook = 获取变量并将其应用于另一个 playbook:
- hosts: 127.0.0.1
connection: local
- shell: ansible-playbook -i ...
register: sqs_id
- shell: ansible-playbook -i ... -e "sqs_id={{sqs_id.stdout}}"
在这种情况下委派也可能有用: http://docs.ansible.com/ansible/playbooks_delegation.html#delegation
您也可以将输出存储在本地文件中并使用 (http://docs.ansible.com/ansible/playbooks_delegation.html#delegation): - 名称:取一个 sqs id local_action: 命令 cat ~/sqs_id
PS:
我不明白为什么你不能编写复杂的剧本,其中将包含许多共享变量的角色?
我对 azure DevOps 管道有类似的问题。 我使用 terraform、ssh-keys 创建了 VM:s,windows username/password 是由 terraform 生成的,并将其存储在 KeyVault 中。
所以我需要在 运行 Ansible 之前查询 KeyVault 对所有创建的 VM:s。我最终使用 Azure python SDK 来获取所有秘密。我还生成了一个清单文件和一个 host_vars 文件夹,每个 VM 都有一个文件。
实际的剧本现在非常基础并且可以完美地完成工作。 terraform 和 ansible 的所有变量都在 json 文件中。而python脚本不到30行。