---
# System prepended metadata

title: 7. Configuration Management using Ansible

---

# 7. Configuration Management using Ansible


[toc]

### Topics
:::warning
- [ ] Introduction to Configuration Management
- [ ] Introduction to Ansible
- [ ] Installation and Configuration
- [ ] Ansible Inventory
- [ ] Ansible Ad-hoc commands
- [ ] Ansible Playbooks
- [ ] Ansible Roles
:::

### Keywords
:::success
- Configuration Management
- Desired State Configuration (DSC)
- idempotence
- Domain Specific Language (DSL)
- Declarative (Chef DSL, YAML, HCL)(What do you need) vs Imperative Languages (Java, C, Python) (What as well as How)
- Agent-based (Pull-based)
- Agentless (Push-based)
:::

### Introduction to Configuration Management

#### Why CM / Automation
:::warning
- Reduce Human errors
- Increase Consistency
- Reduce time and effort
- Reuseability
- Improve productivity
- Ease of Maintenance
:::

#### Popular CM Tools
:::warning
**On-prem**
- Ansible
- Chef
- Puppet
- SaltStack
- CFEngine
- Powershell DSC

**Cloud-based**
- AWS OpsWorks
- AWS Systems Manager
:::


#### IaC vs Config Management
:::warning
- Infrastructure-as-Code --> (Provisioning of the Infrastructure)
    - Terraform
    - AWS CloudFormation
    - Azure ARM templates

- Configuration Management --> (Management and maintenance of the State of the Infrastructure)
    - Chef
    - Ansible
    - Puppet
:::

### Introduction to Ansible

#### Benefits / Features of Ansible
:::warning
- Lower learning curve
- Playbooks are written in YAML
- Works on SSH (no need to open a special port)
- Agentless (Push based)
- Written in Python
:::

