
In the previous article, we saw how to install Ansible, ping a server and a simple playbook.
In this article we’ll discuss about using groups , use of variables and loops in a playbook.
This setup includes 3 machines. The controller node is a local machine where the managed nodes are two ec2 instances.
Inventory Groups
Ansible allows you to organize hosts into groups within the inventory file. Grouping hosts enables you to target specific subsets of hosts and apply different configurations or tasks based on their roles or characteristics.
We can create groups as below:
# cat hostlist
[uat]
35.154.191.210
[prod]
65.0.7.153
---
- hosts: uat
become: true
tasks:
- apt:
name:
- apache2
state: present
# ansible-playbook groups.yaml
____________
< PLAY [uat] >
------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
________________________
< TASK [Gathering Facts] >
------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
ok: [35.154.191.210]
____________
< TASK [apt] >
------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
changed: [35.154.191.210]
____________
< PLAY RECAP >
------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
35.154.191.210 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
To disable the cowsay prompt, add nocows=1 in ansible.cfg
cat ansible.cfg
[defaults]
inventory=./hostlist
remote_user=ubuntu
ask_pass=false
nocows=1
[privilege_escalation]
become=true
become_method=sudo
Now lets change our playbook to include 2nd group and run the playbook.
---
- hosts: uat
name: Install Apache HTTP server
become: true
tasks:
- apt:
name:
- apache2
state: present
- hosts: prod
name: Install cURL
become: true
tasks:
- apt:
name:
- curl
state: present
ansible-playbook groups.yaml
PLAY [Install Apache HTTP server] ********************
TASK [Gathering Facts] *******************************
ok: [35.154.191.210]
TASK [apt] *******************************************
ok: [35.154.191.210]
PLAY [Install cURL] **********************************
TASK [Gathering Facts] *******************************
ok: [65.0.7.153]
TASK [apt] *******************************************
ok: [65.0.7.153]
PLAY RECAP *******************************************
35.154.191.210 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
65.0.7.153 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Group alll
The “all” indicates all the hosts, we don’t need to specify it explicitly, ansible takes this as default.
---
- hosts: uat
name: Install Apache HTTP server
become: true
tasks:
- apt:
name:
- apache2
state: present
- hosts: prod
name: Install cURL
become: true
tasks:
- apt:
name:
- curl
state: present
- hosts: all
name: Create User
tasks:
- user:
name: sagar
state: present
ansible-playbook groups.yaml
PLAY [Install Apache HTTP server] ****
TASK [Gathering Facts] ***************
ok: [35.154.191.210]
TASK [apt] ***************************
ok: [35.154.191.210]
PLAY [Install cURL] ******************
TASK [Gathering Facts] ***************
ok: [65.0.7.153]
TASK [apt] ***************************
ok: [65.0.7.153]
PLAY [Create User] *******************
TASK [Gathering Facts] ***************
ok: [65.0.7.153]
ok: [35.154.191.210]
TASK [user] **************************
changed: [65.0.7.153]
changed: [35.154.191.210]
PLAY RECAP ***************************
35.154.191.210 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
65.0.7.153 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Using Variables:
Example: If we want to install any application or perform any tasks on the nodes, we need to mention those application/task names inside playbook at various places. To avoid repetitive writing, we can create variables and call them in our tasks. We can create variables inside playbook or outside as a separate file.
---
- hosts: all
vars:
- pkg:
- apache2
- net-tools
- usr:
- kumar
tasks:
- name: Install applications {{pkg}}
apt:
name: "{{pkg}}"
state: present
- name: Create user {{usr}}
user:
name: "{{usr}}"
state: present
# ansible-playbook varsplay.yaml
PLAY [all] ******************
TASK [Gathering Facts] ******
ok: [65.0.7.153]
ok: [35.154.191.210]
TASK [Install applications ['apache2', 'net-tools']] *********
changed: [35.154.191.210]
changed: [65.0.7.153]
TASK [Create user ['kumar']] *******
changed: [65.0.7.153]
changed: [35.154.191.210]
PLAY RECAP ************************
35.154.191.210 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
65.0.7.153 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
We can also create the variables as a separate yaml file and include here.
cat vars.yaml
pkg: vim
usr: nothing
---
- hosts: all
vars_files:
- vars.yaml
tasks:
- name: Install applications {{pkg}}
apt:
name: "{{pkg}}"
state: present
- name: Create user {{usr}}
user:
name: "{{usr}}"
state: present
ansible-playbook varsplay.yaml
PLAY [all] ************************
TASK [Gathering Facts] ************
ok: [65.0.7.153]
ok: [35.154.191.210]
TASK [Install applications vim] ****
ok: [65.0.7.153]
ok: [35.154.191.210]
TASK [Create user nothing] *********
changed: [65.0.7.153]
changed: [35.154.191.210]
PLAY RECAP *************************
35.154.191.210 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
65.0.7.153 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Conditionals:
Ansible can use conditionals to execute tasks or plays when certain conditions are met. For example, a conditional can be used to check the OS distribution on a managed host before Ansible installs or configures a service.
- name: install package based on OS
hosts: all
tasks:
- name: install package if CentOS
yum:
name: httpd
state: present
when: ansible_distribution == 'CentOS'
- name: install package if Ubuntu
apt:
name: apache2
state: present
when: ansible_distribution == 'Ubuntu'
ansible-playbook condition.yaml
PLAY [install package based on OS] *********
TASK [Gathering Facts] *********************
ok: [35.154.191.210]
ok: [65.0.7.153]
TASK [install package if CentOS] ***********
skipping: [35.154.191.210]
skipping: [65.0.7.153]
TASK [install package if Ubuntu] ***********
ok: [65.0.7.153]
ok: [35.154.191.210]
PLAY RECAP **********************************
35.154.191.210 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
65.0.7.153 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Loops:
With the loop keywords, we can execute a task multiple times.
- name: create users
hosts: all
tasks:
- name: create user
user:
name: "{{ item }}"
state: present
loop:
- user1
- user2
- user3
- user4
ansible-playbook loopplay.yaml
PLAY [create users] ************************
TASK [Gathering Facts] *********************
ok: [65.0.7.153]
ok: [35.154.191.210]
TASK [create user] *************************
changed: [35.154.191.210] => (item=user1)
changed: [65.0.7.153] => (item=user1)
changed: [35.154.191.210] => (item=user2)
changed: [65.0.7.153] => (item=user2)
changed: [65.0.7.153] => (item=user3)
changed: [35.154.191.210] => (item=user3)
changed: [35.154.191.210] => (item=user4)
changed: [65.0.7.153] => (item=user4)
PLAY RECAP ************************************
35.154.191.210 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
65.0.7.153 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Using loops and variables:
Create usrvar.yml containing all the username and usersplay.yml for the task playbook.
#vim usrvar.yml
usr:
- usera
- userb
- userc
- userd
#vim usersplay.yml
- name: create users
hosts: all
vars_files:
- usrvar.yml
tasks:
- name: create user
user:
name: "{{ item }}"
state: present
loop: "{{ usr }}"
ansible-playbook usersplay.yaml
PLAY [create users] *************************
TASK [Gathering Facts] **********************
ok: [35.154.191.210]
ok: [65.0.7.153]
TASK [create user] **************************
changed: [65.0.7.153] => (item=usera)
changed: [35.154.191.210] => (item=usera)
changed: [65.0.7.153] => (item=userb)
changed: [35.154.191.210] => (item=userb)
changed: [65.0.7.153] => (item=userc)
changed: [35.154.191.210] => (item=userc)
changed: [65.0.7.153] => (item=userd)
changed: [35.154.191.210] => (item=userd)
PLAY RECAP ************************************
35.154.191.210 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
65.0.7.153 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
This is the End of the article. We’ll see more features in future tutorial. Thanks for reading.
Make sure to terminate any vm instances if you have created to avoid incurring charges.
Read More on Ansible:
Reference: Ansible Docs.