Ansible 101 - a newbie guide to Ansible - part 1/2
Table of Contents
What is Ansible?
Ansible is an open source CLI automation software developped by Michael DeHaan (the author of the provisioning server application Cobbler and co-author of the Fedora Unified Network Controller (Func) framework for remote administration.)
Michael created Func and Ansible trying to solve the issue as shown below
Ansible is one of most popular DevOps tools created with Python to help in the orchestration, automation, configuration, and management of IT infrastructure. StackShare lists more than 1,000 companies that use Ansible, including Intel, Evernote, and Hootsuite, NASA, AkumenIA and more. Ansible has Ansible Galaxy, an online community for finding, sharing and re-using Ansible automation content.
There are tools such as Ansible in the market like Chef and Puppet. But when it comes to ease of setup and installation, Ansible dominates the other two, as it has an 'agentless' architecture, Unlike Chef and Puppet which follow master-agent or master-slave architecture.
Ansible Use cases
Ansible can be used in many scenarios like configuring systems, deploying software, and orchestrating advanced workflows to support application deployment, system updates, and more. Ansible's main strengths are simplicity and ease of use that's why you can almost adapt it for many automation scenarios.
SSH Authentiction with keys
Unlike many other tools Ansible doesn't need anything to be installed on target machine, all it needs is SSH connection from the control machine to the target machine and it will do its magic. When talking about SSH, it's essential to clarify some ideas, SSH which stands for Secure SHell, came as a better alternative to authenticate to SFTP servers, instead of username password method. A funny information is that the Elon Muscles (popular) password in 2017 was "123456" lol. According to a study done by Beyond Identity Gen Zers ranked as the worst in having a password for the longest time, as 40% said their oldest password was between 6-10 years old. The older generations’ percentages in that category were much lower, with Boomers at 13.7%, Gen X at 18%, and Millennials at 22.3%. And with machines getting more powerful it will became a matter of time to brute force passwords in short times. Using SSH key authentication method can be a bit more complex, but it increases security when loggin to SFTP servers. The way SSH keys work is
(1) you generate a pair of keys (public and private) which cryptographic keys on the control machine / SSH client
(2) the public key should be stored on the target machine
(3) when trying to log into the target machine, the target checks for public key existence, and it generates a random encrypted string with that key, this latest can only be decrypted with the associated privated key.
(4) Upon receiving the encrypted message from the target, the SSH client will try to decrypt that message using the private key and send it back to the target, if it matches up server negotiates parameters and open a secure chanel for the client to log in to the server.
Ansible Setup
The control machine can be a linux machine, and if it is Windows you can install WSL to proceed, you can install Ansible either by:
(1) a package manager (apt, yum, brew...)
sudo apt install ansible -y
or with:
(2) python using pip (btw did you know know that pip is an abbreviation for preferred installer program)
python3 -m pip install --user ansible
after installing Ansible, we need to setup SSH in the target machine. By running the following commands:
sudo apt install openssh-server
sudo ufw allow ssh
systemctl status ssh
you will install an SSH server, enable application profile on UFW firewall (UFW is a cool program, I will write a blog on it in the near future), then check ssh state (which should be active).
Also, let's create a user named Ansible with its password on the target machine using the following
useradd -m -s /bin/bash ansible
passwd ansible
generate public and private key on the control machine
ssh-keygen
this command will prompts you to enter some information, among them is the /path/to/key
then copy the public key to the target using
ssh-copy-id -i /path/to/key ansible@target-machine
on the target machine, add ansible
user to sudoers group as it will need elivated privileges to install software and run superuser commands
sudo su
echo -e 'ansible\tALL=(ALL:ALL)\tNOPASSWD:\tALL' > /etc/sudoers.d/ansible
the e flag of echo command is to enable interpreting backslash escapes.
All set now, you can check SSH authentication validity with
ssh -i /path/to/key ansible@host
HOORAY ansible is set up.
Ansible inventory
We need to test if everything works as expected, in order to do that we need to run some command on the target machine, we do this by informing ansible with target machines information, and such information are stored in what is called an inventory
file, by default if you didn't add a custom inventory, Ansible will use a default inventory stored in /etc/ansible/hosts, an inventory syntax looks like the following
SERVER_NAME ansible_host=IP ansible_private_key_file=FILE_PATH ansible_ssh_user=USER
__same_as_line_above__ ansible_ssh_port=PORT
in inventory you specify information such as ansible_host which should be either a dns name or ip address, ansible_private_key_file which points to the path of the private key to authenticate the user with against the target, some parameters have default values such as ansible_ssh_port which is by default 22. Declared variable in each line are meant to be assigned to the host of that line
Now we can test ansible connection with the ping module:
ansible -i inventory name_for_server -m ping
should return SUCCESS pong
response, it's like a
In order to not specify each time the inventory to use with the i
flag, we can create ansible.cfg
file which points to default inventory to use:
[defaults]
INVENTORY = ./inventory
Now we can ping with:
ansible -m ping
which will run ping againt all hosts specified in the inventory.
Other parameters that you can use in the inventory file are:
- ansible_connection: by default ansible will try to use SSH, use this flag to indicate other connection methods such as winrm.
- ansible_port: the port to which the connection establishes, by default 22
- ansible_user: the default ssh user name to use.
- ansible_ssh_pass: User password, for security reasons try to use tools such as hashicorp vault.
Sometimes you need to run the same commands on a group of servers, and run other commands on other servers, maybe database servers and web servers. what you can do is creating groups of servers as below:
[webservers]
server1 ansible_host=23.0.2.9
server2 ansible_host=23.0.2.10
[dbservers]
server3 ansible_host=23.0.2.11
server4 ansible_host=23.0.2.12
if some groups share some variables values you can pass them to those groups as follows:
[webservers]
webserver1 ansible_host=23.0.2.9
webserver2 ansible_host=23.0.2.10
[dbservers]
dbserver1 ansible_host=23.0.2.11
dbserver2 ansible_host=23.0.2.12
[webservers:vars]
ansible_user=user1
[dbservers:vars]
ansible_user=user2
when running an adhoc (a command which can be run individually to perform quick functions) or a module (we will see this in the next blog), you can target one host, a group of hosts or all machines in the inventory, this is done using patterns:
ansible PATTERN -m MODULE_NAME -a "MODULE_OPTIONS"
example to only target dbservers group:
ansible dbservers -m service -a "name=mysqld enabled=yes state=started"
let's imagine a scenario where we have prod and development servers, and we need to run specific commands on development but not on prod, we can adjust our inventory to indicate this with:
[webservers]
webserver1 ansible_host=23.0.2.9
webserver2 ansible_host=23.0.2.10
[dbservers]
dbserver1 ansible_host=23.0.2.11
dbserver2 ansible_host=23.0.2.12
[development]
webserver1
dbserver1
[production]
webserver2
dbserver2
so now using the pattern below the command will be applied on the dev servers:
ansible dbservers:\&development -m ping
or:
ansible dbservers:\!production -m ping
here's a table about the different patterns:
pattern | result |
---|---|
all | all hosts in the inventory |
host1 | a single host (host1) |
host1:host2 | host1 and host2 |
group1 | only group1 |
group1:group2 | hosts of group1 and group2 |
group1:\&group2 | servers that are both in group1 and group2 |
group1:\!group2 | servers in group1 with those in group2 excluded |
Ansible Playbook
In Ansible, Playbooks are config files written in yaml syntax, they are the orchestration language of Ansible, it's in them we define what we want the tool to do aka plays, and a play is a set of taks/activities.
The executions of playbooks can either run synchronously or asynchronously, to elaborate, the plays run in order from top to bottom, and when different plays should be running on different hosts, ansible will orchestrate multi-machine deployments.
A simple play will define at least two things:
- The target hosts (using a pattern)
- Tasks to execute
Here's a simple playbook.yaml
to update PostgreSQL servers
YAML- name: Update pgsql servers hosts: dbservers remote_user: root tasks: - name: psql shouls be at the latest version ansible.builtin.yum: name: postgresql state: latest - name: postgresql should be started ansible.builtin.service: name: postgresql state: started
remote_user
is the user account the SSH connection. to run the above playbook we will use the ansible-playbook
command as follow:
BASHansible-playbook playbook.yml
ansible-playbook
accepts some flags such as --forks
which specify number of parallel processes to use by default it's 5, and --verbose
which gives you more detailed information about tasks execution.
Before running playbooks it is always good to lint your files to avoid bugs white the execution, you can achieve such thing using the ansible-lint
CLI command:
ansible-lint playbook.yml
ansible.builtin.service
and ansible.builtin.yum
we used the playbook are called Modules, which are pieces of code that can apply changes to the system, run commands, edit files, manage databases, provision cloud, and more…
you can check available modules by visiting Ansible "All Modules" page, our check them out using ansible-doc
CLI command as follow:
ansible-doc –list
to learn more about a specific module, use:
ansible-doc module_name
which will give you a detailed description about the module, along with examples on how to use it.
Until here this blog ends, we will see in the next one: more on modules, variables, jina2 template, tasks delegation, some advanced topics, and more...