Stepping outside of my configuration management comfort zone and will be using Ansible in my lab!

Ansible is a python based configuration management tool similar to Salt, Puppet, and Chef. It utilizes SSH to interact with the hosts it controls. With that said, controlled hosts or targets will need to have SSH enabled and a specific user for Ansible to utilize.

For this tutorial, I will be using a CentOS 8 virtual machine as the Ansible server and Debian 10 as the target.

The ansible server will also be referred to as the control node.

---------------------------------
| Ansible server | 192.168.1.18 |
---------------------------------
| Target         | 192.168.1.19 |
---------------------------------

Setting up

I'll be creating the ansible user and will give it sudo rights on both the ansible server and target.

  1. Creating the ansible user
adduser ansibleadmin

2. Give ansible user sudo rights

usermod -aG sudo ansibleadmin

3. Create SSH keys

Ansible uses SSH to connect to the controlled instances, but it's not feasible to supply the password to each hosts when executing a playbook. To handle authentication, I'll create SSH key pair (private and public).

ssh-keygen -t rsa -b 4096

Do not put a password on the key.

4. Copy the public key to the target hosts

ssh-copy-id ansibleadmin@192.168.1.19

5. Verify access

If you added the key correctly, you should be automatically connected to the target.

ssh ansibleadmin@192.168.1.18

Installing Ansible

  1. Install Python3
dnf install python3 -y

2. Install ansible

dnf install ansible -y

3. Verify if ansible installed properly

Execute the command below:

ansible --version

Configuring the Ansible Control Node

  1. Edit the ansible hosts file and add your hosts. I'll be managing the control node and target using ansible.
vim /etc/ansible/hosts
[control]
192.168.1.18

[targets]
192.168.1.19

2. Verify ansible can access the hosts

After you're done adding the IP addresses of the control node and target, I'll verify ansible can reach them.

ansible -m ping all

You should get an output like this:

192.168.1.18 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.168.1.19 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Creating a Playbook

  1. Create a directory specifically for the playbooks
mkdir /etc/ansible/playbooks

2. Create an empty file for a playbook

This empty file will be the playbook that will install mysql on the target

touch /etc/ansible/playbooks/mysql.yml

3. Writing the mysql playbook

vim /etc/ansible/playbooks/mysql.yml

After opening mysql.yml, write the following:

---
- hosts: target
  become: true
  tasks:
    - name: Installing MySQL
        dnf: 
          name: mysql-server
          state: latest
          update_cache: yes
          
    - name: Starting MySQL server
      service:
        name: mysqld
        state: started
        enabled: yes

hosts = Which hosts ansible should target, in this case hosts under the target section in the ansible hosts file will be used.

become = Allows ansible to use the sudo command.

tasks = The actions ansible should take on the targets hosts.

- name = The name of the task.

dnf = Is the built it module ansible will use. In the example ansible will use dnf to download packages.

state = The version of the package, in this case it will be the latest version.

update_cache = Will execute dnf update.

service = Is another module within ansible that can interact with services on the target system. This will start a service on the target host.

enabled = Enables the service to always start after a reboot.


Executing the Playbook

  1. Execute syntax check

Before executing the playbook for real, I'm going to do two checks. The first one will be the syntax check.

ansible-playbook --syntax-check mysql.yml

If there are no syntax errors, it will return the playbook's name, like below.

playbook: mysql.yml

If there is an error, it will tell you on which line and column your mistake is on.

2. Check what will be changed on the target

ansible-playbook --check mysql.yml

This command will go and connect to the host and look at the gathered facts and will generate a preview of what will be changed on the target.

3. Execute the  playbook

Now that the checks have shown me what is going to happen, I'm satisfied to execute the playbook.

ansible-playbook mysql.yml 

You will get an output similar to this:

PLAY [database] ***************************************************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************************************************
ok: [192.168.1.19]

TASK [Installing MySQL server] **************************************************************************************************************************************************************************
changed: [192.168.1.19]

TASK [Starting MySQL server] **************************************************************************************************************************************************************************
changed: [192.168.1.19]

PLAY RECAP ********************************************************************************************************************************************************************************************
192.168.1.18     : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Conclusion

See ansible is quite simple isn't it? Well it's just the tip of the iceberg, now I can incorporate ansible into my CI/CD pipeline or use it to manage my infrastructure. Ansible makes it easy to control my fleet of virtual machines. As my infrastructure scales management becomes easier.