Ansible AWX with minikube on Ubuntu 24.04

As I’m getting more into Ansible, I thought I’d try out AWX, one of the open-source upstream projects for Red Hat Ansible Automation Platform. In this post, I’ll show you how I installed it and got it up and running.

Ansible AWX gives you a Web UI, REST API, task engine, role-based access controls, and more. It’s best to deploy it via AWX Operator in a Kubernetes cluster. I’m still learning Kubernetes, so I went with minikube for a single node instance.

Overview

I’ve put together a basic diagram to show you how the architecture for deploying an AWX demo application works:

               +-------------------------------+
               |        Ubuntu Server          |
               |  (Running minikube Cluster)   |
               +-------------------------------+
                               |
                      +-------------------+
                      |    minikube       |
                      |  (Kubernetes      |
                      |  Single-Node)     |
                      +-------------------+
                              |
                   +------------------------+
                   | Kubernetes Namespace:  |
                   |     ansible-awx        |
                   +------------------------+
                              | 
                 +----------------------------+
                 |      AWX Operator Pod      |
                 | (Controller for deploying  |
                 |   and managing AWX)        |
                 +----------------------------+
                             |
    +---------------------------------------------------+
    |        AWX Resources (Deployed by AWX Operator    |
    |          in `ansible-awx` Namespace):             |
    |                                                   |
    +-------------+    +-------------+    +-------------+
    |             |    |             |    |             |
    |   AWX Web   |    |   AWX Task  |    | PostgreSQL  |
    |    Pod      |    |     Pod     |    |  DB Pod     |
    +-------------+    +-------------+    +-------------+
    | Service for |    | Runs AWX    |    | Storage for |
    | AWX UI and  |<-->| tasks and   |<-->| Data        |
    | API         |    | jobs        |    |             |
    +-------------+----+-------------+----+-------------+
  • Ubuntu Server: This is the virtual server running Ubuntu, which is hosting the minikube cluster.
  • minikube: Provides an isolated single-node Kubernetes cluster via Docker.
  • Kubernetes Namespace: Used to group all AWX-related resources together, which are managed by the AWX Operator.
  • AWX Operator: It’s a Kubernetes controller that handles deploying and managing the AWX application components (like AWX Web and the PostgreSQL database).
  • AWX Web Pod: This pod is where you’ll find the AWX web interface and API, which provide the user-facing interface.
  • AWX Task Pod: This pod is in charge of running tasks and jobs, and it handles all the automation tasks.
  • PostgreSQL Database: The PostgreSQL pod is where you’ll find the AWX data, like project settings, inventory lists and job results.

Installation Guide

Resources

  • CPU: 2 vCPUs
  • RAM: 8GB
  • Storage: 25GB

Software Versions

  • OS: Ubuntu 24.04 LTS
  • Docker: 27.3.1
  • minikube: 1.34.0
  • Ansible - AWX Operator: 2.19.1
  • Ansible - AWX: 24.6.1

Update System

  • The first thing to do is to get the latest version of the package list and then upgrade the system packages:
    sudo apt update && sudo apt -y upgrade
    
  • Make sure you check if a reboot is needed and if so, go ahead and do it:
    [ -f /var/run/reboot-required ] && sudo reboot
    

Install Prerequisite Packages

  • git for cloning the AWX Operator repository.
  • make to create AWX Operator.
  • ca-certificates needed for Docker.
  • curl to download installation resources.
sudo apt install git make ca-certificates curl

Docker

  • Install latest Docker version
    Add Docker’s Official GPG Key
    sudo install -m 0755 -d /etc/apt/keyrings
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    sudo chmod a+r /etc/apt/keyrings/docker.asc
    
    Add the Repository to apt sources
    echo \
    "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
    $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
    sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
    Install Docker
    sudo apt-get update
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    
    Verify installation

    sudo docker run hello-world

Allow Default User to Use Docker

Just run the command in your user shell, and you’ll create the Docker group, and also add your current user to it:
sudo usermod -aG docker $USER && newgrp docker

