Ansible 时间戳,在整个播放期间对所有节点都是相同的

Ansible timestamp which is the same for all nodes during the whole play

我想要一个时间戳变量,它在所有主机上都是相同的。 (我将其包含在目录名称中:它在所有主机上必须相同)

我最初的想法是在 group_vars/all.yml 中添加一个声明,因为那 优先级比较高,应该分享一下。

group_vars/all.yml:

my_timestamp: "{{ ansible_date_time.date }}{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}{{ ansible_date_time.second }}"

尝试时,主机之间的值不同,导致我的目录结构不一致。 我怀疑这是因为变量只是延迟评估,当引用的 ansible_date_time 对象在每个主机上已经具有不同的值时,具体取决于执行到达变量引用并解析值的确切时刻。

当我尝试在我的剧本中 set_fact 开始时,同样的问题发生了。

site.yml:

---
# This playbook performs the deployment

- name: Prepare playbook settings
  hosts: all
  tasks:
    - name: Generate my timestamp
      set_fact:
        my_timestamp: "{{ ansible_date_time.date }}{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}{{ ansible_date_time.second }}"

问题是:如何设置一个恒定的共享时间戳,在整个剧本执行期间在所有节点上都相同? clean Ansible 生成一致、恒定时间戳的方法是什么?不作为命令行参数传递,打印到文件并读回值等。

我在使用 Ansible 2.9.23。

你的基本问题是,使用或不使用 set_fact,你正在解析一个值,该值填充在为每个主机收集的事实中。由于与您的目标的 ssh 连接永远不会同时发生,每个主机将有不同的值

解决方案是对所有这些使用来自一台主机的一个时间戳。一种方法是从控制器 (localhost) 获取它,但您可以决定从其他地方获取它(例如,在部署游戏期间使用 set_factsrun_once 获取您组中的第一个主机).

这里是使用控制器的想法。适应自己的要求

---
- name: Make sure we gather facts from localhost
  hosts: localhost

- name: Make my actual deployment
  hosts: all

  vars:
    # declare timestamp using localhost values
    my_timestamp: >-
      {{
        hostvars['localhost'].ansible_date_time.date
      }}{{
        hostvars['localhost'].ansible_date_time.hour
      }}{{
        hostvars['localhost'].ansible_date_time.minute
      }}{{
        hostvars['localhost'].ansible_date_time.second
      }}      

  tasks:
    - name: Make sure timestamp value is the same everywhere
      debug:
        var: my_timestamp

    #... rest of your tasks...

正如@Zeitounator 的回答完美指出的那样,变量是按主机设置的,并且是在评估时设置的。

另一种似乎有效的方法是 运行 set_fact 任务一次,因此它只评估一次 (run_once)。喜欢:

- hosts: all
  gather_facts: true

  tasks:
    - name: save timestamp in var
        my_timestamp: "{{ ansible_date_time.date }}{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}{{ ansible_date_time.second }}"
      run_once: true

    - name: show my_timestamp
      debug:
        var: my_timestamp

由于 my_timestamp 设置了一次,现在每个主机上都会显示相同的时间戳。

我采纳了 Zeitounator 的建议,最后使用了一个中间变量。在接受 Zeitounator 的回答的同时,我为任何对实际解决方案感兴趣的人发布了一个代码示例。

---
# This playbook deploys our infrastrucure to each host type
- name: Prepare playbook settings
  hosts: localhost
  tasks:
    - name: Generate my timestamp
      set_fact:
        my_timestamp_local: "{{hostvars['localhost'].ansible_date_time.date}}{{ hostvars['localhost'].ansible_date_time.hour }}{{ hostvars['localhost'].ansible_date_time.minute }}{{hostvars['localhost'].ansible_date_time.second }}"
        cacheable: yes

    - name: Show generated timestamp
      debug:
        var: hostvars['localhost']['my_timestamp_local']


- name: apply common configuration to all nodes
  hosts: all
  vars:
    my_timestamp: "{{hostvars['localhost']['my_timestamp_local']}}"
  roles:
    - common

- name: apply foo node specific configuration
  hosts: foo_nodes
  vars:
    my_timestamp: "{{hostvars['localhost']['my_timestamp_local']}}"
  roles:
    - foo

- name: apply bar node specific configuration
  hosts: bar_nodes
  vars:
    my_timestamp: "{{hostvars['localhost']['my_timestamp_local']}}"
  roles:
    - bar