Ansible Basics

From Nick's Personal Wiki
Jump to navigation Jump to search

Installing Ansible

Add Required Repositories

For RHEL systems, install the EPEL (Extra Packages for Enterprise Linux) repository:

sudo dnf update
sudo dnf install epel-release 


For Ubuntu/Debian based systems:

sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible 

Install Ansible

Once the repository is enabled, install Ansible using the package manager:

RHEL Systems
sudo dnf install ansible 
Ubuntu/Debian Systems
sudo apt install ansible 


Verify the Installation

After installation, verify Ansible is installed correctly:

ansible --version 

You should see output similar to:

ansible [core 2.x.x]
  config file = /etc/ansible/ansible.cfg
  python version = 3.x.x 

Troubleshooting

  • If epel-release is not found, try enabling the codeready-builder repo or check for typos.


Creating an Ansible Inventory File

An inventory file for Ansible is a file that has a list of the hosts Ansible will interact with, their hostnames, IP addresses, and other relevant information.

By default, Ansible will use '/etc/ansible/hosts' if no specific inventory file is specified.

You can manually specify an inventory file with the '-i' option of the 'ansible-playbook' command. Typically these are .yml or .ini files. i.e.:

 INVENTORY.ini / ANSIBLE_HOSTS.yml / SERVER_LIST.ini 

An example inventory file might look like:

 [web-server] (this is the host group)
 web-server-01 ansible_host=1.2.3.4 (each entry is a single host, with arguments/options beside)
 web-server-02 ansible_host=WEBSERVER_HOSTNAME 

You can also format the inventory file, to manage entire host groups collectively, like this:

 [file-server]
 file01 ansible_host=1.2.3.4
 file02 ansible_host=5.6.7.8
 file03 ansible_host=9.10.11.12
 
 [file-server:vars]
 ansible_user=USER
 ansible_port=PORT#
 ansible_become=[true/false] (whether or not Ansible will become 'root' user)
 ansible_become_user=[true/false] (whether or not Ansible will become the current user)
 ansible_ssh_private_key=/PATH/TO/IDENTITY/FILE  


Creating an Ansible Playbook (Basics)

An Ansible playbook is the instruction set that Ansible will follow to enforce the changes/configurations/etc across the specified hosts in the inventory file(s). Typically playbook files are .yml files. i.e.:

 PLAYBOOK.yml / initial_setup.yml / web_server.yml 

Generic Playbook Syntax

An example playbook may look like this:

  - name: Basic Setup (Description of what this playbook does)
    hosts: all (You can also specify a specific host group, like "file-server" or "web-server" or "prod")
    become: true 
    tasks:
      - name: Set Hostname (Description of what this specific task does)
        hostname:
          name: DESIRED_CUSTOM_HOSTNAME_OF_TARGET_NODE or "{{ inventory_hostname }}" (can use this option if the target's IP is included in the inventory file, Ansible will have the target set its hostname to the target's corresponding IP address) 
 
      - name: DESCRIPTION OF WHAT THIS TASK WILL DO
        dnf: (calls the Ansible module for dnf, there are other modules outlined below)
          name: PACKAGE (specifies the package to pass to dnf)
          state: STATE (see below for available STATES) 


Example Playbook