minikube

  • minikube Documentation
    Download & Install
    curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
    sudo install minikube-linux-amd64 /usr/local/bin/minikube && rm minikube-linux-amd64
    
    Start minikube

    The following command is run as the default user, and not with sudo or root permissions

    minikube start --vm-driver=docker
    
    😄  minikube v1.34.0 on Ubuntu 24.04 (kvm/amd64)
    ✨  Using the docker driver based on user configuration
    📌  Using Docker driver with root privileges
    👍  Starting "minikube" primary control-plane node in "minikube" cluster
    🚜  Pulling base image v0.0.45 ...
    💾  Downloading Kubernetes v1.31.0 preload ...
      > preloaded-images-k8s-v18-v1...:  326.69 MiB / 326.69 MiB  100.00% 15.21 M
      > gcr.io/k8s-minikube/kicbase...:  487.90 MiB / 487.90 MiB  100.00% 20.71 M
    🔥  Creating docker container (CPUs=2, Memory=2200MB) ...
    🐳  Preparing Kubernetes v1.31.0 on Docker 27.2.0 ...
      ▪ Generating certificates and keys ...
      ▪ Booting up control plane ...
      ▪ Configuring RBAC rules ...
    🔗  Configuring bridge CNI (Container Networking Interface) ...
    🔎  Verifying Kubernetes components...
      ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
    🌟  Enabled addons: default-storageclass, storage-provisioner
    💡  kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'
    🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
    

Install kubectl

You can also use minikube kubectl -- <kubectl command> for kubectl commands. I still installed it as a standalone tool because you can use it for other Kubernetes clusters too, and that’s how it’s typically used in real-world scenarios.

The following commands are run with root permissions

sudo su
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

Verify minikube

minikube status

minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Verify Kubernetes Version, Node and Pod Status and Cluster Info

kubectl cluster-info

Kubernetes control plane is running at https://192.168.49.2:8443
CoreDNS is running at https://192.168.49.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

kubectl get node

NAME       STATUS   ROLES           AGE     VERSION
minikube   Ready    control-plane   2m24s   v1.31.0

kubectl get pods -A

NAMESPACE     NAME                               READY   STATUS    RESTARTS        AGE
kube-system   coredns-6f6b679f8f-8n7rm           1/1     Running   1 (2m31s ago)   2m46s
kube-system   etcd-minikube                      1/1     Running   0               2m51s
kube-system   kube-apiserver-minikube            1/1     Running   0               2m51s
kube-system   kube-controller-manager-minikube   1/1     Running   0               2m51s
kube-system   kube-proxy-4ml7r                   1/1     Running   0               2m47s
kube-system   kube-scheduler-minikube            1/1     Running   0               2m53s
kube-system   storage-provisioner                1/1     Running   0               2m32s

Ansible - AWX & Operator

AWX Operator

We’re going to roll out AWX using AWX Operator, so we are going to get that up and running first.

No need for root permissions or sudo here, just use your default user. Once we’ve cloned the repository, we’re using curl to get the latest version number from GitHub:

git clone https://github.com/ansible/awx-operator.git
cd awx-operator/

RELEASE_TAG=`curl -s https://api.github.com/repos/ansible/awx-operator/releases/latest | grep tag_name | cut -d '"' -f 4`
echo $RELEASE_TAG
git checkout $RELEASE_TAG

Next, we choose which Kubernetes namespace we want to use for AWX and then run the Makefile:

export NAMESPACE=ansible-awx
make deploy
namespace/ansible-awx created
customresourcedefinition.apiextensions.k8s.io/awxbackups.awx.ansible.com created
customresourcedefinition.apiextensions.k8s.io/awxmeshingresses.awx.ansible.com created
customresourcedefinition.apiextensions.k8s.io/awxrestores.awx.ansible.com created
customresourcedefinition.apiextensions.k8s.io/awxs.awx.ansible.com created
serviceaccount/awx-operator-controller-manager created
role.rbac.authorization.k8s.io/awx-operator-awx-manager-role created
role.rbac.authorization.k8s.io/awx-operator-leader-election-role created
clusterrole.rbac.authorization.k8s.io/awx-operator-metrics-reader created
clusterrole.rbac.authorization.k8s.io/awx-operator-proxy-role created
rolebinding.rbac.authorization.k8s.io/awx-operator-awx-manager-rolebinding created
rolebinding.rbac.authorization.k8s.io/awx-operator-leader-election-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/awx-operator-proxy-rolebinding created
configmap/awx-operator-awx-manager-config created
service/awx-operator-controller-manager-metrics-service created
deployment.apps/awx-operator-controller-manager created

With the following command, we can now see that the AWX Operator pod is being created: kubectl get pods -n ansible-awx

