【问题标题】:Running ansible on the first node在第一个节点上运行 ansible
【发布时间】:2020-11-10 23:44:12
【问题描述】:

我正在尝试配置一系列 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 when:inventory_hostname == groups['web_servers'][0]` 和其他几个变体,但每次代码都在错误的节点上运行。我怀疑它随机选择一个节点 - 也许第二个节点已经运行得更快了?

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

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

【问题讨论】:

    标签: ansible runonce


    【解决方案1】:

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

    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
    

    【讨论】:

      【解决方案2】:

      默认情况下,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
      

      【讨论】:

        【解决方案3】:

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

        - 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 变量进行正则表达式匹配。

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

        【讨论】:

          【解决方案4】:

          问:让任务只在第一个节点上运行。

          web_servers:
            hosts:
              1.2.3.4:
              1.2.3.5:
          

          A:Playbook的关键字order控制hosts的排序

          引用Playbook Keywords

          顺序: 控制用于执行播放的主机的排序。可能的值是inventory(默认)、sorted、reverse_sorted、reverse_inventory 和shuffle。

          默认顺序为inventory,即play中的第一个host就是inventory中的第一个host。使用 run_once

          引用Task Keywords:

          run_once:将绕过主机循环的布尔值,强制任务尝试在第一个可用主机上执行,然后将任何结果和事实应用于同一批次中的所有活动主机。

          例如,剧本

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

          给予

          msg: Creates a backup cron on 1.2.3.4
          

          测试主机的顺序并查看其他选项。给定库存

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

          剧本显示所选顺序的剧本中的第一个主机

          - 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
          

          给予(删节)

            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'
          

          问:无论出于何种原因,它都不适合我。

          答:在这种情况下,将任务委托给组中的第一个主机。见Delegating tasks。例如

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

          给予

          ok: [1.2.3.4 -> groups.webservers.0] => 
            msg: Creates a backup cron on 1.2.3.4
          

          【讨论】:

          • 我知道这在您的测试中有效,但无论出于何种原因,它都不适合我。我知道使用 serial 可以改变一些 ansible 任务的行为(尽管我没有使用 serial),但也许我的环境特有的其他东西导致这些无法工作)
          • 您不介意用mcve 示例更新问题吗?
          猜你喜欢
          • 1970-01-01
          • 2021-07-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-24
          • 1970-01-01
          相关资源
          最近更新 更多