Set forks for one task in ansible playbook

17,184

Solution 1

Yes checkout rolling updates

specifically you can add a "serial: x" parameter for a play where x is the number of forks

Solution 2

Yes, this is possible by using the throttle keyword:

Limit number of concurrent task runs on task, block and playbook level. This is independent of the forks and serial settings, but cannot be set higher than those limits. For example, if forks is set to 10 and the throttle is set to 15, at most 10 hosts will be operated on in parallel.

Example:

---

- hosts: all
  tasks:
      - name: wait in parallel
        command: sleep 20
      - name: wait  in serial
        command: sleep 30
        throttle: 1

The throttle keyword is available in Ansible since version 2.9.

Solution 3

In the glossary of terms documentation for Ansible there's this paragraph

Rolling Update

The act of addressing a number of nodes in a group N at a time to avoid updating them all at once and bringing the system offline. For instance, in a web topology of 500 nodes handling very large volume, it may be reasonable to update 10 or 20 machines at a time, moving on to the next 10 or 20 when done. The serial: keyword in an Ansible playbooks control the size of the rolling update pool. The default is to address the batch size all at once, so this is something that you must opt-in to. OS configuration (such as making sure config files are correct) does not typically have to use the rolling update model, but can do so if desired.

Using the --forks=X along with serial: playbook constructs it's not possible to limit a single task to run sequentially. That's because the serial: keyword is only applicable to playbooks. Your only recourse here is to split your tasks up into 2 playbooks and limit the entire play which includes the task you want to run sequentially to serial: 1.

Example

$ cat helloansible.yml
---
- hosts: all
  serial: 1

  tasks:
    - debug:
        msg: "hello ansible - serial"

- hosts: all

  tasks:
    - debug:
        msg: "hello ansible - batched"

When I run this against an inventory you'll see the 1st playbook iterate over each host in the inventory:

$ ansible-playbook -i inventory/lab helloansible.yml -l server*

PLAY [all] **************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************************************
ok: [server-01a.lab1.mydom.local]

TASK [debug] ************************************************************************************************************************************************************************************************
ok: [server-01a.lab1.mydom.local] => {
    "msg": "hello ansible - serial"
}

PLAY [all] **************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************************************
ok: [server-01b.lab1.mydom.local]

TASK [debug] ************************************************************************************************************************************************************************************************
ok: [server-01b.lab1.mydom.local] => {
    "msg": "hello ansible - serial"
}

PLAY [all] **************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************************************
ok: [server-redis-01a.lab1.mydom.local]

TASK [debug] ************************************************************************************************************************************************************************************************
ok: [server-redis-01a.lab1.mydom.local] => {
    "msg": "hello ansible - serial"
}

PLAY [all] **************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************************************
ok: [server-redis-01b.lab1.mydom.local]

TASK [debug] ************************************************************************************************************************************************************************************************
ok: [server-redis-01b.lab1.mydom.local] => {
    "msg": "hello ansible - serial"
}

PLAY [all] **************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************************************
ok: [server-redis-01c.lab1.mydom.local]

TASK [debug] ************************************************************************************************************************************************************************************************
ok: [server-redis-01c.lab1.mydom.local] => {
    "msg": "hello ansible - serial"
}

Whereas in the 2nd playbook that runs:

PLAY [all] **************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************************************
ok: [server-01b.lab1.mydom.local]
ok: [server-redis-01a.lab1.mydom.local]
ok: [server-redis-01c.lab1.mydom.local]
ok: [server-redis-01b.lab1.mydom.local]
ok: [server-01a.lab1.mydom.local]

TASK [debug] ************************************************************************************************************************************************************************************************
ok: [server-01a.lab1.mydom.local] => {
    "msg": "hello ansible - batched"
}
ok: [server-01b.lab1.mydom.local] => {
    "msg": "hello ansible - batched"
}
ok: [server-redis-01a.lab1.mydom.local] => {
    "msg": "hello ansible - batched"
}
ok: [server-redis-01b.lab1.mydom.local] => {
    "msg": "hello ansible - batched"
}
ok: [server-redis-01c.lab1.mydom.local] => {
    "msg": "hello ansible - batched"
}

PLAY RECAP **************************************************************************************************************************************************************************************************
server-01a.lab1.mydom.local : ok=4    changed=0    unreachable=0    failed=0
server-01b.lab1.mydom.local : ok=4    changed=0    unreachable=0    failed=0
server-redis-01a.lab1.mydom.local : ok=4    changed=0    unreachable=0    failed=0
server-redis-01b.lab1.mydom.local : ok=4    changed=0    unreachable=0    failed=0
server-redis-01c.lab1.mydom.local : ok=4    changed=0    unreachable=0    failed=0
Share:
17,184
Todd Chapman
Author by

Todd Chapman

Updated on June 05, 2022

Comments

  • Todd Chapman
    Todd Chapman almost 2 years

    I have one task in my playbook that I want to run on only one host at a time. The rest of the tasks I want to honor the --forks option. Is this possible?