AWX es el proyecto de código abierto del que deriva Red Hat Ansible Automation Platform (antes Ansible Tower). Añade a Ansible una interfaz web, una API REST, gestión centralizada de credenciales, inventarios, permisos por usuario y equipo, y un historial de todas las ejecuciones. La única forma de instalación soportada es AWX Operator sobre Kubernetes, así que en este tutorial montarás un Kubernetes ligero de un solo nodo con k3s en Ubuntu 24.04, desplegarás AWX con el operador, lo publicarás con HTTPS y ejecutarás tu primer playbook desde la interfaz.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS dedicado a AWX, por ejemplo un VPS de CubePath, con al menos 4 vCPU, 8 GB de RAM y 40 GB de disco. AWX ejecuta PostgreSQL, la web, el planificador de tareas y los contenedores de cada ejecución, y con menos memoria los pods se quedan en Pending o se reinician.
  • Un usuario no root con privilegios sudo.
  • Un dominio con un registro DNS de tipo A (awx.your_domain) apuntando a la IP pública del servidor, para el certificado HTTPS.
  • Una dirección de correo para el registro en Let's Encrypt.

Paso 1: Preparar el servidor y el cortafuegos

Actualiza el sistema e instala git, que kubectl necesita para descargar los manifiestos del operador desde GitHub:

sudo apt update && sudo apt upgrade -y
sudo apt install git curl

Configura UFW. Además de SSH, HTTP y HTTPS, k3s necesita que se permita el tráfico de las redes internas de pods (10.42.0.0/16) y servicios (10.43.0.0/16); sin estas reglas, los pods no pueden comunicarse entre sí:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 10.42.0.0/16 to any
sudo ufw allow from 10.43.0.0/16 to any
sudo ufw enable

Comprueba las reglas:

sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
Anywhere                   ALLOW       10.42.0.0/16
Anywhere                   ALLOW       10.43.0.0/16
...

No abras el puerto 6443 (API de Kubernetes) a Internet: en este tutorial solo usarás kubectl desde el propio servidor.

Paso 2: Instalar k3s

k3s es una distribución de Kubernetes certificada que se instala como un único binario e incluye Traefik como controlador de Ingress, que usarás para publicar AWX. Descarga el script de instalación oficial y revísalo antes de ejecutarlo:

curl -sfL https://get.k3s.io -o k3s-install.sh
less k3s-install.sh

Ejecútalo. Instala la última versión estable de k3s como servicio systemd:

sudo sh k3s-install.sh

Comprueba que el servicio está activo y que el nodo está listo (puede tardar unos 30 segundos):

sudo systemctl status k3s --no-pager | head -3
sudo k3s kubectl get nodes
● k3s.service - Lightweight Kubernetes
     Loaded: loaded (/etc/systemd/system/k3s.service; enabled; preset: enabled)
     Active: active (running) since ...
NAME   STATUS   ROLES                  AGE   VERSION
awx    Ready    control-plane,master   45s   v1.33.4+k3s1

Paso 3: Configurar kubectl para tu usuario

El archivo de acceso de k3s, /etc/rancher/k3s/k3s.yaml, solo lo puede leer root. Copia una versión para tu usuario con permisos restringidos, en lugar de hacer el original legible por todos:

mkdir -p ~/.kube
sudo k3s kubectl config view --raw > ~/.kube/config
chmod 600 ~/.kube/config
echo 'export KUBECONFIG=~/.kube/config' >> ~/.bashrc
source ~/.bashrc

k3s instala kubectl en /usr/local/bin. Comprueba que funciona sin sudo:

kubectl get pods -A
NAMESPACE     NAME                                      READY   STATUS      RESTARTS   AGE
kube-system   coredns-...                               1/1     Running     0          2m
kube-system   local-path-provisioner-...                1/1     Running     0          2m
kube-system   metrics-server-...                        1/1     Running     0          2m
kube-system   svclb-traefik-...                         2/2     Running     0          1m
kube-system   traefik-...                               1/1     Running     0          1m
...

El local-path-provisioner es el que dará almacenamiento persistente a la base de datos de AWX.

Paso 4: Instalar cert-manager para los certificados HTTPS

cert-manager obtiene y renueva certificados de Let's Encrypt automáticamente para los Ingress de Kubernetes. Instálalo con el manifiesto de su última versión publicada:

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml

Espera a que sus tres pods estén en Running:

kubectl get pods -n cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-...                           1/1     Running   0          60s
cert-manager-cainjector-...                1/1     Running   0          60s
cert-manager-webhook-...                   1/1     Running   0          60s

