Ansible async_status task - error: ansible_job_id "undefined variable"

Ansible async_status task - error: ansible_job_id "undefined variable"

我有一个 3 节点 ubuntu 20.04 lts - kvm - kubernetes 集群,kvm-host 也是 ubuntu 20.04 lts。我 运行 kvm-host 上的剧本。 我有以下清单摘录:

nodes:
  hosts:
    sea_r:
      ansible_host: 192.168.122.60
    spring_r:
      ansible_host: 192.168.122.92
    island_r:
      ansible_host: 192.168.122.93
  vars:
    ansible_user: root

已经尝试了很多async_status,但总是失败

- name: root commands
  hosts: nodes
  tasks:
  - name: bash commands
    ansible.builtin.shell: |
      apt update
    args:
      chdir: /root
      executable: /bin/bash
    async: 2000
    poll: 2
    register: output

  - name: check progress
    ansible.builtin.async_status:
      jid: "{{ output.ansible_job_id }}"
    register: job_result
    until: job_result.finished
    retries: 200
    delay: 5

有错误:

fatal: [sea_r]: FAILED! => {"msg": "The task
includes an option with an undefined variable. 
The error was: 'dict object' has no attribute
'ansible_job_id' ...

如果我改为尝试以下方法,

- name: root commands
  hosts: nodes
  tasks:
  - name: bash commands
    ansible.builtin.shell: |
      apt update
    args:
      chdir: /root
      executable: /bin/bash
    async: 2000
    poll: 2
    register: output
  - debug: msg="{{ output.stdout_lines }}"
  - debug: msg="{{ output.stderr_lines }}"

我没有收到任何错误。 还尝试了以下变体,

  - name: check progress
    ansible.builtin.async_status:
      jid: "{{ item.ansible_job_id }}"
    with_items: "{{ output }}"
    register: job_result
    until: job_result.finished
    retries: 200
    delay: 5

有人建议 as a solution to similar error。那也无济于事,我只是得到了稍微不同的错误:

fatal: [sea_r]: FAILED! => {"msg": "The task includes
an option with an undefined variable. The error 
was: 'ansible.utils.unsafe_proxy.AnsibleUnsafeText
object' has no attribute 'ansible_job_id' ...

在剧本的开头和结尾,我像这样恢复和暂停我的 3 个 kvm 服务器节点:

- name: resume vms
  hosts: local_vm_ctl
  tasks:
  - name: resume vm servers
    shell: |
      virsh resume kub3
      virsh resume kub2
      virsh resume kub1
      virsh list --state-paused --state-running
    args:
      chdir: /home/bi
      executable: /bin/bash
    environment:
      LIBVIRT_DEFAULT_URI: qemu:///system
    register: output
  - debug: msg="{{ output.stdout_lines }}"
  - debug: msg="{{ output.stderr_lines }}"

等等

- name: pause vms
  hosts: local_vm_ctl
  tasks:
  - name: suspend vm servers
    shell: |
      virsh suspend kub3
      virsh suspend kub2
      virsh suspend kub1
      virsh list --state-paused --state-running
    args:
      chdir: /home/bi
      executable: /bin/bash
    environment:
      LIBVIRT_DEFAULT_URI: qemu:///system
    register: output
  - debug: msg="{{ output.stdout_lines }}"
  - debug: msg="{{ output.stderr_lines }}"

但我不明白这些戏剧与上述错误有什么关系。

任何帮助将不胜感激。

您的工作 ID 出现未定义错误,因为:

  1. 您在初始任务中使用 poll: X,因此 ansible 每 X 秒连接一次以检查任务是否完成
  2. 当 ansible 存在那个任务并进入你的下一个 async_status 任务时,工作就完成了。并且由于您对 poll 使用了非零值,因此自动清除了异步状态缓存。
  3. 由于缓存被清除,作业id不再存在。

你上面的场景是为了避免你的目标在长时间的 运行ning 任务上超时,而不是为了 运行 任务并发并有一个稍后的状态检查点。对于第二个需求,你需要运行异步任务poll: 0并自行清理缓存

有关上述概念的更多解释,请参阅文档:

我用你的上述任务做了一个例子,并将其修复为使用专用模块 apt(请注意,你可以向模块添加一个 name 选项,其中包含一个或一系列包和ansible 会一步完成缓存更新和安装)。此外,async_status 任务的 retries * delay 应该等于或大于初始任务的 async,如果你想确保你不会错过最后。

- name: Update apt cache
  ansible.builtin.apt:
    update_cache: true
  async: 2000
  poll: 0
  register: output

- name: check progress
  ansible.builtin.async_status:
    jid: "{{ output.ansible_job_id }}"
  register: job_result
  until: job_result.finished
  retries: 400
  delay: 5

- name: clean async job cache 
  ansible.builtin.async_status:
    jid: "{{ output.ansible_job_id }}"
    mode: cleanup

这对于并行启动一堆持久任务更有用。这是一个无用但实用的示例:

- name: launch some loooooong tasks
  shell: "{{ item }}"
  loop:
    - sleep 30
    - sleep 20
    - sleep 35
  async: 100
  poll: 0
  register: long_cmd

- name: wait until all commands are done
  async_status:
    jid: "{{ item.ansible_job_id }}"
  register: async_poll_result
  until: async_poll_result.finished
  retries: 50
  delay: 2
  loop: "{{ long_cmd.results }}"

- name: clean async job cache
  async_status:
    jid: "{{ item.ansible_job_id }}"
    mode: cleanup
  loop: "{{ long_cmd.results }}"

你的任务有 poll: 2,它告诉 Ansible 每 2 秒在内部轮询一次异步作业,并 return 注册变量中的最终状态。 In order to use async_status 你应该设置 poll: 0 这样任务就不会等待作业完成。