Welcome to our guide on how to install Ansible AWX on CentOS 7 / RHEL 7 using Kubernetes k3s distribution. If you have a separate Kubernetes cluster the installation process should just work fine. In this setup we shall use the operator meant to provide a more Kubernetes-native installation method for AWX via an AWX Custom Resource Definition (CRD).
What is AWX?
AWX is the upstream project from which the Red Hat Ansible Tower which provides a web-based user interface, REST API, and task engine built on top of Ansible. It is the upstream project for Tower, a commercial derivative of AWX. This is an open source community project, sponsored by Red Hat, that enables users to better control their Ansible project use in IT environments. The AWX source code is available under the Apache License 2.0.
Install Ansible AWX on CentOS 7 / RHEL 7
We have some setup requirements to run Ansible AWX on CentOS 7 / RHEL 7 Linux system.
- Kubernetes Cluster / Docker
- CentOS 7 / RHEL 7 server
- User with sudo access
- Minimum of 8GB of RAM – if you have more memory the better
- Minimum of 4vcpus
- 25GB minimum disk space
Step 1: Disable SELinux and firewalld
Let’s ensure our system is updated.
sudo yum -y update
Once the update is successful perform a system reboot
sudo reboot
Disable SELinux or put it in permissive mode to ensure no issues are experienced during the deployment:
sudo setenforce 0
sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config
cat /etc/selinux/config | grep SELINUX=
Disable Firewalld since it’s a recommendation by K3s.
sudo systemctl disable firewalld --now
Step 2: Install K3s Kubernetes Distribution
All recent releases of AWX can run as a containerized application using Docker images deployed on Kubernetes, OpenShift cluster, or using docker-compose. In this guide we shall focus on the installation of Ansible AWX on CentOS 7 / RHEL 7 using k3s Kubernetes distribution.
But first we need to install k3s. This can be done by running the commands below in your terminal.
curl -sfL https://get.k3s.io | sudo bash -
sudo chmod 644 /etc/rancher/k3s/k3s.yaml
After installation check the status of k3s service.
$ systemctl status k3s.service
● k3s.service - Lightweight Kubernetes
Loaded: loaded (/etc/systemd/system/k3s.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2024-04-02 08:54:00 UTC; 5min ago
Docs: https://k3s.io
Process: 22104 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
Process: 22098 ExecStartPre=/sbin/modprobe br_netfilter (code=exited, status=0/SUCCESS)
Process: 22095 ExecStartPre=/bin/sh -xc ! /usr/bin/systemctl is-enabled --quiet nm-cloud-setup.service (code=exited, status=0/SUCCESS)
Main PID: 22107 (k3s-server)
Tasks: 35
Memory: 551.2M
CGroup: /system.slice/k3s.service
├─22107 /usr/local/bin/k3s server
└─22128 containerd -c /var/lib/rancher/k3s/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/k3s/agent/contain...
....
Copy Kubectl configuration.
mkdir ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
Test that your k3s installation works.
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
cent7.mylab.io Ready control-plane,master 6m2s v1.28.8+k3s1
Kubernetes server and client versions can be checked with the commands;
# kubectl version
Client Version: v1.28.8+k3s1
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.8+k3s1
Step 3: Deploy AWX Operator on k3s Kubernetes
Install git and make tools required in this setup.
sudo yum -y install jq git make tar
We’ll need to deploy Kubernetes Operator used to manage one or more AWX instances in any namespace. Clone deployment code from Github:
git clone https://github.com/ansible/awx-operator.git
Create namespace called awx where an operator and AWX instance will be deployed.
export NAMESPACE=awx
kubectl create ns ${NAMESPACE}
You can set current namespace as awx:
kubectl config set-context --current --namespace=awx
Navigate to the awx-operator directory:
cd awx-operator/
Get the latest version of AWX operator from AWX Operator releases and save as RELEASE_TAG variable.
RELEASE_TAG=`curl -s https://api.github.com/repos/ansible/awx-operator/releases/latest | grep tag_name | cut -d '"' -f 4`
echo $RELEASE_TAG
Checkout to the branch using git command:
git checkout $RELEASE_TAG
Deploy AWX Operator into your cluster with the make deploy
commands:
export NAMESPACE=awx
make deploy
Command execution terminal output:
namespace/awx configured
customresourcedefinition.apiextensions.k8s.io/awxbackups.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
Wait a few minutes and awx-operator should be running:
$ kubectl get pods -n awx
NAME READY STATUS RESTARTS AGE
awx-operator-controller-manager-557589c5f4-wm2h5 2/2 Running 0 42s
Step 4: Install AWX on CentOS 7 / RHEL 7 using operator
With the operator running we can proceed to deploy AWX instance in the cluster. But first create a PVC for data persistence in the cluster.
Create a file named public-static-pvc.yaml:
vi public-static-pvc.yaml
Paste and modify the contents below to your liking.
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: public-static-data-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 8Gi
Apply the settings with kubectl apply
commands:
$ kubectl apply -f public-static-pvc.yaml -n awx
persistentvolumeclaim/public-static-data-pvc created
Notice that the PVC won’t be bound at this time. A running Pod is needed for binding to be created.
$ kubectl get pvc -n awx
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
public-static-data-pvc Pending local-path 32s
Create AWX instance deployment YAML file contents:
vi awx-instance-deployment.yml
Paste below contents to the file created.
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
spec:
service_type: nodeport
projects_persistence: true
projects_storage_access_mode: ReadWriteOnce
web_extra_volume_mounts: |
- name: static-data
mountPath: /var/lib/projects
extra_volumes: |
- name: static-data
persistentVolumeClaim:
claimName: public-static-data-pvc
Deploy AWX on CentOS 7 / RHEL 7 Linux machine.
$ kubectl apply -f awx-instance-deployment.yml -n awx
awx.awx.ansible.com/awx created
Wait for the Pods status to change to running
$ kubectl get pods -l "app.kubernetes.io/managed-by=awx-operator" -n awx -w
NAME READY STATUS RESTARTS AGE
awx-postgres-0 1/1 Running 0 2m58s
awx-75698588d6-qz2gf 4/4 Running 0 2m42s
Logs of the deployment progress can be checked using commands shared below.
kubectl logs -f deployments/awx-operator-controller-manager -c awx-manager -n awx
Extra PVCs are created automatically during AWX deployment.
$ kubectl get pvc -n awx
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
postgres-awx-postgres-0 Bound pvc-c67f0695-fd13-4ca5-a742-7e85bdcdd05e 8Gi RWO local-path 3m42s
awx-projects-claim Bound pvc-af9d7b38-a508-46ae-ae22-8a74e612a33d 8Gi RWO local-path 2m45s
public-static-data-pvc Bound pvc-8162895a-ae35-4d3d-bb37-50edef756fbf 8Gi RWO local-path 6m42s
List of Pods created in awx namespace:
$ kubectl get pods -n awx
NAME READY STATUS RESTARTS AGE
awx-operator-controller-manager-566b76fc7f-bs9vm 2/2 Running 0 5m21s
awx-postgres-13-0 1/1 Running 0 3m36s
awx-task-6db4f4b44c-xgptx 4/4 Running 0 2m51s
awx-web-5fbfdb59c4-77x77 3/3 Running 0 99s
Step 5: How to Check AWX Container’s logs
The AWX will have below deployments.
- awx-web
- awx-task
- awx-operator-controller-manager
As can be seen from below command output:
$ kubectl get deploy -n awx
NAME READY UP-TO-DATE AVAILABLE AGE
awx-operator-controller-manager 1/1 1 1 9m19s
awx-task 1/1 1 1 6m52s
awx-web 1/1 1 1 6m
$ kubectl -n awx logs deploy/awx-web
...
2023-08-24 15:05:31,077 INFO success: nginx entered RUNNING state, process has stayed up for > than 30 seconds (startsecs)
2023-08-24 15:05:31,077 INFO success: nginx entered RUNNING state, process has stayed up for > than 30 seconds (startsecs)
2023-08-24 15:05:31,078 INFO success: uwsgi entered RUNNING state, process has stayed up for > than 30 seconds (startsecs)
2023-08-24 15:05:31,078 INFO success: uwsgi entered RUNNING state, process has stayed up for > than 30 seconds (startsecs)
2023-08-24 15:05:31,078 INFO success: daphne entered RUNNING state, process has stayed up for > than 30 seconds (startsecs)
2023-08-24 15:05:31,078 INFO success: daphne entered RUNNING state, process has stayed up for > than 30 seconds (startsecs)
2023-08-24 15:05:31,078 INFO success: awx-cache-clear entered RUNNING state, process has stayed up for > than 30 seconds (startsecs)
2023-08-24 15:05:31,078 INFO success: awx-cache-clear entered RUNNING state, process has stayed up for > than 30 seconds (startsecs)
2023-08-24 15:05:31,078 INFO success: ws-heartbeat entered RUNNING state, process has stayed up for > than 30 seconds (startsecs)
2023-08-24 15:05:31,078 INFO success: ws-heartbeat entered RUNNING state, process has stayed up for > than 30 seconds (startsecs)
Specify the name of the container for which you need to check its logs.
kubectl -n awx logs deploy/<deployment> -c <container>
Or use:
kubectl -n awx logs pod/<podName> -c <containerName>
List all Pods
$ kubectl get pod -n awx
NAME READY STATUS RESTARTS AGE
awx-operator-controller-manager-564f8dc4fc-wspln 2/2 Running 0 12m
awx-postgres-13-0 1/1 Running 0 10m
awx-task-84ff8bcf7b-2ddv4 4/4 Running 0 10m
awx-web-799d8f444f-kfzvl 3/3 Running 0 9m22s
List containers in each pod.
$ kubectl -n awx get pod awx-web-799d8f444f-kfzvl -o jsonpath='{.spec.containers[*].name}';echo
redis awx-web awx-rsyslog
$ kubectl -n awx get pod awx-task-84ff8bcf7b-2ddv4 -o jsonpath='{.spec.containers[*].name}';echo
redis awx-task awx-ee awx-rsyslog
Step 6: Accessing AWX Pod container shell
Commands used to check the logs of each container. See examples below.
kubectl -n awx exec -ti deploy/awx-web -c redis -- /bin/bash
kubectl -n awx exec -ti deploy/awx-web -c awx-rsyslog -- /bin/bash
To get out of the shell, just type exit
bash-5.1$ exit
exit
Step 7: Access AWX Web Interface
Get the AWX Web service port:
$ kubectl get service -n awx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
awx-operator-controller-manager-metrics-service ClusterIP 10.43.151.146 <none> 8443/TCP 19m
awx-postgres-13 ClusterIP None <none> 5432/TCP 17m
awx-service NodePort 10.43.197.41 <none> 80:30614/TCP 16m
From the output we can confirm service node port is 30614. Access AWX web console using your k3s server IP address and service nodeport.
http://k3s-server-ip-address:<port-number>
Welcome to AWX page will be displayed.

The login username is admin with the password as output of the following command:
kubectl -n awx get secret awx-admin-password -o go-template='{{range $k,$v := .data}}{{printf "%s: " $k}}{{if not $v}}{{$v}}{{else}}{{$v | base64decode}}{{end}}{{"\n"}}{{end}}'
Sample output:
password: ZMXFxKxPpDq10iZDyZNhY2cBLxs32Ohu
Login with the admin username and decoded password from above commands:

Once the authentication is successful, you’ll get to AWX administration dashboard.

Therein, there is a lot of stuff to do. Take your time to explore and refer to official AWX documentation for detailed user guides.
Step 8: Configure Ingress for AWX
If you would like to access your AWX using domain names and SSL, check out our ingress articles:
- How To Expose Ansible AWX Service using Traefik Ingress route
- How To Expose Ansible AWX Service using Nginx Ingress
Step 9: How to Upgrade AWX instance on Kubernetes
Follow the guide in the following link to upgrade your AWX operator and instance deployed in a Kubernetes cluster.
Step 10: Uninstalling AWX Operator (Only for reference)
The operator and all associated CRDs can be uninstalled by running the commands below:
# export NAMESPACE=awx
# make undeploy
/root/awx-operator/bin/kustomize build config/default | kubectl delete -f -
namespace "awx" deleted
customresourcedefinition.apiextensions.k8s.io "awxbackups.awx.ansible.com" deleted
customresourcedefinition.apiextensions.k8s.io "awxrestores.awx.ansible.com" deleted
customresourcedefinition.apiextensions.k8s.io "awxs.awx.ansible.com" deleted
serviceaccount "awx-operator-controller-manager" deleted
role.rbac.authorization.k8s.io "awx-operator-leader-election-role" deleted
role.rbac.authorization.k8s.io "awx-operator-manager-role" deleted
clusterrole.rbac.authorization.k8s.io "awx-operator-metrics-reader" deleted
clusterrole.rbac.authorization.k8s.io "awx-operator-proxy-role" deleted
rolebinding.rbac.authorization.k8s.io "awx-operator-leader-election-rolebinding" deleted
rolebinding.rbac.authorization.k8s.io "awx-operator-manager-rolebinding" deleted
clusterrolebinding.rbac.authorization.k8s.io "awx-operator-proxy-rolebinding" deleted
configmap "awx-operator-manager-config" deleted
service "awx-operator-controller-manager-metrics-service" deleted
deployment.apps "awx-operator-controller-manager" deleted
Wrapping Up
To this point we have shown you how to install and use AWX on CentOS 7 / RHEL 7 Linux system. AWX is created to help teams, both small and large in management of complex multi-tier deployments by knowledge, adding control, and delegation to Ansible-powered environments.
Similar:
- Build AWS EC2 Machine Images (AMI) With Packer and Ansible
- Semaphore – Manage Ansible Tasks from A Web UI
Hi Josphat,
Any plans on updating this guide for k3s on ubuntu 20.04? Would love to see that working with let’s encrypt.
Thanks
We have on on k3s already but not with let’s encrypt. We’ll try a proper setup with ssl. https://computingforgeeks.com/how-to-install-ansible-awx-on-ubuntu-linux/
I did all the steps, but I can’t enter the gui, I have a login error:
error on gui:
There was a problem logging in. Please try again.
Thanks so much for this! This is great!
I wonder if you can help though? The only issue is, I can’t seem to run any templates with this build and now sure why. When I do, there is no output, like it didn’t even try anything – after a while if fails with no reason, the only thing that appears on the output screen is “Finished”, so not sure what the issue is. I’ve synced to my git repo for all the projects and templates, and they’re syncing fine. Its when I try and run any job/template against any of my inventory, it fails. Any vague ideas where I could start to find where the issue lies? All the pods and everything seem to be running OK.
Cheers!
Hi , thank you for the detailed steps , however the awx-service is up and running and the pods are up and running , i am unable to load the awx-web using the k3s ip and nodeport . it says
ERR_CONNECTION_TIMED_OUT
Hi
I follow all your steps and all works fine, very easy to follow. thanks.
All works fine but when I am trying to connect to bitbuket to get ansible playbooks .. I got this error.
I think is because AWX is runninb behind nginx proxy manager (to get the ssl certificate) and somehow is not able to redirect correctly.
Please share the error screenshot or logs so that we can help with troubleshooting the issue.
Hey, Josphat! Thanks for the tutorial.
I’m getting an error on “kubectl get pods -n awx” command.
My STATUS is “ImagePullBackOff”. Do you have an idea what i’m doing wrong?
This means you have an issue with container image download. Try deleting the pod and see if recreation will be successful. Also check network connectivity from node, you can try
docker pull hello-world
Hello,
After deploying awx the containers never initialize.
“Init:CrashLoopBackOff”
seems to be “Reconciler error” from logs
Hi Josphat,
Thanks for the tutorial and detailed steps.
pods creation failed with below status, can you please suggest.
awx-operator-controller-manager-57867569c4-d64jj 0/2 Error 1 39m
awx-operator-controller-manager-57867569c4-bkvxj 0/2 Error 1 31m
awx-operator-controller-manager-57867569c4-kfgpl 0/2 Completed 0 20m
awx-operator-controller-manager-57867569c4-2dcrd 0/2 Pending 0 6m11s
awx-operator-controller-manager-57867569c4-ll8rc 0/2 ContainerStatusUnknown 0 13m
awx-task-64d4ccd658-7rch5 0/4 Pending 0 15s
awx-web-8557cbbf77-cp8p2 0/3 Pending 0 15s
awx-postgres-13-0 0/1 Pending 0 15s
i am getting error: Error from server (NotFound): deployments.apps “awx” not found
when i run this command,
kubectl -n awx logs deploy/awx
You must have missed to deploy. Tested and it works fine.
Thanks for the steps
I have followed the steps and I can enter GUI of AWX
But it seems Ansible is not installed with AWX, so when I run playbook from AWX GUI, it always fails and when I CLI to AWX task pods and user ansible-playbook command, it reminds me Ansible is not installed
Can you shed some light how I can further install Ansible into AWX
Also the default user of AWX task pod is ‘awx’ but anywhere I can find the password of this user ?
Thanks for the nice instructions. I used them with Rocky Linux 9.1 and all seems to work. I also suggest you add tar to the yum install step. It’s needed for “make deploy” and I didn’t have it by default.
Great thanks for the tip.