Crea un emisor (ClusterIssuer) que pida certificados a Let's Encrypt validando por HTTP a través de Traefik:

mkdir -p ~/awx && cd ~/awx
nano cluster-issuer.yaml

Sustituye your_email por tu dirección de correo:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: your_email
    privateKeySecretRef:
      name: letsencrypt-prod-account-key
    solvers:
      - http01:
          ingress:
            ingressClassName: traefik

Aplícalo y comprueba que está listo:

kubectl apply -f cluster-issuer.yaml
kubectl get clusterissuer
NAME               READY   AGE
letsencrypt-prod   True    10s

Paso 5: Instalar AWX Operator

El operador es un controlador que vigila los recursos de tipo AWX y crea todo lo necesario (base de datos, despliegues, servicios, Ingress). Se instala con Kustomize, que ya viene integrado en kubectl. Crea el archivo de Kustomize en ~/awx:

nano kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - github.com/ansible/awx-operator/config/default?ref=2.19.1

images:
  - name: quay.io/ansible/awx-operator
    newTag: 2.19.1

namespace: awx

La versión aparece dos veces (en la URL y en newTag) y debe ser la misma. Aplica el manifiesto:

kubectl apply -k .

Comprueba que el operador está en marcha:

kubectl get pods -n awx
NAME                                               READY   STATUS    RESTARTS   AGE
awx-operator-controller-manager-6c9b8d7f5d-x2k8p   2/2     Running   0          50s

Paso 6: Desplegar la instancia de AWX

Describe la instancia de AWX en un recurso propio. Sustituye awx.your_domain por el nombre DNS que creaste:

nano awx.yaml
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
  name: awx
spec:
  service_type: clusterip
  ingress_type: ingress
  ingress_class_name: traefik
  ingress_hosts:
    - hostname: awx.your_domain
      tls_secret: awx-tls
  ingress_annotations: |
    cert-manager.io/cluster-issuer: letsencrypt-prod
  • service_type: clusterip deja el servicio accesible solo dentro del clúster; el acceso externo pasa por Traefik.
  • ingress_hosts crea el Ingress con tu dominio y guarda el certificado en el secreto awx-tls.
  • La anotación cert-manager.io/cluster-issuer indica a cert-manager que emita ese certificado con Let's Encrypt.

Añade el archivo a la lista de recursos de kustomization.yaml:

nano kustomization.yaml
resources:
  - github.com/ansible/awx-operator/config/default?ref=2.19.1
  - awx.yaml

Aplica de nuevo:

kubectl apply -k .

El operador tarda entre 5 y 10 minutos en crear PostgreSQL, migrar la base de datos y arrancar AWX. Sigue su progreso en el log:

kubectl logs -f deployments/awx-operator-controller-manager -c awx-manager -n awx

Cuando termine verás un resumen de Ansible sin fallos (failed=0). Pulsa Ctrl+C y revisa los pods:

kubectl get pods -n awx
NAME                                               READY   STATUS      RESTARTS   AGE
awx-migration-24.6.1-7fk2q                         0/1     Completed   0          6m
awx-operator-controller-manager-6c9b8d7f5d-x2k8p   2/2     Running     0          12m
awx-postgres-15-0                                  1/1     Running     0          7m
awx-task-7d4b9c6f8-mz5tq                           4/4     Running     0          6m
awx-web-5f8c7d9b4-pl2rv                            3/3     Running     0          6m

Comprueba que el certificado se ha emitido:

kubectl get certificate -n awx
NAME      READY   SECRET    AGE
awx-tls   True    awx-tls   5m

Paso 7: Acceder a la interfaz web

El operador genera una contraseña aleatoria para el usuario admin y la guarda en un secreto. Recupérala:

kubectl get secret awx-admin-password -n awx -o jsonpath="{.data.password}" | base64 --decode; echo

Abre https://awx.your_domain en el navegador e inicia sesión con el usuario admin y esa contraseña. Deberías ver el panel de AWX con la organización Default y unos recursos de demostración (Demo Project, Demo Inventory, Demo Job Template).

Crea un usuario personal en Access > Users y usa admin solo para tareas de administración.

Paso 8: Ejecutar tu primer playbook

AWX organiza la automatización en cuatro piezas: una credencial para conectarse a los servidores, un inventario con los servidores, un proyecto con los playbooks (normalmente un repositorio Git) y una plantilla de trabajo que une las tres. Vas a crear cada una para ejecutar un playbook de ejemplo contra un servidor.

Crear la credencial

