Getting Started with Ansible
Tags: ansible, devops, automation, immutable
Published: 2021-01-22 09:54:22

> This post outlines details regarding Ansible an automation tool. It assumes that you have good understanding of Linux and concepts of DevOps.

# Configuration management

Configuration management refers to the task or process, in which we track and control changes to a managed systems, keeping integrity in place. Managed systems can include software, servers, infrastructure components, etc.

```Doubt: What will happen if we do not have CM?```
> Modern IT systems are often deployed in a large-scale manner including on cloud and on-premises using automation. Think about what will happen, if we can not keep track of configuration! Furthermore, it can lead to increased risk if we do it manually.

`Doubt: What is the Benefit of CM?`
> The primary benefit of configuration management is the consistency of managed systems. If we have an automated system in place to take care of CM, then you can sleep peacefully.

`Doubt: What are the Options?`
> Ansible, Chef, Puppet, etc.

`Configuration management and change management both are not similar.`



# Mutable vs Immutable Server Infrastructure

In mutable server infrastructure, systems receive continuous updates and patches, probably configuration also gets updated from time to time. In Immutable infrastructure, server configuration never gets change after they are deployed.

`Doubt: Immutable Infra does not receive patch or update ?`
> Immutable Infra also receives/follows the patch or deployment life cycle but instead of updating the server, we tend to rebuild it using the latest patch or configuration. We provision the new infra, replacing or decommissioning the existing one.

`Doubt: What’s the benefit, can't we patch the existing one ?`
> With Immutable infra, we achieve consistency, a faster automation cycle, and a smooth deployment process. If I have a word to select, I will go with DevOps!



# Idempotent Application

Idempotence is a concept borrowed from mathematics. It is the property in which you apply configuration changes on an item, the exact same result is produced each time, leaving the item in the same state. Now replace “item” with Server or Application! Idempotence is considered important when you are implementing DevOps.

`Doubt: How Idempotence is related with DevOps?`
DevOps is a fancy name, I consider it automation. In automation, you may have to validate or perform the same operation a number of times. If every time you perform the same operation and it starts giving different results, then bring a lot of coffee before coming to the office! You may need one. The idempotent behavior of an application handles this issue conveniently.

`Doubt: Give me one example.`

I need to create one configuration file to be available on the server with standard settings. Modern DevOps tools are able to automate the server build process and can keep consistency. In this scenario, if I use Ansible, then it can consistently ensure one configuration file gets created only if it does not already exist. If the file exists it will simply ignore. It seems simple but gets pretty complex in different scenarios.



# Introduction to Ansible
Ansible is an open-source automation tool primarily used for software provisioning, configuration management, and application deployment. It enables you to achieve infrastructure as code. Ansible uses SSH and WinRM to deploy applications and systems consistently and repeatably. Ansible can help you to create/deploy immutable Infrastructure.

- Configuration management platform
- Agentless Architecture
- Ansible modules are idempotent.
- Can push changes parallelly on all machine
- Require Python
- Open-source tool

### Is Ansible free?
Ansible is an absolutely free and open-source tool that can be utilized for commercial purposes. Apart from Open Source Ansible, the Red Hat Ansible Automation Platform is also available in two editions that are differentiated by support and features. Pricing is based on the number of nodes. Ansible Tower offers free handling of up to 10 nodes.

### Red Hat® Ansible® Automation Platform
Red Hat Ansible Automation Platform integrates Red Hat’s automation suite consisting of Red Hat Ansible Tower, Red Hat Ansible Engine, and few other feature products to serve all enterprise automation needs.

There are few important concepts in Ansible, you should aware of:-
- `Modules` — Ansible uses modules to execute tasks. (Core and Custom)
- `Playbook` — playbooks in a file which is having a list of commands to execute on target servers.
- `Inventory File` — Defines a collection of hosts managed by Ansible (Static and Dynamic)
- `Ansible roles` - Roles provide a framework for fully independent, or interdependent collections of variables, tasks, files, templates, and modules.
- `Task` — Unit of work
- `APIs` — Ansible Tower’s REST API, provides the REST interface to the automation platform



# Architecture
In the Ansible ecosystem, there are two types of nodes available.


### Control Node

The control node is our master ansible server. All Ansible magic happens here. Please note, you can use a Windows machine as a control node.



### Management nodes

