第 6 章 为 AAP2 转换 playbook

使用 Ansible Automation Platform 2 及其容器化执行环境时,localhost 的使用已被修改。在以前的 Ansible Automation Platform 版本中,作业将针对 localhost 运行,它转换为底层 Automation Controller 主机上运行。这可用于存储数据和持久工件。

使用 Ansible Automation Platform 2 时,localhost 意味着您在容器内运行,这是临时的。localhost 不再与特定主机关联,使用可移植的执行环境,这意味着它可以在已嵌入到执行环境容器中的正确环境和软件先决条件的任何位置运行。

6.1. 从自动运行保留数据

将本地 Automation Controller 文件系统视为计数器产品,因为这会将数据绑定到该主机。如果您有多节点集群,那么当您创建依赖于其他和创建的目录的工作流时,每次都会联系不同的主机。例如,如果只在一个节点中创建目录,而另一个节点则运行 playbook,则结果将不一致。

该解决方案是使用某种形式的共享存储解决方案,如 Amazon S3、Gist 或您的数据端点的 rsync 数据的角色。

选项存在在运行时将数据或配置注入容器中。这可以通过自动化控制器的隔离作业路径选项来实现。

这提供了在运行时将目录和文件挂载到执行环境的方法。这可以通过自动化网格来实现,使用 ansible-runner 将它们注入 Podman 容器以启动自动化。以下是使用隔离作业路径的一些用例:

  • 在运行时提供 SSL 证书,而不是将它们纳入执行环境。
  • 传递运行时配置数据,如 SSH 配置设置,但可能是您要提供并在自动化期间使用的任何数据。
  • 在自动化运行期间和之后读取和写入之前使用的文件。

使用率有一些注意事项:

  • 卷挂载必须在所有能够执行自动化的节点上(hybrid control plane 节点和所有执行节点) 预先存在。
  • 如果启用 SELinux (Ansible Automation Platform 默认)是文件权限的。

    • 这很重要,因为无根 podman 在基于非 OCP 安装上运行。

需要仔细观察到注意事项。强烈建议您对无根 Podman 和 Podman 卷挂载选项、隔离作业路径的 [:OPTIONS] 部分进行读取,因为这是 Ansible Automation Platform 2 中使用的内容。

6.1.1. 转换 playbook 示例

例子

这个示例是名为 /mydata 的共享目录,我们希望可以在作业运行期间读取和写入文件。请记住,必须在执行节点上已存在,我们将用于自动化运行。

您将以 aape1.local 执行节点为目标来运行此作业,因为底层主机已经有这个问题。

[awx@aape1 ~]$ ls -la /mydata/
total 4
drwxr-xr-x.  2 awx  awx   41 Apr 28 09:27 .
dr-xr-xr-x. 19 root root 258 Apr 11 15:16 ..
-rw-r--r--.  1 awx  awx   33 Apr 11 12:34 file_read
-rw-r--r--.  1 awx  awx    0 Apr 28 09:27 file_write

您将使用简单的 playbook 启动自动化,并定义 sleep 来供您访问,并了解进程,并演示读取和写入文件。

# vim:ft=ansible:
- hosts: all
  gather_facts: false
  ignore_errors: yes
  vars:
    period: 120
    myfile: /mydata/file
  tasks:
    - name: Collect only selected facts
      ansible.builtin.setup:
        filter:
          - 'ansible_distribution'
          - 'ansible_machine_id'
          - 'ansible_memtotal_mb'
          - 'ansible_memfree_mb'
    - name: "I'm feeling real sleepy..."
      ansible.builtin.wait_for:
        timeout: "{{ period }}"
      delegate_to: localhost
    - ansible.builtin.debug:
        msg: "Isolated paths mounted into execution node: {{ AWX_ISOLATIONS_PATHS }}"
    - name: "Read pre-existing file..."
      ansible.builtin.debug:
        msg: "{{ lookup('file', '{{ myfile }}_read'
    - name: "Write to a new file..."
      ansible.builtin.copy:
        dest: "{{ myfile }}_write"
        content: |
          This is the file I've just written to.

    - name: "Read written out file..."
      ansible.builtin.debug:
        msg: "{{ lookup('file', '{{ myfile }}_write') }}"

在 Ansible Automation Platform 2 中,从 Settings 菜单中选择 Job SettingsJobs

公开隔离任务的路径:

[
"/mydata:/mydata:rw"
]

卷挂载在容器中使用相同的名称进行映射,并具有读写功能。这将在启动作业模板时使用。

prompt on launch 应该为 extra_vars 设置,以便您可以调整每次运行的 sleep 持续时间,默认为 30 秒。