#### Ansible Architecture
![AnsibleArchitecture](https://i.imgur.com/NBgAvlC.png)



#### Ansible Terminologies
:::warning
- Ansible Controller
- Ansible Modules
- Ansible Playbooks
- Ansible Tasks
- Ansible Roles
:::

#### Ansible CLI
:::warning
ansible --> Ad-hoc commands
ansible-playbook --> command line tool to work with Ansible Playbooks
ansible-doc --> to check the documentation (similar to man pages)
ansible-inventory --> to check and work with your hosts and host groups
ansible-galaxy --> to work with Ansible roles
:::

### Installation and Configuration

#### Step 1: Ansible Installation (On Controller Node)
````go=1
sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible

**Validation**
ansible --version
````
#### Step 2a: Setup password-less authentication for localhost (Simplilearn Lab)
````yaml=1
cd ~
ssh-keygen -t rsa  ## Press Enter when asked for File and Paraphrase details
cat .ssh/id_rsa.pub >> .ssh/authorized_keys
Validation:
ssh localhost -p 42006

Expected result:
Above ssh command should take you directly to the target node without the need to put in the password.
````

#### Step 2b: Setup password-less authentication for localhost (DigitalOcean Lab)
````yaml=1
cd ~
ssh-keygen -t rsa  ## Press Enter when asked for File and Paraphrase details
cat .ssh/id_rsa.pub >> .ssh/authorized_keys

Validation:
ssh localhost

Expected result:
Above ssh command should take you directly to the target node without the need to put in the password.
````
#### Step3: Validate Ansible configuration
````yaml=
ansible localhost -m ping
or
ansible -m ping localhost

Expected output:

localhost | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
````

### Working with Ansible Inventory
:::warning
Edit the default Ansible inventory file as follows:
````yaml
sudo vi /etc/ansible/hosts
````
**On simplilearn lab**
````yaml
[nodes]
localhost:42006

[webservers]
localhost:42006
````

**On digitalocean lab**
````yaml
[nodes]
localhost

[webservers]
localhost
````
**Save the file**
````yaml
esc + :wq!
````

**Validate the configuration**
````yaml
ansible -m ping all
or
ansible -m ping nodes
or 
ansible -m ping webservers
````
:::

### Ansible Ad-hoc commands
````yaml=
Syntax:
ansible <inventory-host-group> -m <modulename> -a <arguments> --<additionalparameters>

Examples:
ansible all -m ping
ansible --list-hosts all
ansible --list-hosts <groupname>
ansible all -m shell -a 'hostname'
ansible all -m shell -a 'uptime'
ansible all -m shell -a 'ip r'
ansible all -m shell -a 'fdisk -l' --become ## To get elevated privileges on target nodes
````
#### Classroom activity:
:::warning
Q:
Install elinks using ansible:
Sol:
ansible nodes -m apt -a "name=elinks" --become
ansible nodes -m apt -a "name=elinks state=present" --become
ansible nodes -m apt -a "name=elinks state=latest" --become

Q:
Uninstall elinks using ansible:
Sol:
ansible nodes -m apt -a "name=elinks state=absent" --become

Q:
Create a user "ansibleadm" using ansible
Sol:
ansible nodes -m user -a "name=ansibleadm" --become

Q:
Create a file named "ansible.txt" in /tmp directory

Sol:
ansible nodes -m file -a "path=/tmp/ansible.txt state=touch"
:::

#### Ansible Fundamental Modules
:::warning
- ping
- user
- service
- file
- copy
- apt/yum/package
- template
:::

### Ansible Playbooks
#### Playbook to ping the nodes for health check
:::warning
Ad-hoc command:
````yaml=    
ansible all -m ping
````
Equivalent Playbook:

````yaml=
## vi ping.yaml

--- ## Using playbook to run ping on all nodes
- hosts: nodes
  tasks:
    - name: Ping all nodes
      action: ping
  
````
Run the Playbook:
````yaml=
ansible-playbook ping.yaml
````
:::
YAML files will have the extension as .yaml or .yml


#### Playbook to install package on target nodes
:::warning
Ad-hoc command:
````yaml=
ansible nodes -m apt -a "name=elinks state=present" --become
````

Equivalent playbook:

````yaml=
## vi elinks.yaml

--- ## Basic playbook to install a package via apt module
- hosts: nodes
  become: yes
  tasks:
    - name: install elinks
      apt:
        name: elinks
        state: present

````
Run the Playbook:
````yaml=
ansible-playbook elinks.yaml
````
:::

#### Playbook to create user(s) on target nodes
:::warning
Ad-hoc command:
````yaml=
ansible nodes -m user -a "name=playuser password=mysupersecurepassword" --become
````

Equivalent playbook:
````yaml=
## vi user.yaml

--- ## basic play
- hosts: nodes
  become: yes
  tasks: 
    - name: create user
      user:
        name: userplay
        password: mysupersecurepass
````

Run the Playbook:
````yaml=
ansible-playbook user.yaml
````
:::

#### Variables in Ansible Playbooks
:::warning
````yaml=
## vi vars.yaml

--- ## playbook to install a specified package
- hosts: '{{ myhosts }}'
  become: yes
  tasks:
    - name: install specified software package
      apt:
        name: '{{ pkg }}'
        state: present

````
Run the Playbook:
````yaml=
ansible-playbook vars.yaml --extra-vars "pkg=telnet myhosts=webservers"
or
ansible-playbook vars.yaml -e "pkg=telnet myhosts=webservers"
````
:::


### Ansible Roles


#### Working with Ansible Roles
````yaml=
Check local roles:
ansible-galaxy role list

Create a local role:
ansible-galaxy init <role-name>

Explore Ansible Galaxy:
galaxy.ansible.com

Go to (one of) default location for ansible roles:
cd ~/.ansible
mkdir roles && cd roles

Install a role from Ansible Galaxy:
ansible-galaxy install <authorname.rolename>

Validate the role installation:
ansible-galaxy role list
````

#### Write a playbook to call the role

````yaml=
## vi role-play.yaml

--- ## Playbook to call nginx role
- hosts: nodes
  become: yes
  tasks:
    - name: install and manage nginx
      include_role:
        name: geerlingguy.nginx
````

#### Run the Playbook
````yaml=
ansible-playbook role-play.yaml
````
#### Validate the changes
````yaml=
curl localhost
or 
elinks http://localhost
or 
which nginx
or
sudo systemctl status nginx
````


### Assignments
:::success
**27/28 May 2023**
- Lesson 07 Demo 2
- Lesson 07 Demo 3
- Lesson 07 Demo 4
- Lesson 07 Demo 6
:::


### References
:::info
- [Ansible Inventory Documentation](https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html)
- [Ansible Playbook Documentation](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_intro.html)
:::
