Ansible Execution Environments
Automation breaks when two machines carry different versions of Ansible, Python, or libraries. A playbook that works on a laptop fails on a build server because a library is missing. An execution environment (EE) solves the problem by packing Ansible, Python, collections, and system tools into a container image. Think of a lunch box that holds the meal, cutlery, and a napkin: it travels anywhere and behaves the same at every table.
Diagram: Same Image, Every Place
┌──────────────────────────────────┐
│ Execution Environment Image │
│ ┌────────────────────────────┐ │
│ │ ansible-core 2.16 │ │
│ │ Python 3.11 + libraries │ │
│ │ Collections: aws, k8s │ │
│ │ System tools: git, rsync │ │
│ └────────────────────────────┘ │
└───────┬──────────┬───────────┬───┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Laptop │ │ CI/CD │ │ AWX │
└─────────┘ └─────────┘ └─────────┘
identical behavior everywhere
Tools Involved
| Tool | Purpose |
|---|---|
| ansible-builder | Builds an execution environment image from a definition file |
| ansible-navigator | Runs playbooks inside an image with a text interface |
| ansible-runner | Runs Ansible in an isolated process or container, used by AWX |
| Podman or Docker | Container engine that builds and starts the image |
Install the Tools
python3 -m pip install ansible-builder ansible-navigator
podman --version
Write the Definition File
The file execution-environment.yml lists everything the image needs.
---
version: 3
images:
base_image:
name: quay.io/centos/centos:stream9
dependencies:
ansible_core:
package_pip: ansible-core==2.16.4
ansible_runner:
package_pip: ansible-runner
galaxy: requirements.yml
python: requirements.txt
system: bindep.txt
# requirements.yml
collections:
- name: amazon.aws
- name: community.general
# requirements.txt
boto3
botocore
# bindep.txt
git [platform:rpm]
rsync [platform:rpm]
Build the Image
ansible-builder build --tag shop-ee:1.0
podman images
The builder installs each dependency in layers. A build can take several minutes on the first run.
Run a Playbook Inside the Image
ansible-navigator run site.yml \
--execution-environment-image shop-ee:1.0 \
--mode stdout
Navigator mounts the project folder into the container, runs the playbook, and prints results. Add --mode interactive for a text user interface that lets you browse plays and task details.
Set Defaults for the Project
# ansible-navigator.yml
ansible-navigator:
execution-environment:
image: shop-ee:1.0
pull:
policy: missing
mode: stdout
Inspect an Image
ansible-navigator images
ansible-navigator collections
ansible-navigator doc ansible.builtin.copy
Share the Image
Push the image to a container registry so CI systems and AWX can pull it.
podman tag shop-ee:1.0 registry.example.com/automation/shop-ee:1.0
podman push registry.example.com/automation/shop-ee:1.0
Tag images with version numbers. A fixed tag guarantees the same toolset on every run, and a new tag rolls out upgrades on a schedule.
Benefits
- Identical tool versions across laptops, pipelines, and AWX
- No Python package clashes on the host system
- Faster onboarding, since new teammates pull one image
- Simple rollback by switching to an earlier tag
Try This
Write a definition file that includes the community.general collection. Build the image with a tag of your choice. Run ansible-navigator collections --execution-environment-image with that tag and confirm the collection appears in the list.
Summary
An execution environment is a container image that bundles Ansible, Python, collections, and system tools. The ansible-builder tool creates the image from a definition file, and ansible-navigator runs playbooks inside it. A shared, versioned image removes the "works on my machine" problem and gives every pipeline and teammate the same trusted toolset.
