Back to the main page

Introduction

Ansible Execution Environment is a containerized environment that provides a consistent way to execute Ansible playbooks. It is a key component of the Ansible Automation Platform (AAP), however, its capabilities extend beyond AAP, and it can be utilized independently.

Challenge and Motivation

Usually, there is need to support variety of distros like Solaris, Linux, Oracle Virtual Server, etc. This includes support of older releases such as Solaris 10 and Linux 5. Likely this is limited to use Ansible 2.12.10, as newer Ansible versions are not compatible with these legacy systems.

The challenge is not being able to upgrade to newer Ansible versions, which means you are missing out on new features and improvements. To address this, the plan is to leverage Ansible Execution Environment, and create separate environments with different Ansible versions.

For example, Ansible 2.12.10 environment can be used to manage hosts in some Sustaining mode (ex. Solaris 10, Linux 5-7). Additionally, you can have environment with the latest Ansible version, that will be used to manage newer OS releases. This allows use of latest ansible modules and features.

Getting started with Execution Environments

You can run Ansible automation in containers, like any other application. Ansible uses container images known as Execution Environments (EE) that act as control nodes. The EE remove complexity to scale out automation projects.

Ansible EE is a container image (built using ansible-builder CLI) that bundles Ansible, its dependencies, and any additional requirements needed to execute Ansible playbooks.

The EE image contains the following packages as standard:

Ansible Builder

The ansible-builder CLI is used to configure and build images, that can be used by containerization tools like Podman. These images are then used to run containers, and are known as Ansible EE.

Concept and terms

Execution Environment (EE) definition

This is the YAML file, where you define your EE. By default, it's named execution-environment.yml. It tells ansible-builder how to creates build instruction file (Containerfile for Podman), and use that file to build context for the image.

NOTE: ansible-builder v3 is the latest one, do not use previous version!

Start with ansible-builder

- Likely, you'll have your desired Python version 3.X virtual environment. There use pip to install ansible-builder (pip3 install ansible-builder), ensure it's version 3.x
$ pip3 show ansible-builder

Name: ansible-builder
Version: 3.1.0
Summary: "A tool for building Ansible Execution Environments"
Home-page: https://ansible-builder.readthedocs.io
Author: Ansible, Inc.
Author-email: info@ansible.com
License: Apache Software License, Version 2.0
Location: /root/virtenv/ansible-builder-3.1.0/lib/python3.9/site-packages
Requires: bindep, jsonschema, packaging, PyYAML

- Another requirement is to have installed the containerization tool, like Podman.

- Create EE definition file, and other dependency files - these are just examples.

---
# File: execution-environment.yml

# schema for ansible-builder 3
version: 3
images:
  base_image:
    name: container-registry.oracle.com/os/oraclelinux:9-slim
# Can't use it here, the base image doesn't have python
#options:
#  package_manager_path: /usr/bin/microdnf

dependencies:

  # Install ansible collections
  galaxy: requirements.yml

  # Python dependency installed with pip
  python: requirements.txt

  # Binary (OS) dependency installed with yum/dnf
  system: bindep.txt

  # pip install these
  ansible_core:
    package_pip: ansible-core==2.12.10
  ansible_runner:
    package_pip: ansible-runner

# src is file in same folder as execution-environment.yml
# dest is sub-folder under _build
additional_build_files:
  - { src: ansible.cfg, dest: configs }

# Building layers: base, galaxy, builder (not user accessible), final.
additional_build_steps:
  # Commands to run before building base leyer, usually OS pkgs install
  prepend_base:
    - RUN >-
          microdnf install -y python3 python3-devel python3-pip dnf crypto-policies-scripts &&
          python3 -m pip install --upgrade pip --user &&
          update-crypto-policies --set LEGACY
  # Customize galaxy setup/install
  prepend_galaxy:
    - COPY _build/configs/ansible.cfg /etc/ansible/ansible.cfg
  # Customize runtime environment
  append_final:
    - COPY _build/configs/ansible.cfg /etc/ansible/ansible.cfg
...
---
# File: requirements.yml

