
Infrastructure as a code? What?
I decided to take a look at some common and most popular devops tools out there to see what kind of issue do they solve (besides Docker, because i'm currently familiar with that).
After some research, i found that Ansible is a pretty good starting point in this journey.
Ansible is an open-source automation engine used for IT tasks such as configuration management, application deployment. It simplifies infrastructure management by allowing admins to describe their desired state and execute them on one or multiple machines. This concept is actually called infrastructure as code. The idea is, besides your actual software that you want to deploy, you should also write your desired infrastructure state as a code. So it can automatically and (quite) easily created again from ground up. In general, when you are taking some kind of devops responsibility, you basically try to automate every process like this as you can.
Ansible is actually fairly easy to work with. I found it pretty intuitive and easy to pick up and use.
First let's see what are some essential concepts we need to know in order to use Ansible:
An Ansible inventory is a collection of managed hosts that Ansible targets for automation and configuration management tasks. It defines the "who" of your automation. Listing the servers, network devices, or other systems that Ansible will interact with are defined here.
Example:
[homelab]
10.0.0.30 ansible_port=2222
10.0.0.31 ansible_port=2222
10.0.0.32 ansible_port=2222
[cloud]
188.65.100.54 ansible_port=22
Here i define remote machines that i want to use as a target of my ansible tasks. As you can see, we can separate them by grouping. We can these aliases later.
Also i define the ansible_port variable for them. ansible_port is actually a special variable that ansible uses by default for initiating the ssh connection to remote.
A playbook is a collection of tasks that you use to confugure remote servers. And it's utilizes YAML file format for defining a playbook logic.
Example:
---
- name: Intro to Ansible Playbooks
hosts: homelab # here you can specify remote machines by their alias, or pointing to all of them using "all" keyword
become: yes
become_method: sudo
remote_user: ubuntu
tasks:
- name: Copy file hosts with permissions
ansible.builtin.copy:
src: ./hosts
dest: /tmp/hosts_backup
mode: '0644'
- name: Add the user 'bob'
ansible.builtin.user:
name: bob
- name: Upgrade all apt packages
apt:
force_apt_get: yes
upgrade: dist
become: yes
We can break up the playbook into different sections. Let's start with the header. In the header you set things like the name of the playbook, the hosts to specify targets, the remote_user and become and become_method for configuring the privilege escelation method.
Visit the Ansible documentation. because explaining all of the options here is pointless.
These header fields are mostly boilerplate so let's get familiar with them really fast:
all as a hosts for applying to all of them.become. Essentially, it determines how you become another user with elevated privileges, such as sudo, su, or others.The next section tasks is where you list and define all of your tasks that you want to be performed. think of it as an instruction manual that is exectued one by one.
- name: Copy file hosts with permissions
ansible.builtin.copy:
src: ./hosts
dest: /tmp/hosts_backup
mode: '0644'
copy (docs).You should try to create tasks to be as idempotent as possible. Ansible modules are also designed with this principle in mind. Idempotent means You can run the same task multiple times, and the result will always be the same — without causing unintended side effects. And actually this may be tricky for tasks like "changing the default ssh listening port" and etc.
After installing ansible, run the playbook by using the command below :
ansible-playbook -i inventory.ini my-playbook.yaml
Here, -i stands for inventory. And as a first parameter, you simply pass the playbook that you wrote.
By default, Ansible prints a human-readable summary of play and task execution, including task names, host names, and status indicators (e.g., changed, ok, failed, skipped). For example the status ok means there is nothing to do usually because the desired state is currently exists! (Idempotence)
In the next post, we will write some powerful and useful playbooks aimed at hardening our hosts.