这是对这个问题的跟进。
我有一个配置一堆 EC2 实例的游戏。必要时,该hosts
值是localhost
(因为当它运行时没有主机),并且该播放组装了一个名为的新主机列表ec2hosts
,并生成主机 ip 到主机名映射,因为这是第一次也是唯一一次提供该信息,并且使用set_fact
. 这个主机列表是后续游戏的主题。问题是我需要hostname_map
在第二次播放中使用在配置播放期间创建的字典,而我看不到如何执行此操作。
这是第一部戏:
- hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Provision a set of instances
ec2:
key_name: marcus
instance_type: t2.micro
image: "{{ ami_id }}"
wait: true
exact_count: "{{ server_count }}"
count_tag:
Tutorial: "{{ tutorial_name }}"
instance_tags:
Tutorial: "{{ tutorial_name }}"
groups: ['SSH', 'Web']
register: ec2
- name: Add all instance public IPs to host group
add_host:
hostname: "{{ item.public_ip }}"
groups: ec2hosts
loop: "{{ ec2.instances }}"
- name: Build an IP to hostname map
set_fact:
hostname_map: "{{ hostname_map | combine({item.0.public_ip: (item.1 + '.' + tutorial_domain)}) }}"
loop: "{{ ec2.instances|zip(hostnames)|list }}"
- name: Debug hostname_map
debug:
msg: "{{ hostname_map }}"
最后,hostname_map
包含如下地图:
{
"18.184.109.70": "host1.example.com",
"18.196.135.59": "host2.example.com"
}
通过阅读关于变量范围的 ansible 文档,它说在剧本中定义的变量在该剧本之外不可用,除非它被应用于同一组主机。在这种情况下这是不可能的,所以我需要使用具有全局范围的 var,从我读过的内容set_fact
来看,这是执行此操作的适当方法。所以我在 中创建了一个空变量/group_vars/all
,以便所有播放都可以访问该变量:
hostname_map: {}
下一个播放连接到每个新创建的实例(使用我们动态创建的主机列表)并从内部设置其主机名:
- hosts: ec2hosts
gather_facts: yes
tasks:
- name: Debug hostname_map
debug:
msg: "{{ hostname_map }}"
- name: Set hostnames
hostname:
name: "{{ hostname_map[ansible_host] }}"
但是,这失败了,因为hostname_map
它是空的
TASK [Debug hostname_map]
ok: [18.184.109.70] => {
"msg": {}
}
ok: [18.196.135.59] => {
"msg": {}
}
所以我得到这个错误:
致命:[18.184.109.70]:失败!=> {“msg”:“任务包含一个带有未定义变量的选项。错误是:'dict object'没有属性u'18.184.109.70'
奇怪的是,即使我没有全局定义变量,我也会得到相同的调试输出和错误。
我读过的其他文章都建议应该在 中明确枚举值vars
,但我不能这样做,因为数据是动态的,直到运行时才知道。同样,出于同样的原因,我无法extra_vars
在命令行上使用它。
如何在第二次播放中使此变量可用?我想避免笨拙的解决方案,例如将本地文件写出然后再将其读回!
我也愿意接受以完全不同的方式执行此操作的建议,其中“this”是:创建任意数量的 EC2 实例并为它们分配从静态列表中获取的主机名。
您设置的值
set_fact
将在不同的播放之间可用。请记住, set_fact 是为特定主机设置的。您的第一个游戏是针对localhost运行的,因此事实是 localhosts 变量的一部分。因此,在接下来的游戏中,您应该能够通过这样的任务访问它。您可以使用虚拟主机,它将在add_host的帮助下存储您想要共享的所有变量。然后只需使用hostvars访问您的变量
取决于你如何定义游戏。如果您在一次 ansible 运行中进行多次播放,则它可以工作。但是不适用于多个连续播放。我的意思是当你运行 ansible-playbook playbook1.yml 时它不起作用,然后运行 ansible-playbook playbook2.yml