开启gather_facts导致set_fact与hostvars变量传递失效求助
为什么开启gather_facts会导致变量丢失?
你之前用set_fact+hostvars跨play传变量能正常运行,本质是个“意外”——当gather_facts=no时,Ansible不会刷新目标主机的fact缓存,set_fact默认创建的临时变量(仅当前play有效)会被意外保留到后续play。
但当你把gather_facts改成yes后,Ansible会自动执行setup模块收集主机的系统facts,这个过程会强制刷新主机的fact缓存。而你之前通过set_fact设置的vault变量没有加cacheable: yes参数,属于临时变量,缓存刷新后就被清除了,所以后续Execution Play通过hostvars访问时会提示“未定义”。
至于新增的current_time依赖的ansible_date_time.iso8601,这是gather_facts收集到的系统原生fact,本身会存入缓存,不受这个问题影响。
解决方法
要同时实现传递时间戳和保留vault变量,推荐两种可靠方案:
方案1:给跨play传递的变量加cacheable: yes
直接修改Staging Play中的set_fact任务,给所有需要跨play使用的变量(包括vault变量和current_time)加上cacheable: yes,让变量存入持久化fact缓存,这样后续play就能通过hostvars正常访问:
- name: Staging Play hosts: staging_servers gather_facts: yes tasks: - name: Set cross-play variables set_fact: my_vault_secret: "{{ vault_encrypted_var }}" current_time: "{{ ansible_date_time.iso8601 }}" cacheable: yes
方案2:按需收集facts+直接加载vault文件
如果vault变量原本是存放在独立vault文件中的,完全可以在Execution Play中直接加载,不用依赖hostvars;时间戳则可以单独收集需要的fact,避免全量gather_facts带来的缓存重置:
- name: Staging Play hosts: staging_servers gather_facts: no tasks: - name: 只收集时间相关的facts setup: filter: ansible_date_time - name: 设置时间戳变量 set_fact: current_time: "{{ ansible_date_time.iso8601 }}" cacheable: yes - name: Execution Play hosts: target_servers vars_files: - path/to/your/vault.yml tasks: - name: 使用变量 debug: msg: "Vault密钥: {{ my_vault_secret }}, 时间戳: {{ hostvars['staging_server']['current_time'] }}"
内容的提问来源于stack exchange,提问作者SaintRough

