For now we have seen how to install Ansible on CentOS/RHEL & Ubuntu, and tried some sample commands. Now will see how to write your first ever playbook and how run it. For that login to your ansible controller (knowly where do you installed ansible and call it as master or whatever you named)
To make sure you have a root login to all listed hosts in inventory use below command;
# ansible all -m shell -a id
Controller.foxutech.com | success | rc=0 >> uid=0(root) gid=0(root) groups=0(root)
This shows that the login was successful (return code zero = OK) and that when the command “id” was run on the remote machines, it was running as user “root”.
Writing a playbook
A playbook comprises of a list of hosts and tasks entries, like below:
- hosts: ... tasks: ... - hosts: ... tasks: ... - hosts: ... tasks: ...
In each section, you define a set of task(s) to be run on a set of host(s). The playbook is run in sequence way, although the same task can run on multiple hosts in parallel.
Write First playbook
You will do the following as the “ansible” user. Make sure you are in ansible user home directory;
# pwd # should get /home/ansible
If you are not on the particular user home directory, use ‘cd’ to change Directory. Once you been to the directory, create a playbook file with “.yml” file extension. For example: “ping.yml” (you can name it any). Add below content and check it.
# vim ping.yml
- hosts: - all tasks: - action: ping
Now run the playbook like this:
# ansible-playbook ping.yml
Did it work? The output should have these sections:
This is when the “setup” module is being run to collect information about the hosts you are connecting to
The task you defined in the playbook
Summarizes which tasks were run, how many were success or failure, and how many changes were made
So far your playbook is essentially doing what you did using the ansible command-line.
Let’s Create a Web Server
Let’s use real time example, which we can reproduce for few more examples too. Let’s install nginx package in two systems.
Create webserver.yml which looks like this:
- hosts: - server1.foxutech.com - server2.foxutech.com tasks: - action: yum update_cache=yes - action: yum pkg=nginx state=present
Replace server1 and server2 with two of the hosts you are managing; they must exist in your inventory.
Run it (note that it may be slow the first time).
# ansible-playbook webserver.yml
Hope it’s working!!!, Make a note of “ok” & “Changed” values
Let’s Run it again:
# ansible-playbook webserver.yml
How do the “ok” and “changed” values look now?
Explanation: there are two tasks involving the yum module. One updates the cache of available packages (like “yum update”) and the other ensures that nginx is installed.
Once it done, you can see on both server web service installed, you can open the URL server1.foxutech.com & server2.foxutech.com and check it.
You should see “Nginx Ubuntu Default Page”
It would be helpful if the playbook could be self-documenting, so edit webserver.yml so it now looks like this:
- hosts: - server1.foxutech.com - server2.foxutech.com tasks: - name: ensure package cache is up to date action: yum update_cache=yes - name: install web server action: yum pkg=nginx state=present
Run it again. You should get more helpful TASK descriptions as it runs.
Copy a File
Instead of nginx webpage, sometime we would like to have our own web page. For that that let’s write a own html page.
On ansible home directory, create a file web.html with some HTML text, e.g.
<html> <head><title>FoxuTech’s Ansible</title></head> <body> This is FoxuTech’s Ansible page </body> </html>
Now add a new task to our playbook:
- hosts: - server1.foxutech.com - server2.foxutech.com tasks: - name: ensure package cache is up to date yum: update_cache=yes - name: install web server yum: pkg=nginx state=present - name: install index page copy: src=web.html dest=/var/www/html/index.html backup=yes
After this has run successfully (check for “changed=1”), point your web browser at your two hosts and check you have a new index page.
What about if we wanted to keep the original file? That is what backup=yes is for. If you log in to one of those hosts and look at the contents of that directory, you’ll see that the original file is still there but renamed to a name containing its timestamp.
# ls /var/www/html
Check and Diff
Suppose you want to know what changes ansible will make, before it makes them? Two flags are provided for this.
- –check will tell you which changes would be made, without actually making them. (Not all modules support this)
- –diff shows you the differences between the old and new files
It is common to use both flags. Try changing the text in front.html, and then running this command:
# ansible-playbook webserver.yml --check --diff
It should identify that index.html is going to be updated, and show you the differences.
Run it again without the –check flag and then it will actually apply the change.
Sometimes when you make a configuration change it’s necessary to restart the service. Ansible supports this though “handlers”.
Imagine that whenever the index.html page changes you need to restart nginx (although that’s not actually true). You add a “notify:” statement to every action which needs the restart, and a “handler:” which performs the restart.
- hosts: - server1.foxutech.com - server2.foxutech.com tasks: - name: ensure package cache is up to date yum: update_cache=yes - name: install web server yum: pkg=nginx state=present - name: install index page copy: src=web.html dest=/var/www/html/index.html backup=yes notify: restart nginx handlers: - name: restart nginx service: name=nginx state=restarted
Run your playbook again, firstly without changing front.html, and then after changing front.html.
In the latter case you should see
NOTIFIED: [restart nginx]
which shows that the handler was triggered.
As your playbook gets bigger, it may get slower to run, and you may wish to run only part of a playbook to bypass the earlier steps. The way to do this is using ‘tags’. Example:
- hosts: - server1.foxutech.com - server2.foxutech.com tasks: - name: ensure package cache is up to date yum: update_cache=yes tags: install - name: install web server yum: pkg=nginx state=present tags: install - name: install index page copy: src=web.html dest=/var/www/html/index.html backup=yes tags: configure notify: restart nginx handlers: - name: restart nginx service: name=nginx state=restarted
# ansible-playbook webserver.yml -t configure
and it will run only the task which has been tagged as “configure”. When writing a playbook, you can assign whatever tags make sense to you.
To Run a playbook on Particular Hosts
You can also tell the playbook to run against only a single host or a subset of hosts. The way to do this is with the ‘-l’ (limit) option.
# ansible-playbook webserver.yml -l server2.foxutech.com
This is particularly useful for testing and staged rollout; but note that the -l flag is only a filter against the hosts already listed in the playbook. It cannot cause the playbook to run against other hosts.
# ansible-playbook webserver.yml -l 'server2.foxutech.com;server3.foxutech.com '
will only run those tasks which were already defined to run on either server2 or server3.
Finally, a way to make your playbook easier to maintain is to make use of host groups in the inventory.
Edit your inventory file (/etc/ansible/hosts), remembering you have to use sudo to do this. Divide it into groups by adding group headings surrounded by square brackets, so that it looks like this:
# cat /etc/ansible/hosts
[app_web] server1.foxutech.com ansible_ssh_user=root server2.foxutech.com ansible_ssh_user=root [app_db] server3.foxutech.com ansible_ssh_user=root
Then you can simplify your playbook by listing the groups instead of the individual hosts:
- hosts: - app_web tasks: ... as before - hosts: - app_db tasks: ... as before
Now test that everything still works:
# ansible-playbook webserver.yml
You can also use groups on the command line, e.g.
# ansible app_web -m shell -a 'ls /'
Your webserver.yml file now documents exactly how you built your web servers, and can be used to create additional servers, or rebuild a server if its disk dies.
This means that it’s a valuable asset. You should store it somewhere safe, e.g. in a version control system like subversion or git, or in a backed-up file server
This is the end, hope now you understand how to write a playbook, and how use tags, handlers. On next session will see what roles and how to create/run it.