所有主机的全局Ansible增量变量

时间:2015-12-13 17:25:25

标签: ansible

我的广告资源中有两台服务器(主机)

[server]
10.23.12.33
10.23.12.40

和playbook(play.yml)

---
- hosts: all
  roles:
    web

vars目录中的web角色我有main.yml

---
file_number : 0

任务目录中的内部Web角色我有main.yml

---
- name: Increment variable
  set_fact: file_number={{ file_number | int + 1 }}

- name: create file
  command: 'touch file{{ file_number }}'

现在我希望在第一台机器上我会有 file1 ,在第二台机器上我会有 file2 ,但在这两台机器上我都有 file1

所以这个变量对于每台机器来说都是本地的,我怎么能让它对所有机器都是全局的。

我的文件结构是:

hosts
play.yml
roles/
  web/
    tasks/
      main.yml
    vars/
      main.yml

3 个答案:

答案 0 :(得分:2)

  

现在我希望在第一台机器上我将拥有file1而在第二台机器中我将拥有file2但在两台机器中我都有file1

您需要记住,Ansible中的变量不是全局变量。变量(又名“事实”)唯一地应用于每个主机,因此host1的file_number与host2的file_number不同。这是一个基于你发布的内容的例子:

角色/测试/瓦尔/ main.yml:

---
file_number: 0

角色/测试/任务/ main.yml:

---
- name: Increment variable
  set_fact: file_number={{ file_number | int + 1 }}

- name: debug
  debug: msg="file_number is {{ file_number }} on host {{ inventory_hostname }}"

现在假设您只定义了两个主机,并且您在一个看起来像这样的剧本中多次运行此角色:

---
- hosts: all
  roles:
    - { role: test }

- hosts: host1
  roles:
    - { role: test }

- hosts: all
  roles:
    - { role: test }

因此,在第一次播放中,角色适用于host1和amp;主机2。在第二场比赛中,它仅针对host1运行,而在第三场比赛中,它再次针对host1和amp;主机2。这本剧本的输出是:

PLAY [all] ********************************************************************

TASK: [test | Increment variable] *********************************************
ok: [host1]
ok: [host2]

TASK: [test | debug] **********************************************************
ok: [host1] => {
    "msg": "file_number is 1 on host host1"
}
ok: [host2] => {
    "msg": "file_number is 1 on host host2"
}

PLAY [host1] **************************************************

TASK: [test | Increment variable] *********************************************
ok: [host1]

TASK: [test | debug] **********************************************************
ok: [host1] => {
    "msg": "file_number is 2 on host host1"
}

PLAY [all] ********************************************************************

TASK: [test | Increment variable] *********************************************
ok: [host1]
ok: [host2]

TASK: [test | debug] **********************************************************
ok: [host1] => {
    "msg": "file_number is 3 on host host1"
}
ok: [host2] => {
    "msg": "file_number is 2 on host host2"
}

正如您所看到的,file_number的值对于host1和host2是不同的,因为增加值的角色对host1的运行次数比对host2的运行次数多。

不幸的是,Ansible中的变量global确实没有干净的方法。 Ansible与大量主机并行运行任务的能力的全部性质使得这样的事情变得非常棘手。除非您在并行环境中非常小心全局变量,否则很容易触发race condition,这可能会导致不可预测(不一致)的结果。

答案 1 :(得分:2)

我还没有找到一个带有ansible的解决方案,尽管我已经开始使用shell为所有主机创建全局变量。

  1. 在localhost中的/ tmp中创建临时文件,并在其中放置起始计数
  2. 读取每个主机的文件并增加文件中的数字
  3. 我创建了该文件并在playbook(play.yml)

    中对其进行了初始化
    - name: Manage localhost working area
      hosts: 127.0.0.1
      connection: local
      tasks:
        - name: Create localhost tmp file
          file: path={{ item.path }} state={{ item.state }}
          with_items:
           - { path: '/tmp/file_num', state: 'absent' }
           - { path: '/tmp/file_num', state: 'touch' }
    
        - name: Managing tmp files
          lineinfile: dest=/tmp/file_num line='0'
    

    然后在main.tml任务中的web角色中,我读取文件并递增它。

    - name: Get file number
      local_action: shell file=$((`cat /tmp/file_num` + 1)); echo $file | tee /tmp/file_num
      register: file_num
    
    - name: Set file name
      command: 'touch file{{ file_num.stdout }}'
    

    现在我有第一个主机 file1 和第二个主机 file2

答案 2 :(得分:0)

您可以使用来自here的Matt Martz解决方案。基本上你的任务就像:

- name: Set file name command: 'touch file{{ play_hosts.server.index(inventory_hostname) }}'

您可以删除所有用于维护全局变量和外部文件的代码:)