How to Install Ansible AWX on Kubernetes Cluster

In this post, we will show you how to install Ansible AWX on Kubernetes (k8s) cluster step by step.

Ansible AWX is a powerful open-source tool for managing and automating IT infrastructure. AWX provides a graphical user interface for Ansible, allowing you to easily create, schedule, and run Ansible playbooks.

Kubernetes, on the other hand, is a popular container orchestration platform that is widely used for deploying and managing containerized applications.

Prerequisites

  • Kubernetes cluster
  • Kubectl
  • A regular user with sudo rights and cluster admin rights
  • Internet connectivity

Step :1 Install helm

In case you, helm is installed on your system then run beneath commands to install,

$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
$ chmod +x get_helm.sh
$ ./get_helm.sh
$ helm version

Install-helm-linux-command-line

Step 2: Install the AWX chart

The easiest way to install AWX on Kubernetes is by using the AWX Helm chart. So, to install AWX via chart, first add its repository using following helm command.

$ helm repo add awx-operator https://ansible.github.io/awx-operator/
"awx-operator" has been added to your repositories
$

Note: If you had already added this repository before, then run beneath command to get latest version of packages.

$ helm repo update

To install awx-operator via chart, run

$ helm install ansible-awx-operator awx-operator/awx-operator -n awx --create-namespace

helm-install-awx-operator-kubernetes

This will download the AWX chart and install it on your Kubernetes cluster in awx namespace.The installation process may take a few minutes, so be patient.

Step 3: Verify AWX operator installation

After the successful installation, you can verify AWX operator status by running below command

$ sudo kubectl get pods -n awx

You should see something like this:

awx-operator-pod-status-kubectl

Step:4 Create PV, PVC and deploy AWX yaml file

AWX requires persistent volume for postgres pod. So, let’s first create a storage class for local volume

Note: In this post, I am using local file system as persistent volume.

$ vi local-storage-class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
  namespace: awx
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

Save and close the file and then run ,

$ kubectl create -f local-storage-class.yaml
$ kubectl get sc -n awx
NAME            PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   
local-storage   kubernetes.io/no-provisioner   Delete          WaitForFirstConsumer   false                 
$

Next create persistent volume(pv) using following pv.yaml file,

$ vi pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgres-pv
  namespace: awx
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/storage
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-worker

Save & exit the file.

Postgres-pv-awx-kubernetes

Important note : Make sure folder “/mnt/storage” exists on worker node, if it does not exist then create it using mkdir command on worker node. In our case worker node is “k8s-worker”

Execute the beneath command to create postgres-pv in awx namespace.

$ kubectl create -f pv.yaml

Once pv is created successfully then create persistentvolumecliam using pvc.yaml file,

$ vi  pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-13-ansible-awx-postgres-13-0
  namespace: awx
spec:
  storageClassName: local-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

posgres-pvc-awx-kubernetes

To create pvc, run following kubectl command

$ kubectl create -f pvc.yaml

Verify the status of pv and pvc using beneath command

$ kubectl get pv,pvc -n awx

Now, we are all set to deploy AWX instance. Create an ansible-awx.yaml file with following content

$ vi ansible-awx.yaml
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
  name: ansible-awx
  namespace: awx
spec:
  service_type: nodeport
  postgres_storage_class: local-storage

Ansible-awx-yaml-file

save and close the file.

Execute following kubectl command to deploy awx instance,

$ kubectl create -f ansible-awx.yaml

Wait for couple of minutes and then check pods status in awx namespace.

$ kubectl get pods -n awx

Ansible-AWX-Pods-Status-Kubernetes

Step 5: Access AWX Web Interface

To access the AWX web interface, you need to create a service that exposes the awx-web deployment:

$ kubectl expose deployment ansible-awx-web --name ansible-awx-web-svc --type NodePort -n awx

This command will create a NodePort service that maps the AWX web container’s port to a port on the Kubernetes node. You can find the port number by running:

$ kubectl get svc ansible-awx-web-svc  -n awx

This will output something like this:

NAME                 TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
ansible-awx-web-svc   NodePort   10.99.83.248   <none>        8052:32254/TCP   82s

In this example, the web service is available on port 32254.

Expose-Ansible-AWX-Web-NodePort-Kubernetes

By default, the admin user is admin for web interface and the password is available in the <resourcename>-admin-password secret. To retrieve the admin password, run

$ kubectl get secrets -n awx | grep -i admin-password
ansible-awx-admin-password        Opaque               1      109m
$
$ kubectl get secret ansible-awx-admin-password -o jsonpath="{.data.password}" -n awx | base64 --decode ; echo
l9mWcIOXQhSKnzZQyQQ9LZf3awDV0YMJ
$

