Bookmark this page

Building a Custom Automation Execution Environment

Objectives

  • Build a custom automation execution environment image by using the ansible-builder command.

Deciding When to Create a Custom Automation Execution Environment

Red Hat provides several Ansible automation execution environments that suit the needs of many users. These automation execution environments include the most common Ansible Content Collections.

You can use the ansible-navigator images command to inspect a container image and view the collections, Python packages, and operating system packages it includes.

 Image: ee-supported-rhel8:latest Description
0│Image information               Information collected from image inspection
1│General information             OS and python version information
2│Ansible version and collections Information about ansible and ansible collect
3│Python packages                 Information about python and python packages
4│Operating system packages       Information about operating system packages
5│Everything                      All image information

The automation execution environments that Red Hat provides might be sufficient for your playbooks. In that case, you do not need to create new automation execution environments.

Sometimes, you might need an Ansible Content Collection that is not included in one of the existing automation execution environments. Often, you can install these extra collections in your Ansible project and then use an existing automation execution environment without having to build a new one.

On the other hand, you should consider creating a custom automation execution environment in the following situations:

  • You frequently reuse specific collections that are not included in the existing automation execution environments. It is more efficient to embed those collections in a custom automation execution environment than to install them from the project requirements.yml file every time you run a playbook in that project. This is especially true if you have many projects that use that collection.

  • The collection you want to use requires Python packages or software that are not included in an existing automation execution environment.

  • You need to use a collection that conflicts with another collection in your existing automation execution environments.

Preparing for a New Automation Execution Environment

You use the ansible-builder command to create the container images used for automation execution environments. The ansible-builder RPM package provides that command.

[root@host ~]# yum install ansible-builder

Create a working directory to prepare the files that you need to build the automation execution environment container image. The ansible-builder command searches this working directory for its execution-environment.yml configuration file, which it uses to determine how to build the container image.

The following is an example execution-environment.yml file:

---
version: 1

build_arg_defaults:
  EE_BASE_IMAGE: registry.redhat.io/ansible-automation-platform-22/ee-minimal-rhel8:latest 1
  EE_BUILDER_IMAGE: registry.redhat.io/ansible-automation-platform-22/ansible-builder-rhel8:latest 2

ansible_config: ansible.cfg 3

dependencies:
  galaxy: requirements.yml 4
  python: requirements.txt 5
  system: bindep.txt 6

1

The EE_BASE_IMAGE parameter specifies the automation execution environment container image to use as the starting point. By default, the ansible-builder command uses the Red Hat minimal image registry.redhat.io/ansible-automation-platform-22/ee-minimal-rhel8:latest.

Note

You are not allowed to publicly distribute container images that you build on top of the automation execution environment images that Red Hat provides with Red Hat Ansible Automation Platform.

To distribute your images on a public platform, such as Quay.io, use the public quay.io/ansible/ansible-runner:stable-2.12-latest base image instead. Alternatively, you can publish your execution-environment.yml file and let users build the container image themselves.

Red Hat only supports container images that you build on top of the Red Hat images.

2

The optional EE_BUILDER_IMAGE parameter points to a container image that includes the tools that the build process uses to construct automation execution environment container images. You should not need to use an image different from the default one.

3

The optional ansible_config parameter specifies an Ansible configuration file. The build process uses that file to pull collections from a location that requires authentication. For example, you must authenticate using an authentication URL and a token to install collections from an Ansible automation hub. If you only install collections from a public distribution platform, such as Ansible Galaxy, then you do not need to provide that file.

4

The galaxy parameter points to the file that lists the collections to install inside the automation execution environment. Ansible users usually set the file name to requirements.yml.

5

The python parameter points to the file that lists the Python packages to install. Some collections include a requirements.txt file. If you install such a collection, then you do not need to list its Python dependencies. Python developers usually set the file name to requirements.txt.

6

The system parameter points to the file that lists the RPM packages to install. Some collections include a bindep.txt file. If you install such a collection, then you do not need to list its RPM dependencies. Ansible users usually set the file name to bindep.txt, which is also the name used by the bindep tool that processes the file.

Declaring the Ansible Content Collections to Install

In the requirements.yml file, list the content collections that ansible-builder should install inside the automation execution environment.

The following example is a straightforward requirements.yml file that instructs the ansible-builder command to install the community.aws and community.general collections from Ansible Galaxy.

