What Is Ansible?: Ansible Tutorial For Beginners: Playbook, Commands & Example
What Is Ansible?: Ansible Tutorial For Beginners: Playbook, Commands & Example
What Is Ansible?: Ansible Tutorial For Beginners: Playbook, Commands & Example
What is Ansible?
Ansible is an open source automation and orchestration tool for software provisioning,
configuration management, and software deployment. Ansible can easily run and configure
Unix-like systems as well as Windows systems to provide infrastructure as code. It contains its
own declarative programming language for system configuration and management.
Ansible is popular for its simplicity of installation, ease of use in what concerns the connectivity
to clients, its lack of agent for Ansible clients and the multitude of skills. It functions by
connecting via SSH to the clients, so it doesn't need a special agent on the client-side, and by
pushing modules to the clients, the modules are then executed locally on the client-side and the
output is pushed back to the Ansible server.
Since it uses SSH, it can very easily connect to clients using SSH-Keys, simplifying though the
whole process. Client details, like hostnames or IP addresses and SSH ports, are stored in files
called inventory files. Once you have created an inventory file and populated it, ansible can use
it.
In this Ansible tutorial for beginners, you will learn Ansible step by step:
• What is Ansible?
• Why use Ansible?
• History of Ansible
• Important terms used in Ansible
• Ansible Installation in Linux
• Ansible ad-hoc commands
• Ansible Playbooks
• Ansible Roles
• Ansible Case Study
• Ansible Commands Cheat Sheet
• One of the most significant advantages of Ansible is that it is free to use by everyone.
• It does not need any special system administrator skills to install and use Ansible, and the official
documentation is very comprehensive.
• Its modularity regarding plugins, modules, inventories, and playbooks make Ansible the perfect
companion to orchestrate large environments.
• Ansible is very lightweight and consistent, and no constraints regarding the operating system or
underlying hardware are present.
• It is also very secure due to its agentless capabilities and due to the use of OpenSSH security
features.
• Another advantage that encourages the adoption of Ansible is its smooth learning curve
determined by the comprehensive documentation and easy to learn structure and
configuration.
History of Ansible
Here, are important land marks from the history of ansible:
• In February 2012 the Ansible project began. It was first developed by Michael DeHaan, the
creator of Cobbler and Func, Fedora Unified Network Controller.
• Initially called AnsibleWorks Inc, the company funding the ansible tool was acquired in 2015 by
RedHat and later on, along with RedHat, moved under the umbrella of IBM.
• In the present, Ansible comes included in distributions like Fedora Linux, RHEL, Centos and
Oracle Linux.
• Module:
Basically, a module is a command or set of similar Ansible commands meant to be executed on
the client-side
• Task:
A task is a section that consists of a single procedure to be completed
• Role:
A way of organizing tasks and related files to be later called in a playbook
• Fact:
Information fetched from the client system from the global variables with the gather-facts
operation
• Inventory:
File containing data about the ansible client servers. Defined in later examples as hosts file
• Play:
Execution of a playbook
• Handler:
Task which is called only if a notifier is present
• Notifier:
Section attributed to a task which calls a handler if the output is changed
• Tag:
Name set to a task which can be used later on to issue just that specific task or group of tasks.
For this Ansible tutorial, a simple two servers hosts file will be configured, containing host1 and
host2.
You can make sure that the hosts are accessible from the ansible server by issuing a ping
command on all hosts.
You can issue the same command only on a specific host if needed.
Explanation:
1. –Limit parameter can be used to issue commands only on specific hosts in the host's file
2. Name of the host as defined in the inventory file
If you need to copy a file to multiple destinations rapidly, you can use the copy module in
ansible which uses SCP. So the command and its output look like below:
In the next example, you will find out how to install a package via the yum module on two
Centos hosts.
Of course, all of the yum installer options can be used via ansible, including update, install, latest
version, or remove.
In the below example the same command was issued to remove the previously installed ncdu
package.
1. The output of the yum command shows that the package was removed.
Another useful and essential feature that ansible uses to interact with the client's server is to
gather some facts about the system. So, it fetches hardware, software, and versioning information
from the system and stores each value in a variable that can be later on used.
If you need detailed information about the systems to be modified via ansible, the next command
can be used. The setup module gathers facts from the system variables.
Ansible Playbooks
Ansible Playbooks are the way of sending commands to remote systems through scripts.
Ansible playbooks are used to configure complex system environments to increase flexibility by
executing a script to one or more systems. Ansible playbooks tend to be more of a configuration
language than a programming language.
Ansible playbook commands use YAML format, so there is not much syntax needed, but
indentation must be respected. Like the name is saying, a playbook is a collection of plays.
Through a playbook, you can designate specific roles to some hosts and other roles to other
hosts. By doing so, you can orchestrate multiple servers in very diverse scenarios, all in one
playbook.
To have all the details precise before continuing with Ansible playbook examples, we must first
define a task. These are the interface to ansible modules for roles and playbooks.
Now, let's learn Ansible playbook through an example with one playbook with one play,
containing multiple tasks as below:
---
- hosts: group1
tasks:
- name: Install lldpad package
yum:
name: lldpad
state: latest
- name: check lldpad service status
service:
name: lldpad
state: started
In the above Ansible playbook example, the group1 of hosts in the host's file is targeted for
lldpad package installation using the yum module and afterward the service lldpad created after
the installation is then started using the service module used mostly to interact with systemd
ensemble.
Explanation:
Each ansible playbook works with an inventory file. The inventory file contains a list of servers
divided into groups for better control for details like IP Address and SSH port for each host.
The inventory file you can use for this Ansible playbook example looks like below. There are
two groups, named group1 and group2 each containing host1 and host2 respectively.
[group1]
host1 ansible_host=192.168.100.2 ansible_ssh_port=22
[group2]
host2 ansible_host=192.168.100.3 ansible_ssh_port=22
Explanation:
1. Group name
2. Hostname, with IP address and ssh port, in this case, the default one, 22.
Another useful Ansible playbook example containing this time two plays for two hosts is the
next one. For the first group of hosts, group1, selinux will be enabled. If it is enabled, then a
message will appear on the screen of the host.
For the second group of hosts, httpd package will be installed only if the ansible_os_family is
RedHat and ansible_system_vendor is HP.
---
- hosts: group1
tasks:
- name: Enable SELinux
selinux:
state: enabled
when: ansible_os_family == 'Debian'
register: enable_selinux
- debug:
Imsg: "Selinux Enabled. Please restart the server to apply changes."
when: enable_selinux.changed == true
- hosts: group2
tasks:
- name: Install apache
yum:
name: httpd
state: present
when: ansible_system_vendor == 'HP' and ansible_os_family == 'RedHat'
Explanation:
1. Example of the when clause, In this case, when OS type is Debian. The ansible_os_family
variable is gathered via gather_facts functionality.
2. The task output is registered for future use, with its name enable_selinux
3. Another example of the when clause. In this case, a message will be displayed for the host user
if the SELinux was indeed enabled before.
4. Another example of the when clause consisting of two rules
Besides tasks, there are also some particular tasks called handlers. Handlers must have a unique
name throughout the playbook. These work in the same way as a regular task but a handler can
be notified via a notifier.
If a handler is not notified during the run of the playbook, it will not run. However, if more than
one task notifies a handler, this will run only once after all the tasks are finished.
In the example shown below, you can see how a specific task has a notify section which calls
upon another task. If the output of the first task is changed, then a handler task will be called.
The best example is to have a configuration file changed and afterward restart that specific
service.
---
- hosts: group2
tasks:
- name: sshd config file modify port
lineinfile:
path: /etc/ssh/sshd_config
regexp: 'Port 28675'
line: '#Port 22'
notify:
- restart sshd
handlers
- name: restart sshd
service: sshd
name: sshd
state: restarted
In this case, if the first task, "sshd config file modify port" is changed, meaning that if the port is
not 28675 in the first place, then it will be modified and the task will notify the handler with the
same name to run, and it will restart the sshd service.
Explanation:
1. Example of a notifier
2. Example of a handler
Ansible Roles
When dealing with extensive playbooks, it is easier to split the tasks into roles. This also helps in
reusing the roles in the future. Roles are a collection of tasks, which can be moved from one
playbook to another, can be run independently but only through a playbook file.
Roles are stored in separate directories and have a particular directory structure.
[root@ansible-server test2]# tree
.
`-- role1
|-- defaults
| `-- main.yml
|-- handlers
| `-- main.yml
|-- meta
| `-- main.yml
|-- README.md
|-- tasks
| `-- main.yml
|-- tests
| |-- inventory
| `-- test.yml
`-- vars
`-- main.yml
7 directories, 8 files
The yaml file in the defaults directory contains a list of default variables that are to be used along
with the playbook. The handlers directory is used to store handlers. The meta-directory is
supposed to have information about the author and role dependencies. In the tasks directory,
there is the main yaml file for the role.
The tests directory contains a sample yaml playbook file and a sample inventory file and is
mostly used for testing purposes before creating the actual role.
The vars directory contains the yaml file in which all the variables used by the role will be
defined. The directory templates and the directory files should contain files and templates that
will be used by the tasks in the role.
To create the directory tree for a role, you should use the following command with the last
parameter, the role name:
Ansible also works well with templates. As a language for templating, it uses Jinja2.
In the next example, you will find out how a basic jinja2 template looks like and use it in a role.
At the run time, depending on, let's say in which datacenter your server is located, you can select
from more than one nameservers, each corresponding to a datacenter, using the variable
"resolver_ip_addresses."
{% for resolver in resolver_ip_addresses %}
nameserver {{ resolver }}
{% endfor %}
options timeout:1
options attempts:5
options rotate
In this example, in the playbook directory, there are defined some variables, including a variable
named resolver_ip_addresses with different values depending on the datacenter.
Explanation:
1. Name of the template to be used. Template is located in templates dir in the role path
2. Destination path of the filename to be replaced with the template, on the client-side.
3. Permissions of the destination file
The roles tasks can also have a tag field, which has a name attributed. More than one task can
share the same tag. When running an ansible playbook, you can specify the tag as well, so those
tasks will be executed.
Below is the directory structure of the playbook. The Yaml file that will be used will be p4.yml.
The playbook has three roles, one called resolver that sets a specific nameserver on the servers
by copying a file from the server to the /etc/resolv.conf destination. Another one is called httpd,
and it installs the httpd package with yum module, and the third one enables SELinux and
notifies the logged user to reboot the system. Each role was created using ansible-galaxy
command.
---
- hosts: all
user: root
port: 22
gather_facts: True
roles:
- { role: selinux, tags: selinux }
- { role: httpd, tags: httpd }
- { role: resolver, tags: resolver }
Running the p4.yml playbook on two hosts and interpreting the output. The same command can
be run with the –check parameter for a dry-run. In case you want to use password authentication,
use -k parameter.
Explanation:
Issue a ping command on all servers defined in the inventory file named hosts