如果可执行文件不存在,Ansible 任务如何失败?

如果可执行文件不存在,Ansible 任务如何失败?

我的 Ansible 剧本的一部分是 K3S 集群创建。

对于服务器节点我有以下任务:

<...>

    - name: Retrieve K3S installation status
      command: which k3s
      changed_when: false
      failed_when: false
      register: k3s_installed

    - name: Install K3S unless already installed
      ansible.builtin.shell: |
        curl -sfL https://get.k3s.io | sh -
      async: 300
      poll: 5
      retries: 3
      when: k3s_installed.rc not in [0]

<...>

第一个任务检查主机上是否已安装 K3S,并将结果捕获到变量中。如果命令缺失,k3s_installed则第二个任务安装 K3S 。k3s

我想更进一步,更新第二个任务,检查k3s安装后的可执行文件是否存在。如果不存在,它应该会失败并重试(我已经尝试过了retries: 3)。类似这样的:

failed_when: <condition that checks if k3s executable still not exists>

我发现的所有 Ansible 示例都有failed_when基于当前任务执行结果(如任务输出或退出代码)的条件。实现此检查的正确方法是什么?

答案1

问:更新第二个任务,检查安装后的 k3s 可执行文件是否存在。

答:创建一个检查所需内容的脚本,然后使用模块脚本代替. 使用参数使此任务幂等创建。 例如,

  - script:
      cmd: "{{ playbook_dir }}/bin/install_k3s.sh"
      creates: /usr/local/bin/k3s

(未经测试)

使用异步如果脚本耗时过长。请参见ansible:将循环(until)与条件(when)结合起来关于如何记录结果、测试结果并重复脚本直到满足条件。

您可以使用模块执行相同操作. 模块的优势脚本测试的简单性。您可以先在远程主机上轻松测试独立脚本。当脚本按您的要求执行时,使用模块脚本

答案2

好的 Ansible 任务会让其参数所要求的事情发生,或者失败。也许你会用额外的任务来补充各种事情,但要让任务不做的事情显而易见。快速失败是件好事。

在这种情况下,安装 k3s 软件。通常我会建议使用包管理器。标准化软件档案的安装、升级、审核和回滚方式。Ansible 包模块可以为各种包管理器执行此操作,如果包不存在,则安装该包,如果无法完成,则出错。

不幸的是,这个脚本不是一个合适的软件包。我不喜欢软件安装脚本。它不受软件包管理器的跟踪。有时会从互联网上下载随机脚本和二进制文件。不符合我首选发行版的惯例。并且在错误情况下或再次运行时它们的行为不可靠。

无论如何,您无法真正将“文件存在于远程主机上”任务添加到运行某些任意脚本的任务中。 Ansible 在每个任务中运行一个执行实际工作的低级脚本。 shell 模块仅具有要工作的脚本的返回代码(如果您编写了一个巧妙的 failed_when 表达式,则还有 stdout 或 stderr)。

相反,在安装任务之后执行另一个任务,运行一个简单的 k3s 命令。获取版本或使用文本,或使用它进行一些实际工作,或其他操作。如果它在 $PATH 上不存在,Ansible 将像您预期的那样出错。替换实际不执行任何操作但返回代码为零的选项。

# Install K3S goes here

- name: Check K3S installed
  command: k3s

Ansible 没有很好的方法来重试一组任务,例如安装软件后的这些额外检查。此外,我想看看故障模式,以评估重试是否有用。所以现在不要使用until关键字。

相反,你应该集中精力改进脚本,或者将其构建成合适的软件包存档。无论哪种方式,你都可能想要下载并自定义自己的构建,而不是从互联网上下载。只需打包维护者的东西。

相关内容