---
collections:
  - community.aws
  - community.general

The following example is a more complex requirements.yml file.

---
collections:
  - name: redhat.insights 1
    version: 1.0.5 2
    source: https://console.redhat.com/api/automation-hub/ 3
  - name: ansible.posix
    source: https://hub.example.com/api/galaxy/content/rh-certified/ 4

1

The name of the collection.

2

A specific version of the collection. If not specified, then the ansible-builder command selects the latest version.

3

The distribution platform that provides the collection. This example uses the Ansible automation hub address. You must create an ansible.cfg file and populate it with the token used to access that server. In the execution-environment.yml configuration file, you reference that ansible.cfg file by setting the ansible_config parameter.

4

A collection from private automation hub. You also need to provide your token in an ansible.cfg file.

The following example ansible.cfg file provides the parameters that the ansible-builder command needs to authenticate to Ansible automation hub and to private automation hub (at hub.example.com in this example).

[galaxy]
server_list = ansible_automation_hub, my_hub, galaxy

[galaxy_server.ansible_automation_hub]
url=https://console.redhat.com/api/automation-hub/
auth_url=https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token
token=eyJh...0Nwk

[galaxy_server.my_hub]
url=https://hub.example.com/api/galaxy/content/rh-certified/
token=e8e4...b0c2

[galaxy_server.galaxy]
url=https://galaxy.ansible.com/

Declaring Python Packages

In the requirements.txt file, list the Python packages that ansible-builder must install inside the automation execution environment.

The following example requirements.txt file lists some required Python packages. For each package, you can provide a specific version to select.

sh==1.13.1
jsonschema>=3.2.0,<4.0.1
textfsm
ttp
xmltodict
dnspython

Some collections include a requirements.txt file. In that case, you do not have to duplicate that file in your requirements.txt file.

Declaring RPM Packages

In the bindep.txt file, list the RPM packages that ansible-builder must install inside the automation execution environment.

The following bindep.txt file lists the RPM packages required by the preceding examples.

rsync [platform:rpm]
kubernetes-client [platform:rpm]

The bindep tool, which processes the bindep.txt file, can manage packages for several Linux distributions. Different distributions might have other package names for the same software. In the preceding file, the [platform:rpm] directive targets all the Linux distributions that use the RPM packaging system.

Some collections include a bindep.txt file. In that case, you do not have to duplicate that file in your bindep.txt file.

If the system on which you run the build process has a valid subscription, then the ansible-builder command has access to the same RPM packages as that system. However, if you do not register your system with Red Hat, then the build process has only access to the Red Hat Universal Base Images (UBI) repositories. These repositories are publicly available but only provide a limited set of RPM packages. The packages you define in the bindep.txt file might not be available in these repositories.

Building a New Automation Execution Environment

The execution environment builder automatically pulls the base and the builder images if they are not already available locally. If you use images from a container registry that requires authentication, then you must authenticate before starting the build process.

The following example shows how to log in to the Red Hat container registry that hosts the default images, ee-minimal-rhel8 and ansible-builder-rhel8:

[user@host demo]$ podman login registry.redhat.io

After you have prepared your configuration files and authenticated to the container registry, use the ansible-builder build command to create your automation execution environment container image.

Use the --tag (or -t) option to provide a name for the container image. The name has two parts: a name and an optional tag. For example, use the --tag demo:v1.0 option to name the container demo and give it the v1.0 tag. The tag defaults to latest if you do not specify it. For example, using the --tag demo option is the equivalent of using --tag demo:latest.

A successful build creates a new container image.

[user@host demo]$ ansible-builder build --tag ee-demo:v1.0
Running command:
  podman build -f context/Containerfile -t ee-demo:v1.0 context
Complete! The build context can be found at: /home/user/demo/context

Use the podman images command to display local container images.

[user@host demo]$ podman images
REPOSITORY                         TAG     IMAGE ID      CREATED      SIZE
localhost/ee-demo                  v1.0    9e1e281437a2  2 hours ago  744 MB
...output omitted...

Interacting with the Build Process

For more advanced configurations, you might have to customize the build process. For example, suppose your private automation hub uses a TLS certificate signed by a corporate certificate authority (CA). In that case, you must provide that CA certificate to the build process so that it can download collections from the distribution platform.

The execution environment builder operates in two stages:

  1. The command creates the context/ directory in the current directory. In that directory, it creates the Containerfile file, the equivalent of a Dockerfile file, which contains instructions for the podman build command. It also creates an _build/ subdirectory and then copies your requirements.yml, ansible.cfg, requirements.txt, and bindep.txt files into it so that the build process can access them.

  2. The command then runs the podman build command, which constructs the resulting automation execution environment container image.

To prepare for customizing the build process, use the ansible-builder create command to perform the first stage:

[user@host demo]$ ls
ansible.cfg bindep.txt execution-environment.yml requirements.txt requirements.yml
[user@host demo]$ ansible-builder create
Complete! The build context can be found at: /home/user/demo/context
[user@host demo]$ tree
.
├── ansible.cfg
├── bindep.txt
├── context├── _build│   ├── ansible.cfg│   ├── bindep.txt│   ├── requirements.txt│   └── requirements.yml└── Containerfile
├── execution-environment.yml
├── requirements.txt
└── requirements.yml

2 directories, 10 files

Important

The ansible-builder create command always overwrites the context/Containerfile file. Any changes you make to the context/Containerfile file are lost.

Adjusting the Build Arguments and Base Image

Default values for build arguments can be specified in the execution-environment.yml configuration file, defining the build_arg_defaults variable as a dictionary of arguments and their values. You can also specify these settings from the ansible-builder command line with the --build-arg option. If you also have an execution-environment.yml file, the values specified by the --build-arg option always take precedence.

Build arguments that are used by ansible-builder include:

  • ANSIBLE_GALAXY_CLI_COLLECTION_OPTS passes additional command-line options to the ansible-galaxy command that the build process runs. For example, you can add the --pre option if you want to install prerelease versions of collections.

  • EE_BASE_IMAGE specifies the parent image for the execution environment.

  • EE_BUILDER_IMAGE specifies the image used for compiling tasks.

build_arg_defaults:
  EE_BASE_IMAGE: registry.redhat.io/ansible-automation-platform-22/ee-minimal-rhel8:latest
  EE_BUILDER_IMAGE: registry.redhat.io/ansible-automation-platform-22/ansible-builder-rhel8:latest

The current build arguments are hard coded into the Containerfile file when you use the ansible-builder create command to generate that file.

Modifying the Containerfile File

After running the ansible-builder create command, you can navigate to the context/ directory and modify the Containerfile file to adapt it to your needs.

For example, you could add the following two directives in the Containerfile file to inject a private CA's certificate into the image:

ARG EE_BASE_IMAGE=registry.redhat.io/ansible-automation-platform-22/ee-minimal-rhel8:latest
ARG EE_BUILDER_IMAGE=registry.redhat.io/ansible-automation-platform-22/ansible-builder-rhel8:latest

FROM $EE_BASE_IMAGE as galaxy
ARG ANSIBLE_GALAXY_CLI_COLLECTION_OPTS=
USER root

COPY my-company-ca.pem /etc/pki/ca-trust/source/anchors
RUN update-ca-trust

ADD _build/ansible.cfg ~/.ansible.cfg
...output omitted...

For this example, you would place the my-company-ca.pem certificate file in the context/ directory.

Building the Execution Environment Image

When ready to build the container image, you manually execute the second stage by running the podman build command.

[user@host demo]$ podman build -f context/Containerfile -t ee-demo:v2.0 context
STEP 1: FROM registry.redhat.io/ansible-automation-platform-22/ee-minimal-rhel8:latest AS galaxy
STEP 2: ARG ANSIBLE_GALAXY_CLI_COLLECTION_OPTS=
--> 5894c40a543
STEP 3: USER root
--> 913568f77bb
STEP 4: COPY my-company-ca.pem /etc/pki/ca-trust/source/anchors
--> b9c4d7eaad0
STEP 5: RUN update-ca-trust
--> be65558ebb8
STEP 6: ADD _build/ansible.cfg ~/.ansible.cfg
--> 4a5410ba1c2
...output omitted...
STEP 22: COMMIT ee-demo:v2.0
--> 8be47093daa
8be47093daaae18160468f3db6e0335d55d0d11c838c7e285d74037e4a31d8a9
[user@host demo]$ podman images
REPOSITORY                       TAG     IMAGE ID      CREATED         SIZE
localhost/ee-demo                v2.0    ba77b0d0a59d  2 minutes ago   308 MB
...output omitted...

Revision: do374-2.2-82dc0d7