Install and Setup Ansible on Ubuntu 20.04

0
147

In this tutorial, we are going to learn how to install and setup Ansible on Ubuntu 20.04. Ansible is a simple agentless IT automation tool. It handles configuration management, application deployment, cloud provisioning, ad-hoc task execution, network automation, and multi-node orchestration over the SSH protocol. Ansible makes complex changes like zero-downtime rolling updates with load balancers easy.

Install and Setup Ansible on Ubuntu 20.04

Since Ansible is used to manage remote hosts via SSH protocol, the node on which you install Ansible, in this case, Ubuntu 20.04 system, becomes the control node.

Run System Update

Before you can proceed, ensure that your system package cache is up-to-date;

sudo apt update

Install Ansible on Ubuntu 20.04

Ubuntu 20.04 default repos contain the latest stable release version of Ansible.

sudo apt-cache policy ansible
ansible:
  Installed: (none)
  Candidate: 2.9.6+dfsg-1
  Version table:
     2.9.6+dfsg-1 500
        500 http://ke.archive.ubuntu.com/ubuntu focal/universe amd64 Packages
        500 http://ke.archive.ubuntu.com/ubuntu focal/universe i386 Package

Therefore, you can simply install ansible by executing the command below;

sudo apt install ansible

Once the installation is done, you can check the version of install Ansible as follows;

ansible --version
ansible 2.9.6
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/koromicha/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.8.2 (default, Apr 27 2020, 15:53:34) [GCC 9.3.0]

Setting up Ansible on Ubuntu 20.04 Control Node

Now that Ansible is installed on an Ubuntu 20.04 control node, it is time to set it up to enable you automate deployment of your tasks on the remote hosts via SSH protocol.

Setup Ansible Inventory

An Ansible inventory is a file that list or defines the hosts to be managed via Ansible. /etc/ansible/hosts is the default Ansible inventory file. It is also possible to define a custom file as your Ansible inventory file. When you use a non-default inventory file, you have to specify the path to it with -i <path> option while running ansible.

An inventory file can also be used to store variable values that relate to a specific host or group in inventory.

In the inventory file:

  • you can specify the details of the hosts using resolvable hostnames or IP addresses,
  • A group of hosts are delimited by [header] elements
  • A hostname/IP address can be a member of multiple groups

See examples below to create a hosts file with ungrouped hosts, grouped hosts and a range of hosts.

In this tutorial, I will create my inventory in my home directory.

mkdir $HOME/ansible
vim $HOME/ansible/hosts

NOTE: Any individual host, (Ungrouped hosts),should be specified before any group headers.

# Ungrouped list of hosts
server01.kifarunix-demo.com
192.168.58.5

# Range of hosts
192.168.56.[111:112]

[webapps]
app[01:04].kifarunix-demo.com

# Grouped Hosts
[database]
db[01:03].kifarunix-demo.com
db05.kifarunix-demo.com
db07.kifarunix-demo.com

Save and exit the file.

You can list the hosts in your inventory using the ansible-inventory command. For example, to display the contents of our hosts list above in YAML format;

