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: