11. 09. 2024 Davide Gallo Contribution, Development, DevOps

Ansible Development, Part 1: Building an Execution Environment

Right now, at Würth Phoenix, we are investing in automating most of our operations using Ansible. You’re probably already familiar with what Ansible does, but to summarize, Ansible is an open-source, command-line IT automation application written in Python. I’ve talked about it here:

One challenge we faced while developing our automation scripts was that we needed to install several Python dependencies, which often conflicted with those already installed on the controller machine. While we could use virtual environments (venvs), they’re not a rock-solid solution in my opinion.

The Ansible team was aware of this issue, and for this reason they created ansible-builder. Ansible-builder is a tool that lets you create a container image with everything you need to start using Ansible in your environment, formerly known as Ansible Execution Environment.

I’ll be writing several blog posts about my journey with Ansible, so I think it’s a good idea to start with a guide explaining how to create the environment that we’ll use in future posts.

Sources

Use Case

I want to have a container with all Ansible and Python requirements to run my automation scripts. For example, I want to be able to use Kerberos authentication to manage my Windows hosts.

Requirements

  • A Linux-based server (I suggest Rocky). This machine will be used to develop and/or execute our automation scripts
  • Python >= 3.11
  • Podman

Steps

Installing the developer tools

We need to install the Ansible Development Tools (ADT) suite. This suite contains many powerful utilities to help you write your automation scripts and test them. For now, we’ll use only the ansible-builder tool. Please follow the install instructions here.

Please note that it will also install ansible-core!

You can use this development server to run your automation scripts without any problem, since they will run inside a container with possibly both a separate ansible-core version and Python version.

Preparing our ansible-builder files

It’s not easy to find information on how to use this suite, but luckily I found this well-written post: Ansible Execution Environment for the IBM ISVA Ansible collection | tom’s tips (gwbasics.be)

As the linked blog already goes into detail about how you’re expected to configure your files, I’ll just explain the steps to achieve our use case.

Create the project folder and files

mkdir ~/builder
cd ~/builder
mkdir configs

Inside the directory create the following files:

  • execution-environment.yml: Basically, our Dockerfile
  • bindep.txt: Contains the OS packages (python, krb5 packages, …)
  • python-requirements.txt: Contains all the Python libraries (pypsrp, pywinrm, kerberos,… )
  • galaxy-requirements.yml: Contains all the Ansible Galaxy collections we need (community.windows, ansible.windows, …)
  • ansible.cfg: Default ansible config file (optional)

In the configs/ folder we’ll put our Kerberos configurations.

execution-environment.yml

This is the most important file you need to configure. Here you define your base image (in our case Rocky), and you define how to interact with the other files we created previously.

Please note that we need some extra steps during the build as there’s a bug in the tool. I’ve added a link to the GitHub issue in the code.

---
version: 3

#Base image to use as our template
images:
  base_image:
    name: quay.io/rockylinux/rockylinux:9

#https://access.redhat.com/documentation/it-it/red_hat_ansible_automation_platform/2.1/html/ansible_builder_guide/assembly-using-builder
dependencies:
  python_interpreter:
    package_system: python3.9
    python_path: /usr/bin/python3.9
  ansible_core:
    package_pip: ansible-core~=2.15
  ansible_runner:
    package_pip: ansible-runner~=2.3
  system: bindep.txt
  python: python-requirements.txt
  galaxy: galaxy-requirements.yml

additional_build_files:
  - src: ansible.cfg
    dest: configs
  - src: configs/krb5.conf
    dest: configs


#https://github.com/ansible/ansible-builder/issues/628
additional_build_steps:
  prepend_base: |
    RUN dnf install -y epel-release python3 python3-pip git
  prepend_final:
    - COPY _build/configs/ansible.cfg /etc/ansible/ansible.cfg
    - COPY _build/configs/my-krb5.conf /etc/krb5.conf.d/my-krb5.conf


options:
  package_manager_path: /usr/bin/dnf
# This are needed if you want to run the container in Podman as root. Please, don't.
#  relax_passwd_permissions: true
#  user: root

bindep.txt

I added vim and rsync for my peace of mind, but if you want the bare minimum packages, then you don’t need to install them. You can always run dnf install inside the container if you need them temporarily.

gcc [platform:rpm]
python3-devel [platform:rpm]
krb5-devel [platform:rpm]
krb5-libs [platform:rpm]
krb5-workstation [platform:rpm]
vim [platform:rpm]
rsync [platform:rpm]

python-requirements.txt

pypsrp
pywinrm>=0.3.0
kerberos

galaxy-requirements.yml

---
collections:
  - community.windows
  - ansible.windows
  - ansible.utils
  - community.general
  - ansible.posix

Kerberos configuration

You can read more about it here: 24. User Authentication with Kerberos — Ansible Tower Administration Guide v3.8.6, but basically, you need a my-krb5.conf file with your AD Domain information. You can also decide to completely override the default krb5.conf inside the container.

[realms]
        FOO.BAR.LAN= {
          kdc = ad01.foo.bar.lan
          admin_server = ad01.foo.bar.lan
          master_kdc = ad01.foo.bar.lan
          kdc = ad02.foo.bar.lan
        }

[domain_realm]
        .foo.bar.lan = FOO.BAR.LAN
        foo.bar.lan = FOO.BAR.LAN

Build the container image

Just run ansible-builder and see the magic happen 🙂

If you want to give a name to the image you can use the parameter -t MYNAME

If you want to use this image elsewhere, you can export it using: podman save -o MYNAME.tar localhost/MYNAME:latest

To import it into your target machine, use instead: podman load -i MYNAME.tar

Run the container

Now here’s where it gets a little bit complicated. Basically, you have three choices:

Explaining the first 2 tools requires writing another blog post, so I’ll cut it short here and just run Podman myself. The folder ansible-project/ is where you’ll have your inventories, playbooks and everything else you need to run your automation scripts.

podman run --rm -ti -v ~/ansible-project:/runner/:Z localhost/MYNAME /bin/sh

Now that you’re inside the container, just move to /runner and execute ansible-playbook. Enjoy!

These Solutions are Engineered by Humans

Did you find this article interesting? Are you an “under the hood” kind of person? We’re really big on automation and we’re always looking for people in a similar vein to fill roles like this one as well as other roles here at Würth Phoenix.

Davide Gallo

Davide Gallo

Site Reliability Engineer at Würth Phoenix

Author

Davide Gallo

Leave a Reply

Your email address will not be published. Required fields are marked *

Archive