启动后,会调用 wait_for 模块作为睡眠状态,您可以进入执行节点并查看正在运行的内容。

要验证运行是否已成功完成,请运行以下命令以获得作业的输出:

$ podman exec -it 'podman ps -q' /bin/bash
bash-4.4#

您现在位于运行的执行环境容器中。

查看权限,您会看到 awx 已变为 'root',但这并不像在超级用户中一样真正是 root 用户,因为您使用无根 Podman,这会将用户映射到与沙盒类似的内核命名空间中。了解更多有关 rootless Podman 工作方式的信息,适用于 shadow-utils。

bash-4.4# ls -la /mydata/
Total 4
drwxr-xr-x. 2 root root 41 Apr 28 09:27 .
dr-xr-xr-x. 1 root root 77 Apr 28 09:40 ..
-rw-r—--r–. 1 root root 33 Apr 11 12:34 file_read
-rw-r—--r–. 1 root root  0 Apr 28 09:27 file_write

根据结果,此作业会失败。为了了解原因,需要检查剩余的输出。

TASK [Read pre-existing file…]******************************* 10:50:12
ok: [localhost] =>  {
    “Msg”: “This is the file I am reading in.”

TASK {Write to a new file...}********************************* 10:50:12
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: PermissionError: [Errno 13] Permission denied: b'/mydata/.ansible_tmpazyqyqdrfile_write' -> b' /mydata/file_write'
Fatal: [localhost]: FAILED! => {"changed": false, :checksum": "9f576o85d584287a3516ee8b3385cc6f69bf9ce", "msg": "Unable to make b'/root/.ansible/tmp/anisible-tim-1651139412.9808054-40-91081834383738/source' into /mydata/file_write, failed final rename from b'/mydata/.ansible_tmpazyqyqdrfile_write': [Errno 13] Permission denied: b'/mydata/.ansible_tmpazyqyqdrfile_write' -> b'/mydata/file_write}
...ignoring

TASK [Read written out file...] ****************************** 10:50:13
Fatal: [localhost]: FAILED: => {"msg": "An unhandled exception occurred while running the lookup plugin 'file'. Error was a <class 'ansible.errors.AnsibleError;>, original message: could not locate file in lookup: /mydate/file_write. Vould not locate file in lookup: /mydate/file_write"}
...ignoring

作业失败,即使设置了 :rw,因此它应具有写入功能。进程能够读取现有的文件,但不能写出。这是因为 SELinux 保护要求将正确的标签放在挂载到容器中的卷内容上。如果缺少标签,SELinux 可能会阻止进程在容器内运行。Podman 不会更改操作系统设置的标签。如需更多信息,请参阅 Podman 文档。

这可以是常见的错误解释器。我们已将默认值设置为 :z,它会告知 Podman 在共享卷上重新标记文件对象。

因此,我们可以添加 :z 或将其关闭。

公开隔离任务的路径:

[
   "/mydata:/mydata"
]

playbook 现在可以正常工作:

PLAY [all] **************************************************** 11:05:52
TASK [I'm feeling real sleepy. . .] *************************** 11:05:52
ok: [localhost]
TASK [Read pre-existing file...] ****************************** 11:05:57
ok: [localhost] =>  {
	"Msg": "This is the file I'm reading in."
}
TASK [Write to a new file…] ********************************** 11:05:57
ok: [localhost]
TASK [Read written out file…] ******************************** 11:05:58
ok: [localhost] =>  {
      “Msg”: “This is the file I’ve just written to.”

返回到底层执行节点主机,我们有新写入的内容。

注意

如果您使用容器组在 Red Hat OpenShift 中启动自动化作业,我们也可以告诉 Ansible Automation Platform 2 向那个环境公开相同的路径,但您必须在设置下将默认值切换为 On。

启用后,这将将其注入用于执行的 pod 规格中的 volumeMounts。它类似如下:

apiVersion: v1
kind: Pod
Spec:
   containers:
   - image: registry.redhat.io/ansible-automatoin-platform-24/ee-minimal-rhel8
  args:
    - ansible runner
    - worker
    - –private-data-dir=/runner
  volumeMounts:
mountPath: /mnt2
name: volume-0
readOnly: true
mouuntPath: /mnt3
name: volume-1
readOnly: true
mountPath: /mnt4
name: volume-2
readOnly: true
volumes:
hostPath:
  path: /mnt2
  type: “”
name: volume-0
hostPath:
  path: /mnt3
  type: “”
name: volume-1
hostPath:
  path: /mnt4
  type: “”
name: volume-2

运行的容器内的存储使用覆盖文件系统。运行的容器中的任何修改都会在作业完成后销毁,就像被卸载的 tmpfs 一样。