Ansible中的幂等和随机变量

时间:2015-10-27 22:10:14

标签: cron ansible

有没有办法保证使用随机生成的变量的剧本的幂等性?

例如,我想设置我的crontabs以在不同时间触发多个服务器上的电子邮件,因此我使用ansible的set_fact模块创建随机整数:

  tasks:
  - set_fact:
      first_run_30="{{ 30 | random }}"
    run_once: yes

然后使用ansible将生成的变量应用到我的crontab中,如下所示:

   - name: Setup cron30job
    cron: name=cron30job minute={{first_run_30}},{{first_run_30 | int + 30}} job='/bin/bash /cron30job.sh' state=present user=root
    environment:
      MAILTO: 'me@somelist.com'
      MAILFROM: 'me@somehost.com'

这非常有效,但是,我相信,ansible的无效原则是使用这种策略打破的,因为每次进行游戏都会看到变化:

TASK: [Setup cron30job] ***************************************** 
changed: [127.0.0.1]

此外,在三次单独运行期间每次在root下检查crontab:

[ansible]# cat /var/spool/cron/root 
#Ansible: cron30job
5,35 * * * * /bin/bash /sw/test/cron30job.sh
#Ansible: cron30job
9,39 * * * * /bin/bash /sw/test/cron30job.sh
#Ansible: cron30job
6,36 * * * * /bin/bash /sw/test/cron30job.sh

如果有解决方法,或者在我的方案中无法实现无效,我想知道。

3 个答案:

答案 0 :(得分:12)

从Ansible 2.3版本开始,可以从种子初始化随机数生成器。这样,您就可以创建随机但幂等的数字:

"{{ 59 |random(seed=inventory_hostname) }} * * * * root /script/from/cron"

来源:random number filter

我已经使用此模式生成随机的cron开始时间:

  1. 不同目标服务器上的不同分钟
  2. 同一服务器上不同小时的不同分钟(随机性)
  3. 同一天的同一分钟和服务器重复运行Ansible(idempotence)
  4. 需要Ansible> = 2.3:

     cron:
        name: "{{some_name}}_{{item.day}}"
        state: present
        job: "{{some_job}}"
        weekday: "{{item.day}}"
        hour: "{{item.hour}}"
        minute: "{{59|random(seed=inventory_hostname + item.dow)}}"
      with_items:
     - { day: 0, hour: 3, dow: "sunday" }
     - { day: 1, hour: 7, dow: "monday" }
     - { day: 2, hour: 1, dow: "tuesday" }
     - { day: 3, hour: 5, dow: "wednesday" }
     - { day: 4, hour: 2, dow: "thursday" }
     - { day: 5, hour: 4, dow: "friday" }
     - { day: 6, hour: 7, dow: "saturday" }
    

答案 1 :(得分:6)

您可以获取与节点相关的内容,而不是随机值,例如主机名的哈希值或IP地址的最后一个字节。

这是一个例子:

- name: Get a pseudo-random minute 
  shell: expr $((16#`echo "{{inventory_hostname}}" | md5sum | cut -c 1-4`)) % 30
  register: minute
  changed_when: false

答案 2 :(得分:1)

如果您没有ansible >= 2.3,请使用jinja2进行哈希处理:

{{ (inventory_hostname |hash('md5')|int(0, 16)) % 60 }}