Ansible 101 - The basics

ansible Jan 16, 2023

Ansible is an open-source tool for automating infrastructure and application deployment, using simple YAML language. It's used to manage and automate tasks across multiple servers and devices.

It uses simple, human-readable language (YAML) to describe tasks and configurations, and can be used to manage and automate the deployment, configuration, and management of various systems and applications. Ansible allows you to automate tasks such as software installation, configuration changes, and service management across a large number of servers and devices with minimal effort. It is often used in DevOps and IT operations to improve efficiency and reduce errors.

Most of the content of this blog post came from another blog post I wrote about Ansible. It's a great place to start, with many links with awesome content made by the community and by Red Hat, all of them for free:

Ansible tricks
I want to show you some tricks and solutions that I designed along my journey automating stuff with Ansible. To use these tricks doesn’t matter if you are new in the Ansible world or already are a power user.

1. Ansible world overview

---
markmap:
  zoom: false
  pan: false
---

# Ansible

## [Documentation](https://docs.ansible.com/)

## [Ansible Core](https://docs.ansible.com/core.html)
- ansible
- ansible-playbook
- ansible-vault
- ...

## [Ansible Automation Platform (AAP)](https://www.redhat.com/en/technologies/management/ansible)

- Automation Controller (AWX)
- Automation Hub (pulp)

## [Content Creator tools](https://www.ansible.com/content-tools#:~:text=Ansible%C2%AE%20content%20tools%20are,exact%20Ansible%20content%20they%20need.)

- ansible-navigator
- ansible-lint

## [Community](https://hackmd.io/@ansible-community)

- [Chat at Matrix](https://hackmd.io/@ansible-community/community-matrix-faq)
- [Ansible Galaxy (collections repo)](https://galaxy.ansible.com/)

2. How to install Ansible

Reference: https://docs.ansible.com/ansible/latest/installation_guide/index.html

You can install Ansible using some package manager, like dnf or brew, but you can also use pip to get the latest version.

Example using pip:

# Create a virtual environment
python3 -m venv venv

# Enable the virtual environment
source ./venv/bin/activate

# Install ansible
pip install ansible

3. The YAML sintax

Reference: https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html

Ansible uses the YAML structure. So, it's important to know:

  • dict/map
  • string (inline, multiline)
  • number
  • bool
  • list

4. My first playbook

Reference: https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html

When you install the ansible package, a few CLIs will become available, one of them is the ansible-playbook. You can use it to directly run the playbook:

# Create the my-playbook.yaml file
vim my-playbook.yaml

# Run the playbook
ansible-playbook \
    -e custom_message="I like coffee" \
    my-playbook.yaml
# ./my-playbook.yaml

- name: My first playbook to run on the localhost
  hosts: localhost
  connection: local
  
  # Example of map
  vars:
    show_message: false
    custom_message: I like Pokémon
  
  tasks:
    - name: My debug task
      debug:
        msg: |
            The custom_message value is: {{ custom_message }}
            {% if show_message %}
            hey!
            {% endif %}

5. Converting a bash script into an Ansible Playbook

Create an automation with a bash script

  • Create a directory
  • Create a text file with the current datetime
  • Compress the file
  • Output the file name
#!/bin/bash

OUTPUT_DIR=$(pwd)/output

mkdir -p ${OUTPUT_DIR}
date > ${OUTPUT_DIR}/time.log
cd ${OUTPUT_DIR}
tar -cvf time.log.tar time.log

echo
echo "output file: $(pwd)/time.log.tar"

Create a playbook that invokes the bash script

# Documentation here
---

- name: Run script
  hosts: localhost
  connection: local

  tasks:
    - name: Create output dir
      shell: |
          OUTPUT_DIR=$(pwd)/output

          mkdir -p ${OUTPUT_DIR}
          date > ${OUTPUT_DIR}/time.log
          cd ${OUTPUT_DIR}
          tar -cvf time.log.tar time.log

          echo
          echo "output file: $(pwd)/time.log.tar"

Convert each bash script step into Ansible native modules

# Documentation here
---

- name: Compress datetime file
  hosts: localhost
  connection: local

  tasks:
    - name: Create output dir
      file:
        path: "{{ playbook_dir }}/output"
        state: directory

    - name: Create a file with the date
      copy:
        content: "{{ ansible_date_time.epoch }}"
        dest: "{{ playbook_dir }}/output/time.log"

    - name: Compress time.log
      archive:
        path: "{{ playbook_dir }}/output/time.log"
        dest: "{{ playbook_dir }}/output/time.log.gz"
        format: gz

    - name: Show time.log file path
      ansible.builtin.debug:
        msg: "{{ playbook_dir }}/output/time.log"

6. Run Ansible against a remote instance

How to connect to a remote instance

Create an inventory file:

# ./inventory

[minecraft-servers]
192.168.11.22

[minecraft-servers:vars]
custom_message="This message came from the inventory file"

Create the playbook:

# ./remote-playbook.yaml

- name: Connecting to a remote instance
  hosts: minecraft-servers
  connection: local
  
  # Example of map
  vars:
    custom_message: I like Pokémon
  
  tasks:
    - name: My debug task
      debug:
        msg: "The custom_message value is: {{ custom_message }}"

Run the playbook against the remote instance:

# Test your SSH connection against your host
ssh [email protected]

# Create the inventory file
vim ./inventory

# Create the playbook
vim ./remote-playbook.yaml

# Run the playbook
ansible-playbook -i ./inventory ./remote-playbook.yaml

How to add your GitHub pub keys to the SSH authorized_keys file

- hosts: all

  vars:
    github_users:
      - thenets
    machine_user: ec2-user

  tasks:
    - name: Add the GitHub user's public keys to the authorized_keys file
      ansible.posix.authorized_key:
        user: "{{ machine_user }}"
        key: https://github.com/{{ item }}.keys
      become: true
      loop: "{{ github_users }}"

Cheatsheet

Tricks

  1. Dynamicaly set env variable
- name: Set var in real time
  set_fact:
    current_time: "{{ lookup('pipe', 'date +%Y-%m-%d_%H-%M-%S') }}"

Full playbook example

---
- name: Basic Playbook for working with files
  # cat /etc/hosts - use this in terminal to see list of available hosts
  hosts: localhost
  # SSH is the default connection unless you are running in your own computer
  connection: local
  vars:
    luiz_filename: luiz_loves_shrimp
    other_filename: other_file
    my_directories: ./foo/bar/

  tasks:
    # Google for "ansible 'something' module"
    - name: Creating a file
      # https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html
      ansible.builtin.file:
        path: "{{ luiz_filename }}"
        # about state parameter:
        #https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html#parameter-state
        state: touch
      # aboput registering the output of the task
      # https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#registering-variables
      register: created_file
      # Returned values of file module
      # https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html#return-values

    - name: Debugging registered variable
      ansible.builtin.debug:
        msg: "{{ created_file }}"

    # Fail module to stop the execution at this point (uncomment)
    # - ansible.builtin.fail:
    #   when: created_file.owner != "sakus"

    - name: Creating all the directories in the path
      ansible.builtin.file:
        path: "{{ my_directories }}"
        #set state to absent to remove anything
        state: directory
        recurse: true

    - name: Creating a file
      ansible.builtin.file:
        path: "{{ other_filename }}"
        state: touch

    - name: Removing a file
      ansible.builtin.file:
        path: "{{ other_filename }}"
        # set state to absent to remove anything
        state: absent

Tags

Luiz Costa

I am a senior software engineer at Red Hat / Ansible. I love automation tools, games, and coffee. I am also an active contributor to open-source projects on GitHub.