ansible-inventory -i $HOME/ansible/hosts --list -y
all:
  children:
    database:
      hosts:
        db01.kifarunix-demo.com: {}
        db02.kifarunix-demo.com: {}
        db03.kifarunix-demo.com: {}
        db05.kifarunix-demo.com: {}
        db07.kifarunix-demo.com: {}
    ungrouped:
      hosts:
        192.168.56.111: {}
        192.168.56.112: {}
        192.168.58.5: {}
        server01.kifarunix-demo.com: {}
    webapps:
      hosts:
        app01.kifarunix-demo.com: {}
        app02.kifarunix-demo.com: {}
        app03.kifarunix-demo.com: {}
        app04.kifarunix-demo.com: {

Read more on how to build ansible inventory.

Setting up Ansible SSH key authentication

Generate SSH Keys

Use of passwordless SSH key authentication is one of the common methods that by default Ansible uses for managing remote hosts. Therefore, you need to generate passwordless SSH key and copy the keys to the remote hosts your want to manage with Ansible.

ssh-keygen

For passwordless SSH key generation, simply press ENTER for empty password.

Generating public/private rsa key pair.
Enter file in which to save the key (/home/koromicha/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/koromicha/.ssh/id_rsa
Your public key has been saved in /home/koromicha/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:Ba9LyP0epsCPIVN5nvIVT9zgnLCRL1P/dmgiAvWjbMc [email protected]
The key's randomart image is:
+---[RSA 3072]----+
|        .        |
|         o .     |
|        . * o    |
|     . = + X =   |
|      * S B B o  |
|     o * * B   o |
|    o = O E o o +|
|     o O B o o ..|
|      . + .      |
+----[SHA256]-----+

Read more about other connection methods on Ansible connection plugins page.

Copy the keys to remote hosts

Next, copy the keys to the remote hosts. Use a remote user with sudo rights.

for i in 192.168.58.5 192.168.56.111 192.168.56.112; do ssh-copy-id -o StrictHostKeyChecking=no [email protected]$i; done

In this demo, we will be using a user with passwordless sudo rights. To enable a user to run commands with sudo without being prompted for password, run the command below on the remote hosts being managed.

echo "johndoe ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/johndoe

Read more on Ansible privileges escalation page.

Test Ansible Connection to Remote Hosts

Ansible uses ping module to verify the reachability to the remote hosts defined on the inventory file. Below is our test inventory;

ansible-inventory -i $HOME/ansible/demo --list -y
all:
  children:
    centos:
      hosts:
        192.168.56.111: {}
        192.168.56.112: {}
    ungrouped: {}

To test the connection, as user johndoe, whose keys we copied above;

ansible -i $HOME/ansible/demo -m ping -u johndoe all
192.168.56.111 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
192.168.56.112 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

Both 192.168.56.111 and 192.168.56.112 are CentOS 8 servers.

Running Ansible ad-hoc commands

If you have tasks that you would rarely repeat, ad-hoc commands come in so handy. With ad-hoc commands, you can manage user accounts, services, packages, run ad-hoc system commands like check free RAM, gather system facts.

To see a few examples, check if the remote systems have internet connectivity using ping command;

 ansible -i $HOME/ansible/demo -a "ping 8.8.8.8 -c 3" all -u johndoe

To check free memory;

ansible -i $HOME/ansible/demo -a "free -h" all -u johndoe
192.168.56.112 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:          818Mi       234Mi       196Mi        10Mi       387Mi       444Mi
Swap:         819Mi          0B       819Mi
192.168.56.111 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:          818Mi       230Mi       214Mi        10Mi       373Mi       452Mi
Swap:         819Mi          0B       819Mi

To install a package, for example a vim editor, as user johndoe with sudo rights (--become);

ansible -i $HOME/ansible/demo -m apt -m yum -a "name=vim state=present" all -u johndoe --become

Read more about ad-hoc commands on Introduction to ad-hoc commands.

Using Ansible Playbooks

Playbooks are Ansible’s configuration, deployment, and orchestration language. They define roles and tasks (a set of steps to take to set up a specific process) to be executed on the remote hosts.

In this demo, we will cover two simple examples of playbooks;

So before we can proceed, create Ansible roles directory. Ansible Roles defines a collections of variables, tasks, files, templates and any other ansible artefacts.

For our example, we will have two roles, useraccount and apache, for defining what user account to create and the package to be installed.

Below is our simple sample Roles directory structure;

myplaybooks
	site.yml
	roles/
	     useraccounts
		tasks/
                     main.yml
	     webserver/
		tasks/
                     main.yml

To create the relevant directories as per above structure;

mkdir -p myplaybooks/roles/{useraccounts/tasks,webserver/tasks}

Create master playbook, site.yml to define values that will be applicable to all other tasks;

vim myplaybooks/site.yml
---
#
# A common Playbook to Create a user accounts.
#
- hosts: all 
  remote_user: johndoe
  become: yes
  roles:
  - { role: useraccounts }
  - { role: webserver }

Ansible Playbook to Create User Account

The playbook for creating user account is as per my roles directory structure above. So create a file in which you will define particulars of a user to be created.

vim myplaybooks/roles/useraccounts/tasks/main.yml
---
#
# Create a user account
#
- name: Add User Jane Doe to the system
  user:
          name: janedoe
          password: "{{ 'strongpassword' | password_hash('sha512') }}"
          groups: wheel
          shell: /bin/bash
          comment: Jane Doe
          expires: 1584993090

Ansible Playbook to Install Apache Web server

Similarly, create task file for installing Apache web server on Ubuntu 20.04 and CentOS 8 systems;

vim myplaybooks/roles/webserver/tasks/main.yml
---
#
# Install Apache Web server on CentOS 8
#
- name: Install Apache on CentOS 8
  yum:
          name: httpd
          update_cache: yes
          state: latest

To list master Ansible Playbook tasks;

ansible-playbook myplaybooks/site.yml --list-tasks -i demo
playbook: myplaybooks/site.yml

  play #1 (all): all	TAGS: []
    tasks:
      useraccounts : Add User Jane Doe to the system	TAGS: []
      webserver : Install Apache on CentOS 8	TAGS: []

Running Ansible Playbook Dry Run checks

To check your playbook without making any changes on the remote host, use the --check option.

ansible-playbook myplaybooks/site.yml --check -i $HOME/ansible/demo
PLAY [all] *****************************************************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************************************************
ok: [192.168.56.112]
ok: [192.168.56.111]

TASK [useraccounts : Add User Jane Doe to the system] **********************************************************************************************************************
changed: [192.168.56.112]
changed: [192.168.56.111]

TASK [webserver : Install Apache on CentOS 8] ******************************************************************************************************************************
changed: [192.168.56.111]
changed: [192.168.56.112]

PLAY RECAP *****************************************************************************************************************************************************************
192.168.56.111             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.56.112             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Executing Ansible Playbook

Once you have verified that there is not error with the checks above, proceed to execute the playbook;

ansible-playbook myplaybooks/site.yml -i $HOME/ansible/demo
PLAY [all] *****************************************************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************************************************
ok: [192.168.56.112]
ok: [192.168.56.111]

TASK [useraccounts : Add User Jane Doe to the system] **********************************************************************************************************************
changed: [192.168.56.111]
changed: [192.168.56.112]

TASK [webserver : Install Apache on CentOS 8] ******************************************************************************************************************************
changed: [192.168.56.111]
changed: [192.168.56.112]

PLAY RECAP *****************************************************************************************************************************************************************
192.168.56.111             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.56.112             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

Verify User Account Creation and Package installed using Ansible

You can create yet another master playbook to verify if user account for janedoe is created as well as checking is Apache is installed by checking its service if available. Both of these can be checked using Ansible getent module.

vim myplaybooks/check.yml
---
- hosts: centos
  remote_user: johndoe
  become: yes
  gather_facts: no  # or it will fail on the setup step
  tasks:
          - name: Check if user Jane Doe (janedoe) is created.
            getent:
                  database: passwd
                  key: janedoe
          - name: Check if Apache service exists.
            getent:
                  database: services
                  key: http

Execute the playbook;

ansible-playbook myplaybooks/check.yml -i $HOME/ansible/demo
PLAY [centos] **************************************************************************************************************************************************************

TASK [Check if user Jane Doe (janedoe) is created.] ************************************************************************************************************************
ok: [192.168.56.112]
ok: [192.168.56.111]

TASK [Check if Apache service exists.] *************************************************************************************************************************************
ok: [192.168.56.112]
ok: [192.168.56.111]

PLAY RECAP *****************************************************************************************************************************************************************
192.168.56.111             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.56.112             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

And there you go.

That marks the end of our tutorial on how to install and setup Ansible on Ubuntu 20.04. We hope this was informative. Enjoy.

Further Reading

Getting Started with Ansible

Other Tutorials

Install and Deploy Kubernetes Cluster on Ubuntu 20.04

Install Docker CE on Ubuntu 20.04

Setup GlusterFS Distributed Replicated Volume on CentOS 8

LEAVE A REPLY

Please enter your comment!
Please enter your name here