NAME                                               READY   STATUS              RESTARTS        AGE
awx-operator-controller-manager-687b856498-q8xxk   0/2     ContainerCreating   0               88s

AWX

The next command creates a Kubernetes AWX custom resource that informs the AWX Operator to deploy an AWX instance named awx-demo. The AWX Operator, which is already running, monitors the Kubernetes API for changes. When it detects the creation of this new resource, it takes over to manage the deployment process.
kubectl create -f awx-demo.yml -n ansible-awx

It might take a little while for everything to be fully operational.

You can keep an eye on the progress with this command:
The output is refreshed when a new pod is launched or a status changes.

kubectl get pods -l "app.kubernetes.io/managed-by=awx-operator" -n ansible-awx -w
NAME                            READY   STATUS              RESTARTS   AGE
awx-demo-postgres-15-0          1/1     Running             0          2m28s
awx-demo-task-cd65fd874-djjvq   0/4     Init:0/2            0          4s
awx-demo-web-78d8f9bbdd-zgk7v   0/3     ContainerCreating   0          7s
awx-demo-task-cd65fd874-djjvq   0/4     Init:0/2            0          3m3s
awx-demo-web-78d8f9bbdd-zgk7v   3/3     Running             0          3m8s
awx-demo-migration-24.6.1-phcx2   0/1     Pending             0          0s
awx-demo-migration-24.6.1-phcx2   0/1     Pending             0          0s
awx-demo-migration-24.6.1-phcx2   0/1     ContainerCreating   0          0s
awx-demo-migration-24.6.1-phcx2   1/1     Running             0          4s

You can also check the installation logs to see how things are going:

kubectl logs awx-operator-controller-manager-687b856498-q8xxk -n ansible-awx -f

You can exit both by pressing CTRL+C.

Verify deployment

kubectl get pods -n ansible-awx

NAME                                               READY   STATUS      RESTARTS       AGE
awx-demo-migration-24.6.1-phcx2                    0/1     Completed   0              9m54s
awx-demo-postgres-15-0                             1/1     Running     0              17m
awx-demo-task-cd65fd874-djjvq                      4/4     Running     0              15m
awx-demo-web-78d8f9bbdd-zgk7v                      3/3     Running     0              15m
awx-operator-controller-manager-687b856498-q8xxk   1/2     Running     5 (104s ago)   23m

We can now take a look at the IP addresses and ports that are being used for these pods: kubectl get svc -n ansible-awx

NAME                                              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
awx-demo-postgres-15                              ClusterIP   None             <none>        5432/TCP       18m
awx-demo-service                                  NodePort    10.108.237.214   <none>        80:32596/TCP   16m
awx-operator-controller-manager-metrics-service   ClusterIP   10.99.79.207     <none>        8443/TCP       24m

Access AWX Web UI

  • You can access the AWX dashboard directly from your machine where minikube is running. To get the URL, just use this command:
    minikube service awx-demo-service --url -n ansible-awx
    If you use this command, you’ll get more details:
    minikube service list -n ansible-awx
    |-------------|-------------------------------------------------|--------------|---------------------------|
    |  NAMESPACE  |                      NAME                       | TARGET PORT  |            URL            |
    |-------------|-------------------------------------------------|--------------|---------------------------|
    | ansible-awx | awx-demo-postgres-15                            | No node port |                           |
    | ansible-awx | awx-demo-service                                | http/80      | http://192.168.49.2:32596 |
    | ansible-awx | awx-operator-controller-manager-metrics-service | No node port |                           |
    |-------------|-------------------------------------------------|--------------|---------------------------|
    

External Access
In production, we’d probably use Ingress to get access from our network to the AWX web UI, but in a test environment we can simply use port forwarding with kubectl:

kubectl port-forward service/awx-demo-service -n ansible-awx --address 0.0.0.0 10445:80 &> /dev/null &
  • You can access it via your browser:
    http://<ip-address-ubuntu-vm>:10445/#/login

Note: If you reboot the Ubuntu VM or restart the minikube Docker container, the port forwarding will be lost because kubectl port-forward only establishes a temporary network tunnel.

Get AWX admin Password
  • To get the password for the admin user, we just need to run this command:
    kubectl get secret awx-demo-admin-password -o jsonpath="{.data.password}" -n ansible-awx | base64 --decode; echo
    

This is the AWX dashboard with the current tech preview of the user interface:
AWX Web UI - Dashboard


Resources