Skip to main content

Command Palette

Search for a command to run...

02 - Ansible Advanced

Published
5 min read
R

I am an aspiring DevOps Engineer proficient with containers and container orchestration tools like Docker, Kubernetes along with experienced in Infrastructure as code tools and Configuration as code tools, Terraform, Ansible. Well-versed in CICD tool - Jenkins. Have hands-on experience with various AWS and Azure services. I really enjoy learning new things and connecting with people across a range of industries, so don't hesitate to reach out if you'd like to get in touch.

Playbook run options

  1. Dry Run (Check Mode)

    • The --check option runs the playbook without making changes to the target systems.

        $ ansible-playbook playbook.yml --check
      
  2. Start at

    • The --start-at-task option is use to specify a name of a task that the playbook should start at.

    • This skips all the other tasks that come before it and the playbook will start running at the task specified.

        $ ansible-playbook playbook.yml –-start-at-task “Start httpd service”
      
  3. Tags

    • We can optionally tag the plays or tasks using tag option to the playbook or task.

    • Using this, we can choose to run or skip specific tasks from all the tasks.

        $  ansible-playbook playbook.yml –-tags "install"
      
        $ ansible-playbook playbook.yml –-skip-tags "install"
      

Install and Configure Ansible

Control Node

  • A control node is a machine where the core Ansible software is installed and configured. We store all our code and playbooks on this control node only.

  • The Ansible software can only be installed on a Linux machine, we cannot have a Windows machine as a control node of Ansible.

  • However, Windows machines can be a target nodes or managed nodes in Ansible.

Install Ansible on Control Node

$ sudo yum install ansible        # RedHat or CentOS

$ sudo apt-get install ansible    # Ubuntu

$ sudo dnf install ansible        # Fedora

$ sudo pip install ansible        # Python (PIP)

Install Ansible via PIP (RedHat or CentOS)

PIP gives the latest version of ansible as some of package managers may not as they are not updated.

# install pip if not present
$ sudo yum install epel-release        # use this command while installing with package manager as well
$ sudo yum install python-pip

# install ansible 
$ sudo pip install ansible 

# upgrade ansible
$ sudo pip install --upgrade ansible

#install specific version of ansible
$ sudo pip install ansible==2.4

Note

  • The default inventory hosts file (/etc/ansible/hosts) and the default ansible configuration file (/etc/ansible/ansible.cfg) are only created when Ansible is installed using the package managers like yum or apt-get. They are not created by default if Ansible is installed using Python (pip).

Create and distribute SSH keys to managed nodes

  • On control node, create a pair of SSH keys (public and private key-pair) and transfer the public key to the target machines.

      $ ssh keygen -t rsa    
      id_rsa    id_rsa.pub       # private and public key (default location is ~/.ssh)
    
  • To transfer, there are 2 options:

    1. Copy the contents of the public key at the location ~/.ssh/authorized_keys on target machines using username and password for the first time, and after this disable the password-based authentication.

    2. Make use of ssh-copy-id tool, it needs the path of private key.

       $ ssh-copy-id -i id_rsa user1@server1
      
  • Now, we can login into the target machines using SSH private key.

      $ ssh -i rsa_pub user1@server1
    

Inventory File

  • Ansible assumes that the user is root by default.

  • If we have configured SSH keys using other user (like user1), they we have to explicitly mentioned that inside the inventory file using ansible_user parameter.

  • Ansible picks up the SSH private key from the default location (~/.ssh). If it is present at some other location, then we have to specify the path that using ansible_ssh_private_key_file parameter.

      web1 ansible_host=172.20.1.100 ansible_user=user1 ansible_ssh_private_key_file=/some-path/private-key
    

Ad-hoc commands

  • Ad-hoc commands in Ansible are single-line commands executed directly from the command line without the need to create a playbook.

      $ ansible <host-pattern> -m <module-name> -a "<arguments>"
    

Examples:

  1. Ping All Hosts:
  • Check connectivity to all hosts in the inventory using the ping module:

      $ ansible all -m ping
    
  1. Run a Command on Remote Hosts:
  • Use the command module to run a command:

      $ ansible webservers -m command -a "uptime"
    
  1. Copy a File to Remote Hosts:
  • Copy a file using the copy module:

      $ ansible all -m copy -a "src=/tmp/test.txt dest=/tmp/test.txt"
    
  1. Restart a Service:
  • Restart the Apache service using the service module:

      $ ansible webservers -m service -a "name=httpd state=restarted"
    

Privilege Escalation

  • Privilege escalation in Ansible refers to the process of executing tasks on managed nodes with elevated privileges, such as root or another administrative user.

Key Parameters for Privilege Escalation

  1. become:

    • Enables privilege escalation.

    • Equivalent to using sudo in a shell.

  2. become_user:

    • Specifies the user to switch to when escalating privileges.

    • Default is root.

  3. become_method:

    • Defines the method used for privilege escalation. Default is sudo.

    • Other options include su, pbrun, or doas.

  4. become_flags:

    • Adds additional flags or options for the privilege escalation method.
  5. become_password:

    • Used if the privilege escalation method requires a password.

    • Use --ask-become-pass parameter while running a playbook or module in a command line.


Dynamic Inventory

  • Dynamic Inventory is a inventory information that Ansible retrieves programmatically when the Ansible playbook is run (as opposed to us defining it in a static inventory file).

  • Dynamic inventory in Ansible refers to a method of dynamically generating a list of managed hosts (inventory) at runtime, instead of using a static inventory file.

  • Inventory Script or Plugin:

    • A script or plugin fetches host information from an external source (e.g., AWS, Azure, GCP, etc.).

    • The script generates inventory data in JSON format.

Static Inventory:

web1 ansible_host=172.20.1.100 ansible_ssh_pass=Passw0rd
web2 ansible_host=172.20.1.101 ansible_ssh_pass=Passw0rd
[web_servers]
web1
web2
$ ansible-playbook playbook.yml –i inventory.txt

Inventory Script (Dynamic Inventory):

#!/usr/bin/env python
import json
import argparse

# Get inventory data from source - CMDB or any other API
def get_inventory_data():
    return {
        "web_servers": {
        "hosts": ["web1", "web2"]
    },
    "_meta": {
        "hostvars": {
            "web1": {
                "ansible_host": "172.20.1.100",
                "ansible_ssh_pass": "Passw0rd"
            },
            "web2": {
                "ansible_host": "172.20.1.101",
                "ansible_ssh_pass": "Passw0rd"
        }
        }
    }
}
# Default main function
if __name__ == "__main__":
    read_cli_args();
    inventory_data = get_inventory_data()
    if args.list:
    print(json.dumps(inventory_data))
    <Code Hidden>
  • Command to run a playbook:

      $ ansible-playbook playbook.yml –i inventory.py
    
  • --list: output the entire inventory information in JSON format

      ./inventory.py --list
    
      {
          "web_servers": {
              "hosts": [
                  "web1",
                  "web2"
              ]
          },
          "_meta": {
              "hostvars": {
                  "web2": {
                      "ansible_host": "172.20.1.101",
                      "ansible_ssh_pass": "Passw0rd"
                  },
                  "web1": {
                      "ansible_host": "172.20.1.100",
                      "ansible_ssh_pass": "Passw0rd"
                  }
              }
          }
      }
    
  • --host: print the parameters defined for the given host in a JSON format

      $ ./inventory.py –-host web1
    
      {
          "ansible_host": "172.20.1.100",
          "ansible_ssh_pass": "Passw0rd"
      }
    
  • There are multiple inventory script (.py) readily available to use on ansible repo. For ex:

      $ ansible-playbook playbook.yml –i ec2.py