# Collections installed with ansible-galaxy
# ansible.posix latest doesn't support ansible-core 2.12.10
collections:
  - name: ansible.netcommon
  - name: ansible.posix
    version: 1.5.4
  - name: ansible.utils
  - name: ansible.windows
  - name: community.crypto
  - name: community.dns
  - name: community.general
  - name: community.libvirt
  - name: community.mysql
  - name: community.network
  - name: community.postgresql
  - name: containers.podman
  - name: oracle.oci
  - name: ovirt.ovirt
...
# File: requirements.txt

# Python modules installed with pip
ansible-lint==5.4
# File: bindep.txt

# Binary dependency, installed with yum/dnf
sshpass
git
- The command "ansible-builder create" builds instruction file Containerfile (Podman).

- The command "ansible-builder build" does previous step (create Containerfile), and runs Podman to build an image based on Containerfile.


# Build the image
# Use verbosity level 3
# Specify image tag

$ ansible-builder build -v 3 --tag ol9-core2.12.10

... Expect successful completion with output:

[3/3] COMMIT ansible-execution-env:latest
--> 93ec8f24cbc2
Successfully tagged localhost/ol9-ansible-core2.12.10:latest
93ec8f24cbc2d4bd0348ac424d72b87686e6f79696a985e8c0b078cf2a4a40b5

# Run podman images to review images on your host.

Use the EE to run a playbook

Simple playbook to report distro version of remote host, and ping it.

---
# Simple playbook to report distro version of remote host, and ping it.
- name: Play
  hosts: all
  gather_facts: true
  tasks:
    - name: Debug
      ansible.builtin.debug:
        msg: "{{ ansible_distribution }}_{{ ansible_distribution_version }}"
    - name: Connection check
      ansible.builtin.ping:
...

Start container from image, and run playbook.

# Mount local folder to containers' /runner
# In this folder, you have your inventory and playbook
# Remove/delete container after run with --rm
# Interactive terminal is option -it
 
$ podman run --rm -it -v $PWD:/runner localhost/ol9-core2.12.10 ansible-playbook -i inventory playbook.yml

Image (EE) distribution

When it comes to distributing Podman images among multiple hosts, the native approach is to utilize a container registry, like OCIR. The OCIR serves as a centralized repository for storing and managing container images.

However, in environments where a container registry is not available, alternative methods can be employed. One such approach is to use the Podman CLI to manually distribute images.

Save podman image as tar archive.

# List images

$ podman images

REPOSITORY                          TAG         IMAGE ID      CREATED            SIZE
localhost/ol8-python39-core2.12.10  latest      e7848f65da2a  9 days ago         1.44 GB
localhost/ol8-python38-core2.12.10  latest      60a3bf2e5540  2 weeks ago        1.43 GB <- save it

# Save the image (ex. ol8-python38-core2.12.10), use oci-archive format, and specify output name.

$ podman save --format oci-archive -o ee-ol8-core21210 60a3bf2e5540

Copying blob 1dcf70a42af2 done   |
Copying blob 97779b2da816 done   |
Copying config 60a3bf2e55 done   |
Writing manifest to image destination

# Verify the result.

$ ls -lah 8-38-21210
-rw-r--r-- 1 root root 583M Jul  3 08:41 ee-ol8-core21210

Import podman image on another host.

# Copy image to another host

$ scp ee-ol8-core21210 another-host.domain.com:/tmp/

# On another host, load the image

$ cd /tmp
$ podman load -i ee-ol8-core21210

Getting image source signatures
Copying blob 93388424bfae done   |
Copying config 60a3bf2e55 done   |
Writing manifest to image destination
Loaded image: sha256:60a3bf2e554057f6d8eadeafc76ee1de7c29759149fa83777cb7698278dfffa1

# List images

$ podman images
REPOSITORY                     TAG         IMAGE ID      CREATED       SIZE
ee-ol8-core21210               none      60a3bf2e5540  2 weeks ago   1.43 GB

# Verify the image
# Start container, as root, and run command to verify OL and Ansible versions.

$ podman run -u root --rm -it 60a3bf2e5540

bash-4.4# cat /etc/oracle-release
Oracle Linux Server release 8.10

bash-4.4# ansible --version
ansible [core 2.12.10]
  python version = 3.8.17 (default, Oct 25 2023, 04:18:23) [GCC 8.5.0 20210514 (Red Hat 8.5.0-20.0.1)]
  jinja version = 3.1.6

Back to the main page