I have a playbook with multiple tasks for a single role, i want to divide the tasks say 80% to first host and remaining 20% to second host , the first and second host will be picked from
ansible-playbook -i 1.2.3.4, 2.3.4.5, update.yml
where 1.2.3.4 is first server ip and 2.3.4.5 is second server ip. How can i achieve this.
To recap:
You have one role with 10 tasks. 6 of which you want to execute on server 1 and the rest on server 2
A way would be to write 2 different playbooks which will include the tasks you want to execute on the specified hosts.
Another might be to use tags on each task and execute ansible with --tags and specify them on playbook level
- hosts: all
tags:
- foo
role:
...
- hosts: all
tags:
- bar
role:
...
ref https://docs.ansible.com/ansible/latest/user_guide/playbooks_tags.html
Playbook tasks execution can be controlled by tags or blocks. My previous answer was related to the task execution on few of the hosts(I miss understood)
For eg.
serial: "80%"
would mean that all the tasks will be performed on 80% of the hosts first then will be performed on the remaining hosts.
For playbook to execute some tasks on few hosts and some on few hosts you can may be use when with ansible_hostname set to some hosts
Related
My use case is to use a single playbook to run the same role on 2 different host groups, but I want to pass different variable values depending on the host group the role is executing against.
I've tried many ways of doing this, but I am finding the second play for the second host group is not executed.
---
- name: Run against webservers
hosts: webservers
vars: var1: "val_a"
roles:
- common_role
- name: Run against dbservers
hosts: dbservers
vars: var1: "val_b"
roles:
- common_role
```
when I execute code similar to above, it only executes the first play, against webservers, and terminates. Is my use case valid? (i.e. execution of same role, against 2 host groups, but passing different variable values for each group, within single playbook)
You can set the ignore_errors on the failing task to continue the execution.
- fail:
when: var1 == 'val_a'
ignore_errors: true
But keep in mind that current role continue to execute rest of the tasks after failing one too.
I have set of tasks that i want to execute at set of hosts sequentially.
Example is below.
hosts: all
tasks:
- name: do some work
include_tasks: tasks_here.yml
loop: "{{ vars[play_hosts] }}"
ansible-playbook main.yml --limit myhosts
I expect that set of tasks would be executed at first host, then at second host etc... But in fact these tasks are being executed simulatineously at all hosts in "limit".
I suspect that it's happening because I use limit but i need it in my case.
So what I should I do?
By default, as specified here:
plays run with a linear strategy, in which all hosts will run each task before any host starts the next task.
You can use the strategy serial: 1 to execute the tasks on each host sequentially.
For example:
- hosts: all
serial: 1
tasks:
...
When the serial parameter is 1, Ansible takes a host and then executes the tasks given in the playbook before moving onto the next host.
But what happens when serial parameter is more than one?
For example, if I have 10 hosts and my serial parameter is 3, how will those 3 tasks execute the tasks? Will those tasks be executed one after another one host at a time? Or will it be executed like the default execution strategy, each host will execute the first task before moving on the next one.
I haven't found any documentation that refers to this.
Given the assumption you keep the standard strategy, each play of the playbook will be executed on as many nodes as you specified on the keyword serial, but task by task, so even if you have a node that run a task faster than the others node, It won't run the next task, until the others have finished the same task. Then another 3 nodes will be taken from the inventory. If you have another play, the same scenario will be done.
so basically with your 10 nodes inventory that will do
take 3 nodes
execute tasks
take 3 nodes
execute tasks
take 3 nodes
execute tasks
take remaining node
execute tasks
The behaviour is explained in https://docs.ansible.com/ansible/2.5/user_guide/playbooks_strategies.html
The serial directive can ‘batch’ this behaviour to a subset of the
hosts, which then run to completion of the play before the next
‘batch’ starts.
I suggest you to have such test playbook to play with to understand playbook, plays and serial.
- hosts: all
gather_facts: false
serial: 3
tasks:
- ping:
- ping:
- hosts: all
gather_facts: false
serial: 5 # test with 5 nodes now
tasks:
- ping:
- ping:
if you want to simulate the difference of behaviour, you can run your playbook with the option -C
Consider next scenario:
multiple hosts needs to be configured independently. At some point in time, after ALL configuration tasks on ALL hosts been completed successfully, some final tasks needs to be run on ONLY ONE host. what would be the proper solution for ansible playbook ?
Use run_once for that: http://docs.ansible.com/ansible/latest/user_guide/playbooks_delegation.html#run-once
Example:
---
- hosts: all
tasks:
- command: echo preparing stuff on all hosts
- command: echo run only on single host
run_once: True
We have a "periodic" tag in our roles that is intended to be run at regular intervals by our Ansible box for file assurance, etc. Would it be possible to have a playbook for periodic runs that calls the other playbooks with the appropriate host groups and tags?
The only way to execute an Ansible playbook "with the appropriate host groups and tags" is to run ansible-playbook executable. This is the only case in which all the data structures starting from the inventory would be created in isolation from the currently running playbook.
You can simply call the executable using command module on the control machine:
- hosts: localhost
tasks:
- command: ansible-playbook {{ playbook }} --tags {{ tags }}
You can also use local_action or delegate_to.
It might be that you want to include plays, or use roles, however given the problem description in the question, it's impossible to tell.
Here is what we ended up with: It turns out that tags and variables passed on the command-line are inherited all the way down the line. This allowed us to pass this on the command line:
ansible-playbook -t periodic periodic.yml
Which calls a playbook like this:
---
- name: This playbook must be called with the "periodic" tag.
hosts: 127.0.0.1
any_errors_fatal: True
tasks:
- fail:
when: periodic not True
- name: Begin periodic runs for type 1 servers
include: type1-server.yml
vars:
servers:
- host_group1
- host_group2
- ...
- name: Begin periodic runs for type 2 servers
...
Our 'real' playbooks have - hosts: "{{ servers }}" so that they can be inherited from the parent. The tasks in our roles are tagged with "periodic" for things that need to be run on a schedule. We then use SystemD to schedule the runs. You can use cron, but SystemD is better IMHO. Examples can be provided upon request.