Management nodes are those machines that we are going to manage using Ansible. You do not have to install Ansible or additional software on the management nodes, that's why Ansible is referred to as agentless.

# How does Ansible connect to Management Nodes?

Ansible’s agent-less architecture leverage natively available communication services to connect hosts which you want to manage. Ansible uses the SSH protocol to communicate with Linux hosts and WinRM or Powershell with Windows hosts.
- Ansible gets the list of nodes from the inventory file.
- Ansible needs to know what user should be used to log in, if the user is not root then privilege escalation is required or not?
- Ansible supports password and passwordless authentication. In most of the scenarios, you will find SSH keys for authentication in use.

# Who populates the inventory file?
Ansible supports two kinds of inventory files, Static and Dynamic. As the name suggests Static inventory is populated by users manually and Dynamic inventories can populate themselves automatically. Dynamic inventory is useful in scenarios where hosts are added and removed frequently and automatically. Dynamic inventory uses plugins.
In the simplest form, the inventory file can be INI formatted and look like -

```sh
arun@ubuntu:~$ cat /etc/ansible/hosts
worker
worker-1
worker-2

```

Inventory file can utilize the concept of groups and subgroups. Please refer to the documentation for more details. The file can be formatted in YAML format as well.

# What is the purpose of Modules?
Ansible ships with a number of modules that can be executed directly on remote hosts or through playbooks. These modules stay in the modules library. Tasks in the playbook can invoke modules to do the work. Ansible modules are Idempotent, it means they only make changes if a change is needed. To list all available modules, please run the following command

```sh
$ ansible-doc -l
# to list specific module details 
$ ansible-doc ping
```

# Why we need Playbook?
You create a playbook to define a list of tasks. Playbooks are reusable. They are in YAML format and can be managed in the version control system. A play is a list of ordered tasks that run against inventory. `An alternative to playbook is ad-hoc commands.`
While creating a playbook please be careful with identation. Example Playbook -

```sh
# playbook-1.yml
- name: Create Test File
  hosts: all
  become: yes
  tasks:
    - name: Create a file in tmp location called '/tmp/file.txt' 
      copy:
        content: Hi This is playbook
        dest: /tmp/file.txt

```

How above playbook has been organized?

```sh
# playbook-1.yml
- name: <Name of Play>
  hosts: <Management Host>
  become: <privilege escalation>
  tasks:
    - name: <Name of task> 
      <module>:
         <arg-1>
         <arg-2>
```

You can validate the syntax as well before running.

```sh
$ ansible-playbook --syntax-check playbook-1.yml

```

To run this playbook

```sh
$ ansible-playbook playbook-1.yml
```

# Ansible Ad-Hoc Commands?

Ansible ad-hoc command uses the ansible command-line tool to automate a task on managed nodes. These tasks avoid using playbooks and use modules to perform any operation quickly on nodes.
e.g. ping all nodes

```sh
$ ansible all -m ping
# format of command
$ ansible [host-pattern]  -m [module] -a "[module options]" -i "[inventory]"

```

e.g. ensure service is started on all webservers:

```sh
$ ansible all -m ansible.builtin.service -a "name=httpd state=started"
```

# Ansible Configuration file

This Ansible file is a master configuration file where all settings and configuration resides. There are multiple sections in the configuration file. Each section has its own purpose. To find out what location is the file being referred to, run the following command

```sh
arun@ubuntu:~$ ansible --version
ansible 2.9.17
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/arun/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.17 (default, Sep 30 2020, 13:38:04) [GCC 7.5.0]

```
Ansible provides you flexibility in terms of the configuration file. Precedence as follows

- ANSIBLE_CONFIG (environment variable if set)
- ansible.cfg (in the current directory)
- ~/.ansible.cfg (in the home directory)
- /etc/ansible/ansible.cfg


# Demo Deployment

We are going to deploy an open-source version of Ansible for the demo.
In this demo we are going to use 1 node for Ansible Control node and we will manage 1 machine using this node. Both of the machines are Ubuntu 18.04.
- Control Node Name — Ubuntu
- Management Node Name — Worker

Let’s prepare the control node first. In this step, we are going to generate a key-pair for password-less authentication. Please note this is not mandatory, if you are okay to provide the password when Ansible run its playbook, you can avoid this step :-
```sh
arun@ubuntu:~$ ssh-keygen -t rsa
```

