Feedback

Chat Icon

AWX in Action

Ansible Orchestration at Scale

From Zero to AWX: A Kubernetes Install That Actually Works
20%

Deploying AWX on K3s With the Operator

There are several ways to install Ansible AWX. Starting from version 18, the preferred method is the AWX Operator. The easiest path, by contrast, is Docker and Docker Compose — but this isn't recommended for production and is only suitable for testing, since it has no official public release.

A Kubernetes operator is a controller that extends the Kubernetes API to manage an application's lifecycle. The AWX Operator handles installing, upgrading, scaling, and reconciling AWX instances on a cluster.

The operator install steps are in the official documentation. If you prefer Helm, there's also a community Helm chart for installing the operator on an existing cluster.

Production AWX runs on a multi-node, HA Kubernetes cluster. For learning, CI/CD, or smaller workloads, a single-node setup is enough and can be scaled out later. This guide uses a single-node K3s cluster — no HA, but the migration path to a real cluster stays open.

K3s is a lightweight, CNCF-certified Kubernetes distribution that installs in one command. Originally built for edge and IoT, it's a good fit for dev, CI, and small labs. More at k3s.io.

We'll install on the awx-1 node, following the steps from kurokobo's awx-on-k3s repository.

Start by disabling firewalld and nm-cloud-setup (if enabled) as required by K3s:

# Disable firewalld only if it's running.
systemctl is-active --quiet firewalld && systemctl disable firewalld --now

# Disable nm-cloud-setup only if its service or timer is running.
systemctl is-active --quiet nm-cloud-setup.service && systemctl disable nm-cloud-setup.service --now
systemctl is-active --quiet nm-cloud-setup.timer && systemctl disable nm-cloud-setup.timer --now

# Reboot only if dnf says it's needed (pending kernel or glibc updates).
dnf needs-restarting -r || reboot

Install kubectl with autocompletion:

# Install kubectl
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

# Configure autocompletion
dnf install -y bash-completion
source /usr/share/bash-completion/bash_completion
echo 'source <(kubectl completion bash)' >>~/.bashrc

# source the bashrc
source ~/.bashrc

Install K3s with --write-kubeconfig-mode 644 to make the config file (/etc/rancher/k3s/k3s.yaml) readable by non-root users, pinning the version to v1.29.6+k3s2:

curl -sfL https://get.k3s.io | \
    INSTALL_K3S_VERSION=v1.29.6+k3s2 \
    sh -s - \
    --write-kubeconfig-mode 644

Clone the awx-on-k3s repository:

cd ~

# Install git
dnf install -y git

# Clone the awx-on-k3s repository
git clone https://github.com/kurokobo/awx-on-k3s.git
cd awx-on-k3s

# checkout 2.19.1
git checkout 2.19.1+20260320.1

This version of the operator was released with AWX v24.6.

Copy the Kubeconfig file to its default location (~/.kube/config):

mkdir -p ~/.kube
cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
chown $(id -u):$(id -g) ~/.kube/config

Then invoke the operator to install AWX:

kubectl apply -k operator

Now when you run kubectl -n awx get all, you should see 2 pod replicas running, a service, a deployment, and a replicaset. These are the resources that make up the operator:

pod/awx-operator-controller-manager-xxx-xxx
service/awx-operator-controller-manager-metrics-service
deployment.apps/awx-operator-controller-manager
replicaset.apps/awx-operator-controller-manager-xxxx

Since we are going to use "awx.example.com" as the domain name for the AWX machine, we will self-sign a certificate for this domain:

# Set the AWX_HOST variable
AWX_HOST="awx.example.com"

# Generate a self-signed certificate
openssl req -x509 -nodes \
    -days 3650 \
    -newkey rsa:2048 \
    -out ./base/tls.crt \
    -keyout ./base/tls.key \
    -subj "/CN=${AWX_HOST}/O=${AWX_HOST}" \
    -addext "subjectAltName = DNS:${AWX_HOST}"

Now update base/awx.yaml. You'll set the domain name, choose a disk size for the PostgreSQL volume, and pick the number of replicas for the web and task services along with their resource requirements. You can copy and execute the whole block below:

cat << EOF > base/awx.yaml
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
  name: awx
spec:
  # These parameters are designed for use with:
  # - AWX Operator: 2.19.1
  #   https://github.com/ansible/awx-operator/blob/2.19.1/README.md

  admin_user: admin
  admin_password_secret: awx-admin-password

  ingress_type: ingress
  ingress_hosts:
    - hostname: ${AWX_HOST}
      tls_secret: awx-secret-tls

  postgres_configuration_secret: awx-postgres-configuration

  postgres_data_volume_init: true
  postgres_storage_class: awx-postgres-volume
  postgres_storage_requirements:
    requests:
      storage: 8Gi

  projects_persistence: true
  projects_existing_claim: awx-projects-claim

  web_replicas: 1
  task_replicas: 1

  web_resource_requirements: {}
  task_resource_requirements: {}
  ee_resource_requirements: {}
  init_container_resource_requirements: {}
  postgres_resource_requirements: {}
  redis_resource_requirements: {}
  rsyslog_resource_requirements: {}

  # Uncomment to reveal "censored" logs
  #no_log: false

EOF

Next, update base/kustomization.yaml. If you want to change the PostgreSQL password, the AWX password, or the SECRET_KEY, this is where you do it. Here's an example you can use:

cat << EOF > base/kustomization.yaml
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: awx

generatorOptions:
  disableNameSuffixHash: true

secretGenerator:
  - name: awx-secret-tls
    type: kubernetes.io/tls
    files:
      - tls.crt
      - tls.key

  - name: awx-postgres-configuration
    type: Opaque
    literals:
      - host=awx-postgres-15
      - port=5432
      - database=awx
      - username=awx
      - password=Ansible123!
      - type=managed

  - name: awx-admin-password
    type: Opaque
    literals:
      - password=Ansible123!

  # If you want to specify SECRET_KEY for your AWX manually, uncomment following lines and change the value.
  # Refer AAC documentation for detail about SECRET_KEY.
  # https://docs.ansible.com/automation-controller/latest/html/administration/secret_handling.html
  #- name: awx-secret-key
  #  type: Opaque
  #  literals:
  #    - secret_key=MySuperSecureSecretKey123!

resources:
  - pv.yaml
  - pvc.yaml

AWX in Action

Ansible Orchestration at Scale

Enroll now to unlock all content and receive all future updates for free.