AWX sur K3s — Déploiement via AWX Operator dans un LXC Proxmox¶
AWX est l'interface web open-source pour Ansible. À partir de la version 18, AWX ne supporte plus Docker Compose et requiert Kubernetes. Ce guide déploie AWX via l'AWX Operator sur un cluster K3s single-node hébergé dans un conteneur LXC Proxmox — la solution la plus légère pour un homelab.
Architecture¶
Proxmox VE
└── LXC <CT_ID> — awx.votre-domaine.tld (<CT_IP>) — 6 Go RAM / 4 cores / 32 Go
└── K3s (single-node)
└── namespace: awx-operator-system
├── awx-operator ← AWX Operator (controller)
├── awx-web ← Interface web + API REST
├── awx-task ← Exécuteur de jobs Ansible
├── awx-redis ← Cache / file de messages
└── awx-postgres ← Base de données (StatefulSet)
Namespace unique
L'instance AWX et l'Operator doivent être dans le même namespace (awx-operator-system). L'Operator ne surveille que son propre namespace par défaut — créer l'instance AWX ailleurs l'empêche de la reconcilier.
Accès : http://<CT_IP>:30080 (NodePort K3s)
Prérequis¶
Valeurs d'exemple utilisées dans ce guide — à adapter à votre environnement :
| Paramètre | Valeur d'exemple |
|---|---|
| ID conteneur | 200 |
| Hostname | awx.votre-domaine.tld |
| IP fixe | 192.168.1.200/24 |
| Passerelle | 192.168.1.254 |
| RAM | 6144 Mo (minimum recommandé) |
| CPU | 4 cores |
| Disque | 32 Go |
| Stockage Proxmox | local-lvm |
| Mode | Privilégié (requis par K3s) |
| Port web | 30080 (NodePort) |
Conteneur privilégié
K3s nécessite un conteneur privilégié (unprivileged: 0) pour accéder aux namespaces kernel. Ce n'est pas un choix de confort — K3s ne peut pas démarrer dans un LXC non privilégié sans configuration kernel avancée.
Déploiement automatique via le script¶
cd /root/scripts/awx-lxc
cp vars-example.conf vars.conf # éditer les valeurs
chmod +x install.sh
bash install.sh
Le script réalise dans l'ordre les étapes décrites ci-dessous.
Durée
Le déploiement complet prend 8 à 12 minutes — la majorité du temps est passée à télécharger les images AWX (~1,5 Go au total).
Déploiement manuel étape par étape¶
1 — Charger les modules kernel sur l'hôte Proxmox¶
Ces modules doivent être présents sur l'hôte avant le démarrage de K3s :
modprobe br_netfilter
modprobe overlay
Pour les rendre persistants au redémarrage :
echo -e "br_netfilter\noverlay" >> /etc/modules-load.d/k3s.conf
2 — Créer le conteneur LXC¶
pveam update
pveam download local debian-12-standard_12.x-x_amd64.tar.zst
pct create 200 local:vztmpl/debian-12-standard_12.x-x_amd64.tar.zst \
--hostname awx.votre-domaine.tld \
--memory 6144 \
--swap 2048 \
--cores 4 \
--rootfs local-lvm:32 \
--net0 name=eth0,bridge=vmbr0,ip=192.168.1.200/24,gw=192.168.1.254 \
--unprivileged 0 \
--features nesting=1 \
--onboot 1
Ajouter la configuration kernel requise par K3s dans /etc/pve/lxc/200.conf :
cat >> /etc/pve/lxc/200.conf << 'EOF'
lxc.apparmor.profile: unconfined
lxc.cgroup2.devices.allow: a
lxc.cap.drop:
lxc.mount.auto: proc:rw sys:rw
EOF
Démarrer le conteneur :
pct start 200
3 — Installer les dépendances¶
pct exec 200 -- apt-get update -qq
pct exec 200 -- apt-get install -y --no-install-recommends \
curl ca-certificates git open-iscsi nfs-common
4 — Corriger /dev/kmsg (spécifique LXC)¶
Le kubelet requiert /dev/kmsg, absent des LXC Proxmox. Ce lien symbolique le recrée automatiquement à chaque démarrage :
pct exec 200 -- bash -c "
echo 'L /dev/kmsg - - - - /dev/console' > /etc/tmpfiles.d/kmsg.conf &&
systemd-tmpfiles --create /etc/tmpfiles.d/kmsg.conf
"
5 — Installer K3s¶
pct exec 200 -- bash -c "
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC='--disable=traefik' sh -
"
Attendre que le nœud soit prêt :
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
until /usr/local/bin/kubectl get nodes 2>/dev/null | grep -q 'Ready'; do sleep 5; done
/usr/local/bin/kubectl get nodes
"
6 — Déployer l'AWX Operator via kustomize¶
Récupérer la dernière version stable :
OPERATOR_TAG=$(curl -s https://api.github.com/repos/ansible/awx-operator/releases/latest \
| grep '"tag_name"' | cut -d'"' -f4)
echo "AWX Operator : $OPERATOR_TAG"
Créer le fichier kustomization et appliquer :
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
mkdir -p /tmp/awx-install && cd /tmp/awx-install
cat > kustomization.yaml <<EOF
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- github.com/ansible/awx-operator/config/default?ref=${OPERATOR_TAG}
namespace: awx-operator-system
EOF
/usr/local/bin/kubectl create namespace awx-operator-system --dry-run=client -o yaml \
| /usr/local/bin/kubectl apply -f -
/usr/local/bin/kubectl apply -k .
"
Correctif kube-rbac-proxy
L'image gcr.io/kubebuilder/kube-rbac-proxy a été retirée de Google Container Registry. Patcher le déploiement pour utiliser l'image de remplacement sur quay.io :
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
/usr/local/bin/kubectl patch deployment awx-operator-controller-manager \
-n awx-operator-system \
--type='json' \
-p='[
{\"op\": \"replace\", \"path\": \"/spec/template/spec/containers/0/image\", \"value\": \"quay.io/brancz/kube-rbac-proxy:v0.15.0\"},
{\"op\": \"replace\", \"path\": \"/spec/template/spec/containers/1/image\", \"value\": \"quay.io/ansible/awx-operator:${OPERATOR_TAG}\"}
]'
"
Attendre que l'Operator soit opérationnel (2/2 Running) :
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
until /usr/local/bin/kubectl get pods -n awx-operator-system \
| grep controller-manager | grep -q '2/2'; do sleep 5; done
echo 'Operator prêt'
"
7 — Déployer l'instance AWX¶
Namespace
L'instance AWX doit impérativement être créée dans awx-operator-system, le même namespace que l'Operator.
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
cat <<'EOF' | /usr/local/bin/kubectl apply -f -
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
namespace: awx-operator-system
spec:
service_type: nodeport
nodeport_port: 30080
postgres_storage_class: local-path
EOF
"
Attendre que les pods AWX soient en Running (8 à 12 min) :
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
until /usr/local/bin/kubectl get pods -n awx-operator-system \
| grep 'awx-web' | grep -q 'Running'; do
/usr/local/bin/kubectl get pods -n awx-operator-system
sleep 15
done
echo 'AWX opérationnel'
"
8 — Exposer le NodePort via iptables¶
CT_IP=192.168.1.200
iptables -t nat -A PREROUTING -p tcp --dport 30080 -j DNAT --to-destination ${CT_IP}:30080
iptables -I FORWARD -p tcp -d ${CT_IP} --dport 30080 -j ACCEPT
iptables-save > /etc/iptables.rules
Vérification post-installation¶
État des pods¶
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
/usr/local/bin/kubectl get pods -n awx-operator-system
"
Résultat attendu :
NAME READY STATUS RESTARTS
awx-operator-controller-manager-... 2/2 Running 0
awx-postgres-15-0 1/1 Running 0
awx-redis-... 1/1 Running 0
awx-task-... 4/4 Running 0
awx-web-... 3/3 Running 0
Logs de l'Operator¶
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
/usr/local/bin/kubectl logs -n awx-operator-system \
deploy/awx-operator-controller-manager -c awx-manager -f
"
Accès à l'interface¶
http://192.168.1.200:30080
Récupérer le mot de passe admin (généré automatiquement à l'installation) :
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
/usr/local/bin/kubectl get secret awx-admin-password \
-n awx-operator-system \
-o jsonpath='{.data.password}' | base64 --decode && echo
"
- Utilisateur :
admin - Mot de passe : résultat de la commande ci-dessus
Mise à jour¶
La mise à jour d'AWX passe par la mise à jour de l'Operator via kustomize — l'Operator se charge ensuite de mettre à jour l'instance automatiquement.
cd /root/scripts/awx-lxc
bash update.sh
Ou manuellement :
NEW_TAG=$(curl -s https://api.github.com/repos/ansible/awx-operator/releases/latest \
| grep '"tag_name"' | cut -d'"' -f4)
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
mkdir -p /tmp/awx-update && cd /tmp/awx-update
cat > kustomization.yaml <<EOF
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- github.com/ansible/awx-operator/config/default?ref=${NEW_TAG}
namespace: awx-operator-system
EOF
/usr/local/bin/kubectl apply -k .
"
Points d'administration¶
État général¶
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
/usr/local/bin/kubectl get pods -n awx-operator-system
/usr/local/bin/kubectl top pods -n awx-operator-system
"
Redémarrer AWX sans recréer les données¶
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
/usr/local/bin/kubectl rollout restart \
deployment/awx-web deployment/awx-task \
-n awx-operator-system
"
Sauvegarde des données¶
pct exec 200 -- bash -c "
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
/usr/local/bin/kubectl exec -n awx-operator-system deploy/awx-web -- \
awx-manage dumpdata --natural-foreign --natural-primary \
-e contenttypes -e auth.Permission \
--indent 4 > /tmp/awx-backup-\$(date +%Y%m%d).json
"
Désinstallation complète¶
cd /root/scripts/awx-lxc
bash uninstall.sh
Comparaison avec l'ancienne installation Docker Compose¶
| AWX 17 (Docker Compose) | AWX actuel (K3s + Operator) | |
|---|---|---|
| Support | ❌ Abandonné depuis v18 | ✅ Actif |
| Mise à jour | Manuelle et complexe | kustomize apply + Operator |
| Ressources | ~2 Go RAM | ~4-6 Go RAM |
| Complexité opérationnelle | Faible | Modérée |
| RBAC | ✅ | ✅ |
| Workflows | ✅ | ✅ |
| API REST | ✅ | ✅ |