这是这个问题。
我有一个剧本,它配置了一堆 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 文档中关于变量范围的内容,它指出,除非将 play 中定义的变量应用于同一组主机,否则该变量在该 play 之外不可用。在这种情况下,这是不可能的,所以我需要使用具有全局范围的 var,从我所读的内容来看,这set_fact
是适当的方法。因此,我在 中创建了一个空变量/group_vars/all
,以便所有 play 都可以访问该变量:
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
出于同样的原因,我无法在命令行上使用 提供它。
我怎样才能使这个变量在第二个播放中可用?我想避免笨拙的解决方案,例如写出本地文件然后将其读回!
我还愿意接受以完全不同的方式执行此操作的建议,其中“此”是:创建任意数量的 EC2 实例并为它们分配从静态列表中获取的主机名。
答案1
您设置的值set_fact
将在不同的游戏中可用。请记住 set_fact 是为特定主机设置. 你的第一场比赛是本地主机因此事实是 localhosts 变量的一部分。因此,在下一个游戏中,您应该能够使用类似这样的任务来访问它。
- debug:
var: hostvars['localhost']['hostmap']
答案2
你可以使用虚拟主机它将存储您想要共享的所有变量添加主机.然后只需使用主机变量
- hosts: "18.184.109.70"
user: ubuntu
tasks:
- name: set a variable
set_fact:
shared_variable: "Some value"
- name: add variables to dummy host
add_host:
name: "variable_holder"
shared_variable: "{{ shared_variable }}"
- hosts: "18.196.135.59"
user: ubuntu
vars:
shared_variable: "{{ hostvars['variable_holder']['shared_variable'] }}"
tasks:
- debug:
msg: "{{ shared_variable }}"
答案3
取决于你如何定义 play。如果你在一次 ansible 运行中有多个 play,它就可以工作。但是,它不适用于多个连续的 play。我的意思是,当你运行 ansible-playbook playbook1.yml,然后运行 ansible-playbook playbook2.yml 时,它不起作用