0

我正在尝试配置一系列 Web 服务器。我的库存文件中有以下内容:

web_servers:
  hosts:
    1.2.3.4:
    1.2.3.5:

我想确保第一个主机(1.2.3.4)上创建了一个 cron 作业。但它必须是那个特定的主机。

这是我的ansible yaml:

- name: Creates a backup cron file under /etc/cron.d
  cron:
    name: App Backups
    weekday: "*"
    minute: "0"
    hour: "2"
    user: app
    job: "/scripts/backups.sh"
    cron_file: app-backup

我尝试添加run_once: true以及 何时添加:inventory_hostname == groups['web_servers'][0]` 和其他几个变体,但每次代码在错误的节点上运行。我怀疑它随机选择一个节点 - 也许第二个节点已经运行得更快了?

必须有某种方法来确保它始终在 1.2.3.4 上运行。我不想在 playbook 中对 hosts 文件进行硬编码,因为它将用于设置多个环境,并且 IP 会因环境而异。

有人可以帮我理解如何让任务只在第一个节点上运行吗?

4

4 回答 4

0

Q: "Get the task to run only on the first node."

web_servers:
  hosts:
    1.2.3.4:
    1.2.3.5:

A: Playbook's keyword order controls the sorting of hosts

Quoting from Playbook Keywords

order: Controls the sorting of hosts as they are used for executing the play. Possible values are inventory (default), sorted, reverse_sorted, reverse_inventory, and shuffle.

By default, the order is inventory, i.e. the first host in the play is the first host in the inventory. Use run_once

Quoting from Task Keywords:

run_once: Boolean that will bypass the host loop, forcing the task to attempt to execute on the first host available and afterward apply any results and facts to all active hosts in the same batch.

For example, the playbook

- hosts: webservers
  tasks:
    - debug:
        msg: "Creates a backup cron on {{ inventory_hostname }}"
      run_once: true

gives

msg: Creates a backup cron on 1.2.3.4

Test order of the hosts and see other options. Given the inventory

shell> cat hosts
webservers:
  hosts:
    1.2.3.4:
    1.2.3.5:
    1.2.3.3:

the playbook shows the first host in the play for the selected order

- hosts: webservers
  order: inventory
  tasks:
    - debug:
        msg: "inventory: {{ inventory_hostname }}"
      run_once: true

- hosts: webservers
  order: reverse_inventory
  tasks:
    - debug:
        msg: "reverse_inventory: {{ inventory_hostname }}"
      run_once: true

- hosts: webservers
  order: sorted
  tasks:
    - debug:
        msg: "sorted: {{ inventory_hostname }}"
      run_once: true

- hosts: webservers
  order: reverse_sorted
  tasks:
    - debug:
        msg: "reverse_sorted: {{ inventory_hostname }}"
      run_once: true

- hosts: webservers
  order: shuffle
  tasks:
    - debug:
        msg: "shuffle: {{ inventory_hostname }}"
      run_once: true

gives (abridged)

  msg: 'inventory: 1.2.3.4'
  msg: 'reverse_inventory: 1.2.3.3'
  msg: 'sorted: 1.2.3.3'
  msg: 'reverse_sorted: 1.2.3.5'
  msg: 'shuffle: 1.2.3.5'

Q: "For whatever reason it's not working for me."

A: In this case, delegate the task to the first host in the group. See Delegating tasks. For example

    - debug:
        msg: "Creates a backup cron on {{ inventory_hostname }}"
      run_once: true
      delegate_to: groups.webservers.0

gives

ok: [1.2.3.4 -> groups.webservers.0] => 
  msg: Creates a backup cron on 1.2.3.4
于 2020-11-11T10:24:26.233 回答
0

为了他人的利益,我最终使用了与上述建议完全不同的东西:

- name: Creates a backup cron file under /etc/cron.d
  cron:
    name: App Backups
    weekday: "*"
    minute: "0"
    hour: "2"
    user: app
    job: "/scripts/backups.sh"
    cron_file: app-backup
  when: ansible_hostname is regex (".*[A-za-z]1$")

就我而言,我知道第一台服务器将以数字 1 结尾。所以我对ansible_hostname变量进行正则表达式匹配。

我意识到上述任何建议都不会提到,因为我没有提到系统命名约定,但鉴于上述方法对我不起作用,我想为可能处于类似情况的人提供这种替代方案情况。

于 2020-11-12T11:15:30.460 回答
0

听起来第一个节点应该在自己的组中,然后您可以在游戏中定位:

web_servers:
  hosts:
    1.2.3.4:
    1.2.3.5:

cron_runner:
  hosts:
    1.2.3.4:
- hosts: cron_runner

  tasks:
    - name: Creates a backup cron file under /etc/cron.d
      cron:
        name: App Backups
        weekday: "*"
        minute: "0"
        hour: "2"
        user: app
        job: "/scripts/backups.sh"
        cron_file: app-backup
于 2020-11-11T01:07:10.337 回答
0

默认情况下,Ansible 使用 5 个分叉在任何主机上开始下一个任务之前在受播放影响的所有主机上运行每个任务。

在您的第一次游戏中,使用本地主机中的第一个主机保存一个变量,在您的第二次游戏中使用该变量。

- hosts: localhost

  tasks:
  - name: Get the first host
    set_fact:
      ip_server: "{{ groups['webservers'][0] }}"

- hosts: "{{ hostvars['localhost']['ip_server'] }}"

  tasks:
  - name: Creates a backup cron file under /etc/cron.d
    cron:
      name: App Backups
      weekday: "*"
      minute: "0"
      hour: "2"
      user: app
      job: "/scripts/backups.sh"
      cron_file: app-backup
于 2020-11-11T01:09:23.963 回答