We will use ssh-copy-id to copy the keys to remote managed server and add it to authorized_keys.

```sh
arun@ubuntu:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub arun@worker
```
You should verify it, via ssh to server

```sh
# it should not ask password this time
arun@ubuntu:~$ ssh arun@worker
```
Ansible Installation will be performed using Package Manager. The steps are simple and pretty straight forward.

```sh
$ sudo apt-get -y update
$ sudo apt-get install -y software-properties-common
$ sudo apt-add-repository --yes --update ppa:ansible/ansible
$ sudo apt-get install -y ansible
# Once your installation is over, make sure you verify it using following command.
$ ansible --version
```

`Ansible version command is important, it will tell which configuration file is in use! In the default section on this file, you can find details about inventory.`

By Default all entries in configuration file are commented. The commented values which are mentioned in the file are default values. You can use this file for Ansible or you can create a copy out of it and configure it as per your requirement.


Open default inventory file and place management nodes entries in that.

```sh
$ vi /etc/ansible/hosts
```
You can verify inventory as well.

```sh
arun@ubuntu:~$ ansible-inventory -y --list
```

### How Ansible will connect to management nodes?
Settings used for connections are defined in the Ansible configuration file. By default, it uses root as user and port 22 for connection along with other variables.

```sh
remote_port = 22
remote_user = root
ask_pass = True 
# in case of key based authentication, you can connect directly
```
Apart from this, you can control privilege escalation settings as well.

` What is privilege escalation in Ansible?`
> Ansible uses existing privilege escalation systems to execute tasks on the management nodes. This feature allows you to ‘become’ another user, different from the user that logged into the machine (remote user)

` Why we need privilege escalation? `

> As we are aware, not all of the operations on Linux/Unix based systems can be run using generic users. You may need privileged users in most of the cases. Ansible uses privilege escalation to work this out. This setting is part of the configuration file.

```sh
[privilege_escalation]
#become=True
#become_method=sudo
#become_user=root
#become_ask_pass=False

```
After configuring the inventory and Configuration file, we are ready to use Ansible. Let’s perform a quick test using Ad-Hoc Command.

```sh 
$ sudo ansible all -m ping
# all is to refer all nodes mentioned in inventory

```

### Running a Sample Playbook

In this play, we are creating a user group on the management node.

```sh
- name: GROUP AND USER CREATE
  hosts: all
  become: yes
  become_method: sudo
  tasks:
   - name: Add group ansible to remote server
     group:
       name: ansible
       gid: 5001
       state: present

```

Let’s run this playbook

```sh
sudo ansible-playbook playbook-1.yml
```

Verify the change has been performed on the target machine

```sh
arun@worker:~$ cat /etc/group | grep ansible
ansible:x:5001:
```
That’s the way to run the playbook.
One very helpful command to list all changed variables in the config file

```sh
$ ansible-config dump --only-changed
```

# Ansible Variables
Ansible support variables that can be reusable in the project. Variables provide the way to handle dynamic values. Variables are scoped as well.
- `Global` — Set for all hosts
- `Host` — For particular host
- `Play` — Set for all but in the context of the play

Please refer to documentation for more details.

# Preparing Ansible Project

In a real-world scenario, there are multiple types of servers available in a deployment. You can manage the Ansible project differently in those cases. You can create your structure and utilize the concept of host_vars. `Any setting placed inside host_vars will override the settings in ansible.cfg`

```sh
arun@ubuntu:~/ansible/project-1$ tree
.
├── ansible.cfg
├── host_vars
│   ├── worker-1
│   ├── worker-2
│   └── worker-3
└── inventory
1 directory, 5 files
arun@ubuntu:~/ansible/project-1$ cat host_vars/worker-1
# Connection
ansible_host: 10.0.0.5
ansible_port: 22
ansible_user: arun

```

# Debug

Use -v flag to debug the connectivity

```sh
arun@ubuntu:~$ sudo ansible all -m ping -vvv
```
You can perform dry-run as well.

```sh
arun@ubuntu:~$ sudo ansible-playbook -C playbook-1.yml

```

That’s all for now. I will cover more advanced topics on Ansible in upcoming posts.
Keep Learning and Stay Safe and Secure :)

Ref to [Medium](https://arunksingh16.medium.com/getting-started-with-ansible-32ec730ee605) article with images :)