En Resources > Credentials, pulsa Add:

  • Name: ssh-servidores
  • Organization: Default
  • Credential Type: Machine
  • Username: el usuario remoto (your_user)
  • SSH Private Key: pega la clave privada cuya pública está en ~/.ssh/authorized_keys del servidor de destino
  • Privilege Escalation Method: sudo, y la contraseña de sudo si tu usuario la necesita

Guarda. AWX cifra las credenciales en su base de datos y no vuelve a mostrar los secretos.

Crear el inventario

En Resources > Inventories, pulsa Add > Add inventory, llámalo produccion y guarda. En la pestaña Hosts, añade un host con el nombre del servidor (web1) y, en Variables:

ansible_host: your_server_ip

Crear el proyecto

En Resources > Projects, pulsa Add:

  • Name: ejemplos
  • Organization: Default
  • Source Control Type: Git
  • Source Control URL: https://github.com/ansible/ansible-tower-samples
  • Marca Update Revision on Launch para que AWX descargue la última versión del repositorio en cada ejecución.

Guarda. AWX clona el repositorio; el estado del proyecto pasa a Successful en unos segundos. Para tus propios playbooks usa tu repositorio y, si es privado, una credencial de tipo Source Control.

Crear y lanzar la plantilla de trabajo

En Resources > Templates, pulsa Add > Add job template:

  • Name: hola-mundo
  • Inventory: produccion
  • Project: ejemplos
  • Playbook: hello_world.yml
  • Credentials: ssh-servidores

Guarda y pulsa Launch. AWX abre la salida de la ejecución en directo:

PLAY [Hello World Sample] ******************************************************

TASK [Gathering Facts] *********************************************************
ok: [web1]

TASK [Hello Message] ***********************************************************
ok: [web1] => {
    "msg": "Hello World!"
}

PLAY RECAP *********************************************************************
web1                       : ok=2    changed=0    unreachable=0    failed=0

Si ves unreachable, el pod de ejecución no llega al servidor por SSH: comprueba la IP, el puerto 22 del destino y que la clave de la credencial es la correcta.

Desde la misma plantilla puedes programar ejecuciones periódicas (pestaña Schedules) y dar permiso de ejecución a otros usuarios o equipos (pestaña Access) sin darles acceso a las credenciales.

Paso 9: Hacer copias de seguridad de AWX

Toda la configuración de AWX (credenciales, inventarios, historial) vive en PostgreSQL. El operador incluye un recurso AWXBackup que vuelca la base de datos y los secretos a un volumen persistente:

nano ~/awx/backup.yaml
apiVersion: awx.ansible.com/v1beta1
kind: AWXBackup
metadata:
  name: awx-backup-inicial
  namespace: awx
spec:
  deployment_name: awx
kubectl apply -f ~/awx/backup.yaml
kubectl get awxbackup -n awx

Revisa el log del operador hasta que la copia termine. Guarda también una copia del secreto awx-secret-key, sin el cual no se pueden descifrar las credenciales al restaurar:

kubectl get secret awx-secret-key -n awx -o yaml > ~/awx-secret-key.yaml
chmod 600 ~/awx-secret-key.yaml

Esa copia queda en el mismo servidor; muévela a un almacenamiento externo seguro.

Solución de problemas

Los pods de AWX se quedan en Pending. Normalmente falta memoria o CPU. kubectl describe pod <nombre> -n awx muestra el motivo en la sección Events (Insufficient memory, Insufficient cpu).

El certificado no pasa a READY True. Comprueba que el registro DNS apunta a la IP del servidor y que el puerto 80 está abierto: Let's Encrypt valida por HTTP. kubectl describe certificate awx-tls -n awx y kubectl get challenges -n awx muestran el error concreto.

kubectl apply -k . falla al descargar los manifiestos. Falta git en el servidor o la etiqueta de ref= no existe. Comprueba la etiqueta en la página de versiones del operador.

El operador repite errores en su log. Busca la primera tarea con fatal en kubectl logs deployments/awx-operator-controller-manager -c awx-manager -n awx; suele indicar un campo mal escrito en awx.yaml.

Conclusión

Tienes AWX funcionando sobre k3s en Ubuntu 24.04, publicado con HTTPS de Let's Encrypt, con una primera plantilla de trabajo ejecutada contra un servidor real y una copia de seguridad inicial. Como siguientes pasos, conecta AWX a tus repositorios de playbooks con credenciales de tipo Source Control, crea equipos con permisos por inventario y plantilla, y programa AWXBackup de forma periódica junto con una copia externa del secreto de cifrado.