Managing Playbook Execution with Fork, Serial, and Throttle in Ansible
Ansible playbook execution focusing on the linear strategy
Let's see the default behavior of an Ansible playbook execution focusing on the linear strategy and the use of forks.
MyTestPlaybook.yaml
- name: Controlling Playbook Execution with Fork, Serial, and Throttle
hosts: all
gather_facts: no
tasks:
- name: This is the first task
debug:
msg: Task 1 executed
- name: This is the second task
debug:
msg: Task 2 executed
- name: This is the third task
debug:
msg: Task 3 executed
By default, Ansible uses the linear strategy, which means tasks are executed sequentially on all hosts. Each task in the playbook must be completed on all hosts before the next task begins.
Forks
The forks parameter controls the number of parallel processes Ansible will use to execute tasks. By default, Ansible uses five forks, which can be adjusted in the "Ansible" configuration file (ansible.cfg
) or via the command line.
Example Execution
With the linear strategy and five forks, the playbook will execute as follows:
Task 1 will run on up to 5 hosts in parallel.
Once Task 1 completes on all hosts, Task 2 will start.
Task 2 will also run on up to 5 hosts in parallel.
Finally, Task 3 will run on up to 5 hosts in parallel.
This setup ensures tasks are executed in the specified order, but multiple hosts can be processed simultaneously, improving efficiency.
Let us see how it works.
[rajith@controlnode ~]$ ansible-playbook -i inventory MyTestPlaybook.yaml -k
SSH password:
PLAY [Controlling Playbook Execution with Fork, Serial, and Throttle] ***********************************************************************************************************************
TASK [This is the first task] ***************************************************************************************************************************************************************
ok: [node1] => {
"msg": "Task 1 executed"
}
ok: [node2] => {
"msg": "Task 1 executed"
}
ok: [node3] => {
"msg": "Task 1 executed"
}
ok: [node4] => {
"msg": "Task 1 executed"
}
ok: [node5] => {
"msg": "Task 1 executed"
}
ok: [node6] => {
"msg": "Task 1 executed"
}
TASK [This is the second task] **************************************************************************************************************************************************************
ok: [node1] => {
"msg": "Task 2 executed"
}
ok: [node2] => {
"msg": "Task 2 executed"
}
ok: [node3] => {
"msg": "Task 2 executed"
}
ok: [node4] => {
"msg": "Task 2 executed"
}
ok: [node5] => {
"msg": "Task 2 executed"
}
ok: [node6] => {
"msg": "Task 2 executed"
}
TASK [This is the third task] ***************************************************************************************************************************************************************
ok: [node1] => {
"msg": "Task 3 executed"
}
ok: [node2] => {
"msg": "Task 3 executed"
}
ok: [node3] => {
"msg": "Task 3 executed"
}
ok: [node4] => {
"msg": "Task 3 executed"
}
ok: [node5] => {
"msg": "Task 3 executed"
}
ok: [node6] => {
"msg": "Task 3 executed"
}
PLAY RECAP **********************************************************************************************************************************************************************************
node1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node3 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node4 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node5 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node6 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[rajith@controlnode ~]$
Understanding the distinction between using 'serial' and linear execution in an Ansible playbook.
let's dive into this lab exercise and understand the difference between using serial: 3
and a linear execution in an Ansible playbook.
Lab Exercise Explanation
Playbook with serial: 3
serial: 3
Here's the playbook you provided:
- name: Controlling Playbook Execution with Fork, Serial, and Throttle
hosts: all
gather_facts: no
serial: 3
tasks:
- name: This is the first task
debug:
msg: Task 1 executed
- name: This is the second task
debug:
msg: Task 2 executed
- name: This is the third task
debug:
msg: Task 3 executed
Execution with serial: 3
serial: 3
When you specify serial: 3
, Ansible will execute the playbook in batches of 3 hosts at a time. This means that if you have 9 hosts, the playbook will run on the first 3 hosts, then the next 3, and finally the last 3. This can be useful for rolling updates or when you want to limit the number of hosts being updated simultaneously to reduce the risk of widespread failure.
Example Execution:
First batch (3 hosts): Task 1, Task 2, Task 3
Second batch (next 3 hosts): Task 1, Task 2, Task 3
Third batch (last 3 hosts): Task 1, Task 2, Task 3
Linear Execution (without serial
)
serial
)If you remove the serial
directive, Ansible will attempt to execute the playbook on all hosts simultaneously (up to the limit set by the forks
parameter, which defaults to 5).
Example Execution:
All hosts (up to the limit of forks): Task 1, Task 2, Task 3
Difference in Execution
Concurrency:
With
serial: 3
: The playbook runs in batches of 3 hosts, ensuring that only 3 hosts are being processed at any given time.Without
serial
: The playbook runs on all hosts simultaneously, limited by theforks
parameter.
Control:
With
serial: 3
: Provides more control over the deployment process, allowing for staged rollouts and reducing the risk of widespread issues.Without
serial
: Faster execution but with less control, which might be riskier in large environments.
Resource Utilization:
With
serial: 3
: More predictable and controlled resource usage, as only a subset of hosts are being processed at a time.Without
serial
: Higher resource usage as more hosts are processed simultaneously.
Practical Example
Let's say you have 6 hosts: host1
, host2
, host3
, host4
, host5
, and host6
.
With
serial: 3
:First batch:
host1
,host2
,host3
Second batch:
host4
,host5
,host6
Without
serial
:All 6 hosts are processed simultaneously (up to the limit of
forks
).
[rajith@controlnode ~]$ ansible-playbook -i inventory MyTestPlaybook.yaml -k
SSH password:
PLAY [Controlling Playbook Execution with Fork, Serial, and Throttle] ***********************************************************************************************************************************************************************
TASK [This is the first task] ***************************************************************************************************************************************************************************************************************
ok: [node1] => {
"msg": "Task 1 executed"
}
ok: [node2] => {
"msg": "Task 1 executed"
}
ok: [node3] => {
"msg": "Task 1 executed"
}
TASK [This is the second task] **************************************************************************************************************************************************************************************************************
ok: [node1] => {
"msg": "Task 2 executed"
}
ok: [node2] => {
"msg": "Task 2 executed"
}
ok: [node3] => {
"msg": "Task 2 executed"
}
TASK [This is the third task] ***************************************************************************************************************************************************************************************************************
ok: [node1] => {
"msg": "Task 3 executed"
}
ok: [node2] => {
"msg": "Task 3 executed"
}
ok: [node3] => {
"msg": "Task 3 executed"
}
PLAY [Controlling Playbook Execution with Fork, Serial, and Throttle] ***********************************************************************************************************************************************************************
TASK [This is the first task] ***************************************************************************************************************************************************************************************************************
ok: [node4] => {
"msg": "Task 1 executed"
}
ok: [node5] => {
"msg": "Task 1 executed"
}
ok: [node6] => {
"msg": "Task 1 executed"
}
TASK [This is the second task] **************************************************************************************************************************************************************************************************************
ok: [node4] => {
"msg": "Task 2 executed"
}
ok: [node5] => {
"msg": "Task 2 executed"
}
ok: [node6] => {
"msg": "Task 2 executed"
}
TASK [This is the third task] ***************************************************************************************************************************************************************************************************************
ok: [node4] => {
"msg": "Task 3 executed"
}
ok: [node5] => {
"msg": "Task 3 executed"
}
ok: [node6] => {
"msg": "Task 3 executed"
}
PLAY RECAP **********************************************************************************************************************************************************************************************************************************
node1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node3 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node4 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node5 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node6 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[rajith@controlnode ~]$
Conclusion
Using serial
in your playbook provides a way to control the number of hosts being processed at a time, which can be crucial for managing resources and reducing risks during deployments. It allows for more controlled and staged rollouts compared to linear execution, which processes all hosts simultaneously.
Let us see the example Fork and throttle in the next module.
ForkAndThrottle
Feel free to run the playbook with and without the serial
directive to observe the differences in execution.
Last updated