You can now access the AWX web interface by opening a web browser and navigating to `http://<node-ip>:<node-port>/`. In the example above, the URL would be

http://192.168.1.223:3225

AWX-Login-URL-Kubernetes

Click on Log In after entering the credentials.

Ansible-AWX-Web-Dashboard

Congratulations! You have successfully installed Ansible AWX on Kubernetes. You can now use AWX to automate your IT infrastructure and make your life as a sysadmin easier.

21 thoughts on “How to Install Ansible AWX on Kubernetes Cluster”

  1. I wanted to take a moment to express my gratitude for your comprehensive guide on setting up AWX on Kubernetes. Your clear instructions and detailed explanations have been invaluable in helping me to understand and successfully deploy AWX in my Kubernetes environment.

    Reply
  2. unfortunately, if I try to create the storageclass as you described, it breaks with this error:

    error: error parsing storageclass.yaml: error converting YAML to JSON: yaml: line 5: mapping values are not allowed in this context

    Reply
  3. It’s just a typo; it should be this:
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
    name: local-storage
    namespace: awx
    provisioner: kubernetes.io/no-provisioner
    volumeBindingMode: WaitForFirstConsumer

    Reply
      • Thanks for posting this. I was able to deploy AWX to my local Rancher Kubernetes setup.

        I chose to use longhorn for storage, so I had to do things a bit differently.

        apiVersion: v1
        kind: PersistentVolumeClaim
        metadata:
        name: ansible-awx-projects
        namespace: awx
        spec:
        accessModes:
        – ReadWriteOnce
        storageClassName: longhorn
        resources:
        requests:
        storage: 1Gi

        and then configured the internal Postgres limits:

        apiVersion: awx.ansible.com/v1beta1
        kind: AWX
        metadata:
        name: ansible-awx
        namespace: awx
        spec:
        postgres_resource_requirements:
        requests:
        cpu: 500m
        memory: 2Gi
        limits:
        cpu: ‘1’
        memory: 4Gi
        postgres_storage_requirements:
        requests:
        storage: 10Gi
        limits:
        storage: 50Gi
        postgres_storage_class: longhorn
        postgres_extra_args:
        – ‘-c’
        – ‘max_connections=1000’
        projects_persistence: true
        projects_existing_claim: ansible-awx-projects

        Reply
  4. This helm install path no longer works.
    helm install ansible-awx-operator awx-operator/awx-operator -n awx –create-namespace
    Error: INSTALLATION FAILED: Kubernetes cluster unreachable: Get “http://localhost:8080/version”: dial tcp [::1]:8080: connect: connection refused

    Reply
    • Hi Marshall,

      It seems like Kubernetes cluster is not reachable from the system on which you are trying run helm command. So, please try to fix connectivity issue first.

      Reply
  5. I followed this post, but failed in step 4:
    kubectl get pvc -n awx
    NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
    postgres-13-ansible-awx-postgres-13-0 Pending local-storage 7m
    kubectl get pods -n awx
    NAME READY STATUS RESTARTS AGE
    ansible-awx-postgres-13-0 0/1 Pending 0 2m19s
    awx-operator-controller-manager-846fdb76d5-m5mbf 2/2 Running 4 (47m ago) 49m

    Reply
    • Hello,

      If you copied the exact commands, your PV configuration will be incorrect. Make sure the hostname matches the nodeaffinity. You can run this command to verify: kubectl get nodes –show-labels. Your server hostname is most likely not what the OP has posted.

      Reply
  6. I followed this post, but failed in step 4:

    [root@awxtest01 ~]# kubectl get pvc -n awx
    NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
    postgres-13-ansible-awx-postgres-13-0 Pending local-storage 40m
    [root@awxtest01 ~]#

    [root@awxtest01 ~]# kubectl describe postgres-13-ansible-awx-postgres-13-0
    error: the server doesn’t have a resource type “postgres-13-ansible-awx-postgres-13-0”
    [root@awxtest01 ~]# kubectl describe pvc postgres-13-ansible-awx-postgres-13-0 -n awx
    Name: postgres-13-ansible-awx-postgres-13-0
    Namespace: awx
    StorageClass: local-storage
    Status: Pending
    Volume:
    Labels:
    Annotations:
    Finalizers: [kubernetes.io/pvc-protection]
    Capacity:
    Access Modes:
    VolumeMode: Filesystem
    Used By: ansible-awx-postgres-13-0
    Events:
    Type Reason Age From Message
    —- —— —- —- ——-
    Normal WaitForFirstConsumer 39m (x11 over 41m) persistentvolume-controller waiting for first consumer to be created before binding
    Normal WaitForPodScheduled 80s (x151 over 38m) persistentvolume-controller waiting for pod ansible-awx-postgres-13-0 to be scheduled

    Please suggest, thanks in advance

    Reply
  7. Thank for a very clear step-by-step instruction, I have followed it for the latest version and seems everything running. However, I have noticed two svc created:

    service/ansible-awx-service NodePort xxxxxxxx 80:31560/TCP 16m
    service/ansible-awx-web-svc NodePort xxxxxxx 8052:32490/TCP 14m

    which node-port should I used for the URL? I have tried both but neither of them responds, any suggestion to troubleshooting it?

    Reply
  8. i have followed the all the steps and all of my resources are running perfectly but still the AWX console dont come up…

    FYI:- i am using k3s (rancher lightweight Kubernetes)

    dont know what is going wrong 🙁

    Reply
  9. I have been exploring ansible solutions to create all AWX-related config via ansible, like inventory, jobs, etc. Is there a way to do this via the helm chart, so I can configure this at startup? I have left-over ansible tasks that create all of this, but I was hoping there’s a more “kubernetes”-way to do this (i.e. config via helm chart specs)…

    Reply
  10. Hi,
    Thank you for the excellent guide!

    When I deploy AWX instance ansible-aws-task and ansible-aws-web getting failed and status is “CrashLoopBackoff”

    ambi@kube-master:~/awx$ kubectl get pods -n awx
    NAME READY STATUS RESTARTS AGE
    ansible-awx-postgres-13-0 1/1 Running 0 2m39s
    ansible-awx-task-8567b4d6d5-htrz8 0/4 Init:CrashLoopBackOff 4 (39s ago) 2m18s
    ansible-awx-web-6766ddb5c8-8xk25 1/3 CrashLoopBackOff 2 (13s ago) 16s
    awx-operator-controller-manager-6569d67f4c-nqtmh 2/2 Running 0 114m
    ambi@kube-master:~/awx$

    —————–
    describe pod shows following logs

    Events:
    Type Reason Age From Message
    —- —— —- —- ——-
    Normal Scheduled 99s default-scheduler Successfully assigned awx/ansible-awx-task-8567b4d6d5-htrz8 to kube-worker
    Normal Pulled 2s (x5 over 99s) kubelet Container image “quay.io/ansible/awx-ee:latest” already present on machine
    Normal Created 2s (x5 over 99s) kubelet Created container init
    Normal Started 1s (x5 over 99s) kubelet Started container init
    Warning BackOff 1s (x9 over 97s) kubelet Back-off restarting failed container init in pod ansible-awx-task-8567b4d6d5-htrz8_awx(a0c528db-ec4a-4ced-9dca-9bd3004fa782)
    ==================
    Cannot really find what’s going on in the logs

    le-awx”,”namespace”:”awx”,”error”:”exit status 2″,”stacktrace”:”github.com/operator-framework/ansible-operator-plugins/internal/ansible/runner.(*runner).Run.func1\n\tansible-operator-plugins/internal/ansible/runner/runner.go:269″}
    {“level”:”error”,”ts”:”2024-01-03T14:07:45Z”,”msg”:”Reconciler error”,”controller”:”awx-controller”,”object”:{“name”:”ansible-awx”,”namespace”:”awx”},”namespace”:”awx”,”name”:”ansible-awx”,”reconcileID”:”e9b8d090-4f0d-444c-91d0-4f3528f5e6e3″,”error”:”event runner on failed”,”stacktrace”:”sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\t/home/runner/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:329\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/home/runner/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:274\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2\n\t/home/runner/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:235″}
    =================
    Could anyone please help me, Thank You!

    Reply
  11. I was able to go through all the steps but i mm getting an error on my ansible-awx-web pod. It gives a status of CrashLoopBackOff and when i look at the logs the error says psycopg.OperationalError: connection failed: password authentication failed for user “awx”
    How can I fix my yaml to solve this error?

    Reply
  12. After running this step
    $ kubectl create -f ansible-awx.yaml
    i get errror when create container” Warning FailedMount 6s (x7 over 37s) kubelet MountVolume.NewMounter initialization failed for volume “postgres-pv” : path “/mnt/storage” does not exist”
    How can I fix my yaml to solve this error?

    Reply

Leave a Comment