An example playbook (with some notations) to perform specific tasks may look like this:

  - name: Hostname and Repo Config Playbook
    hosts: all 
    become: true 
    tasks:
      - name: Set Hostname 
        hostname:
          name: DESIRED_CUSTOM_HOSTNAME_OF_TARGET_NODE or "{{ inventory_hostname }}" (can use this option if the target's IP is included in the inventory file, Ansible will have the target set its hostname based on the target's IP's corresponding hostname) 
      - name: Ensure epel-release repository is installed
        dnf: 
          name: epel-release 
          state: present 
      -name: Reboot if hostname changes
       reboot: 
         msg: "Rebooting after hostname change"
         connect_timeout: 5
         reboot_timeout: 300
       when: ansible_hostname != inventory_hostname (this task will only be run when this condition is met, when the device's hostname does NOT match the hostname specified in the inventory file passed to Ansible) 


Ansible Playback Modules

Some other modules that can be called in an Ansible Playbook include:

Package Modules (apt, yum, dnf, etc.)

 State: Description
 present: Ensures the package is installed.
 latest: Installs or upgrades the package to the latest version.
 absent: Removes the package if it is installed.
 installed: Alias for present.
 removed: Alias for absent. 

Service Modules (service, systemd)

 State: Description
 started: Ensures the service is running.
 stopped: Ensures the service is stopped.
 restarted: Stops and starts the service again.
 reloaded: Reloads the service (useful for configs).
 enabled: (with enabled: true) Ensures service starts at boot.
 disabled: Prevents service from starting at boot. 

Crontab Modules

Ansible can modify the cron files of the root user (/var/spool/cron/root) with the below module:

 ansible.builtin.cron: 

An example of how this would be used would be:

- name: Set cron job to reboot hosts at 1300 every 2nd day of every month
  hosts: all
  become: true
  tasks:
    - name: Set cron job to reboot hosts at 1300 every 2nd day of every month
      ansible.builtin.cron:
        name: "Scheduled Reboot"
        minute: "0" (these next few fields follow standard Cron logic)
        hour: "13"
        day: "*/2"
        job: "/sbin/reboot"
        user: root 

Then to remove that same cron job from the target hosts:

- name: Remove the cron job to reboot hosts at 1300 every 2nd day of every month
  hosts: all
  become: true
  tasks:
    - name: Remove "Scheduled Reboot" cron job
      ansible.builtin.cron:
        name: "Scheduled Reboot" (Specify the EXACT name of the cron job you created originally, this is how Ansible locates it)
        user: root
        state: absent (verifies that it is missing, and removes it if it still exists) 

File and Directory Modules (file, copy, template)

 State: Description
 touch: Creates an empty file if it doesn’t exist.
 absent: Deletes the file or directory.
 directory: Ensures a directory exists.
 file: Ensures it’s a regular file (can also adjust permissions).
 link: Ensures a symbolic link exists.
 hard: Ensures a hard link exists. 
 blockinfile: Adds a specified block of plaintext to a specified file at a specified path. (See Below)

Blockinfile Module

Blockinfile example:

- name: Add PLAINTEXT to /path/to/EXAMPLE.txt
  blockinfile:
      path: /path/to/EXAMPLE.txt
      block: "PLAINTEXT TO BE ADDED"

You can also specify the file via the Inventory file. The inventory file would look like this:

[EXAMPLEHOSTS] 
EXAMPLEHOST ansible_host=1.2.3.4 FILE_NAME=/path/to/EXAMPLE.txt
EXAMPLEHOST2 ansible_host=5.6.7.8 FILE_NAME=/path/to/other/EXAMPLE.doc 

Then you can specify these host-specific files (FILE_NAME in this example) using blockinfile via:

- name: Add PLAINTEXT to multiple hosts
  blockinfile:
      path: "{{ FILE_NAME }}"
      block: "PLAINTEXT TO BE ADDED"
      insertafter: '^something' #Adds the block to the line after 'something'
      insertbefore: 'something else^' #Adds the block to the line before 'something else'

User & Group Modules (user, group)

 State: Description
 present: Ensures the user or group exists.
 absent: Ensures the user or group is removed. 

Network Resources / Repos

For repositories (like yum_repository, apt_repository):

 State: Description
 present: Repo is configured and available.
 absent: Repo is removed. 

For firewall rules, cloud resources, etc., modules usually support:

 State: Description
 present: Create or apply the configuration.
 absent: Remove or undo the configuration.
 enabled: Turn on or activate the resource.
 disabled: Turn off or deactivate it. 

Running an Ansible Playbook

The basic syntax for running an Ansible playbook command looks like:

 ansible-playbook -i INVENTORY_FILE PLAYBOOK_FILE 

If your playbook will require Ansible to perform operations as a superuser (i.e. will require 'sudo') you can pass the 'sudo' password like this:

 ansible-playbook -i INVENTORY_FILE PLAYBOOK_FILE --ask-become-pass 


Additional Resources

Redhat Developer Site

Ansible Community Documentation