Outils pour utilisateurs

Outils du site


blog

AWX - build to run

AWX Resource Requirements

Prérequis logiciels

  • have configured an NTP client on all nodes

Architecture

Choix :

  • Base de données sur le hôte ou sur K8S ?
    • Idéalement Postgres dans un conteneur : plus de souplesse avec la gestion des versions

Conf système hôte

  • Réactiver SELinux
  • Après avoir redéfini ipv6_disabled, si OK désactiver l'IPv6 sur le hôte et tester

Changer dans Job settings - Container Run Options

[
  "--network",
  "slirp4netns:enable_ipv6=true"
]

Désactiver le SWAP. Totalement ou memory.swap.max=0 ? Voir

cat /sys/fs/cgroup/memory.swap.max

Conf Podman

Tester le démarrage automatique native Podman

podman update --restart=always kind-control-plane

A la place de ~/.config/systemd/user/container-kind-control-plane.service

Réseau

Conf AWX

Voir :

kubectl get AWX -o json | jq '.items[0].spec'
  • auto_upgrade
  • hostname
  • ipv6_disabled

Sauvegarde / backup

  1. Export de tous les objets AWX en YAML
  2. Export de la base de données
  3. Sauvegarde avec AWX Operator
Export de tous les objets AWX en YAML
awx -f yaml export > all.yaml

NOTE : Les credentials ne sont pas exportés, ni certains objets

Export de la base de données PostgreSQL

Voir :

# retrieve your secret's name, something like awx-postgres-configuration
kubectl get secrets
 
# show secrets 
kubectl get secrets awx-your-instance-postgres-configuration -o yaml
 
kubectl port-forward awx-your-postgre-pod 5432:5432

Source : https://forum.ansible.com/t/need-advices-on-awx-config-import-export/6974/6

Sauvegarde avec AWX Operator

PoC Stockage

Voir :

cluster-config.yml

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
    - containerPort: 30000
      hostPort: 30000
      protocol: TCP
  extraMounts:
    - containerPath: /data/files
      hostPath: /data/files

ansible-files-pv.yml

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: awx-ansible-files-volume
spec:
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  capacity:
    storage: 2Gi
  storageClassName: local-path
  hostPath:
    path: /data/ansible-files

ansible-files-pvc.yml

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: awx-ansible-files-claim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 2Gi
  storageClassName: local-path
kubectl create secret generic awx-custom-certs --from-file=bundle-ca.crt=/etc/ssl/certs/ca-bundle.crt

cluster-config.yml

---

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
    extraPortMappings:
      - containerPort: 30000
        hostPort: 30000
        protocol: TCP
    extraMounts:
      - containerPath: /data/ansible-files
        hostPath: /data/ansible-files
      - containerPath: /data/projects
        hostPath: /data/projects
      - containerPath: /data/postgres-13
        hostPath: /data/postgres-13

Fixer la version avec l'option --image

kind create cluster --image kindest/node:v1.34.2

Available tags can be found at https://hub.docker.com/r/kindest/node/tags

kind create cluster --config=cluster-config.yml --name=kind2
 
# kubectl create deployment nginx --image=nginx --port=80
# kubectl create service nodeport nginx --tcp=80:80 --node-port=30000
 
kubectl create service nodeport awx-service --tcp=80:80 --node-port=30000

Dans jobs settings changer :

Paths to expose to isolated jobs

[
  "/etc/pki/ca-trust:/etc/pki/ca-trust:O",
  "/usr/share/pki:/usr/share/pki:O"
]

Debug

2025/11/10 18:15 · Jean-Baptiste

AWX - Changer l'Execution Environment du Control Plane

Changer Control Plane Execution Environment

kubectl edit AWX
spec:
  control_plane_ee_image: registry.test.svc.cluster.local:5000/awx-ee-gts-it:2.19.3-2-1 

Par défaut c'était quay.io/ansible/awx-ee:24.6.1

2025/11/07 22:11 · Jean-Baptiste

AWX - ansible-galaxy - need ignore-certs to download roles with ansible-galaxy

Description

requirements.yml

---

- name: test_jb
  src: https://bitbucket.acme.local/scm/jean/ansible-role-test_jb.git
  scm: git               # <--- Add this line to fix HTTP Error 501 !
  version: master
ansible-galaxy role install -r requirements.yml
- downloading role from https://bitbucket.acme.local/scm/jean/ansible-role-test_jb.git
[ERROR]: failed to download the file: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1147)>
[WARNING]: - test_jb was NOT installed successfully.
ERROR! - you can use --ignore-errors to skip failed roles and finish processing the list.
Méthode Fichier de conf ansible.cfg

STATUS : NOK

need ignore-certs to download roles with ansible-galaxy https://github.com/geerlingguy/ansible-for-kubernetes/issues/62

Erreur :

urlopen error [SSL: CERTIFICATE_VERIFY_FAILED]
certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)>

~/.ansible.cfg

[galaxy]
ignore_certs = yes

Effet : aucun

Méthode par variables d'environement

STATUS : NOK

https://docs.ansible.com/ansible/latest/reference_appendices/config.html

export ANSIBLE_GALAXY_IGNORE=yes
export GALAXY_IGNORE_CERTS=yes

Effet : aucun

Méthode config Libcurl

STATUS : NOK

echo "cacert=/runner/ca.crt" > ~/.curlrc

Effet : ça fonctionne pour curl et git mais aucun effet pour ansible-galaxy

Méthode K8S

STATUS : OK

https://ansible.readthedocs.io/projects/awx-operator/en/latest/user-guide/advanced-configuration/trusting-a-custom-certificate-authority.html

Syntaxe

kubectl create secret generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run=server|client|none]
kubectl create secret generic awx-custom-certs --from-file=bundle-ca.crt=/etc/ssl/certs/ca-bundle.crt
kubectl edit AWX
spec:
  bundle_cacert_secret: awx-custom-certs
Méthode ajout CA au niveau système

STATUS : NOK

https://virtualhobbit.com/2020/06/19/adding-internal-ca-ssl-chains-to-ansible-awx/

curl -k -w %{certs} https://www.acme.fr > cacert.pem
mv chain.pem /etc/pki/ca-trust/source/anchors/
/etc/pki/ca-trust/source/anchors/
update-ca-trust extract

Effet : C'est étrange, ça fonctionne pour wget mais pas pour curl ni pour ansible-galaxy. C'est comme si libcurl ne parvenait pas à choisir le certificat approprié.

Méthode ajouter le certificat dans /etc/ansible/

STATUS : A confirmer

Voir :

Add the ca cert to /etc/ansible on the system you are running ansible-galaxy from. The file should use a .crt or .pem

Testé en mettant le certificat dans ~/.ansible/ : aucun effet

Méthode par config Git

STATUS : NOK

git config --global http.sslCAInfo ~/ca.crt

ansible-galaxy ignore http.sslCAInfo

Effet : ça fonctionne pour git mais pas pour ansible-galaxy Ça semble ne concerner que la commande gît, mais pas Python (ansible-galaxy)

Méthode par hack wrapper (enveloppe)

STATUS : OK pour HTTPS mais KO pour l'authentification

Pas nécessaire si K8S bundle_cacert_secret

Settings / Extra Environment Variable

{
  "GIT_SSL_NO_VERIFY": "true"
}

ansible-galaxy.sh

#! /bin/bash
 
set -euo pipefail
 
declare -a all_args
 
arg_append() {
    all_args=(${all_args[@]} $1)
}
 
while [ "${1-}" != "" ]; do
    case $1 in
    install)
        arg_append install
        arg_append "-c"
        ;;
    *)
        arg_append "$@"
        ;;
    esac
    shift
done
 
exec /usr/local/bin/ansible-galaxy1 "${all_args[@]}"

execution-environment.yml

---

version: 3

images:
  base_image:
    name: quay.io/ansible/awx-ee:24.6.1

additional_build_files:
  - src: files/ansible-galaxy.sh
    dest: files/

additional_build_steps:
  prepend_base:
    - RUN cp -p /usr/local/bin/ansible-galaxy /usr/local/bin/ansible-galaxy.orig
    - RUN mv /usr/local/bin/ansible-galaxy /usr/local/bin/ansible-galaxy1
    - ADD _build/files/ansible-galaxy.sh /usr/local/bin/ansible-galaxy

options:
  user: '1000'

Comme l'authentification de fonctionne pas, testons : requirements.yml

---

- name: test_jb
  #src: https://bitbucket.acme.local/scm/jean/ansible-role-test_jb.git
  src: https://jean:password@bitbucket.acme.local/scm/jean/ansible-role-test_jb.git
  version: master

Note : le mot de passe doit être en URL encoding si il contient des caractères spéciaux

[ERROR]: failed to download the file: HTTP Error 501:\n[WARNING]: - test_jb was NOT installed successfully.\nERROR! - you can use --ignore-errors to skip failed roles and finish processing the list.",

Effet : Ça ne fonctionne toujours pas, mais pour une autre raison. On a avancé le schmilblick. Le script wrapper fait joue bien son rôle.

Conclusions provisoires

A faire :

Note : vu qu'après avoir corrigé (en bidouillant) le problème de TLS nous tombons sur un 2em problème il y a de fortes probabilités que notre approche ne soit pas la bonne. Nous ne sommes certainement pas les premiers à tenter de faire fonctionner ansible-galaxy avec Bitbucket en HTTPS avec des certificats auto signés.

Idéalement la CA devrait être déployée est fonctionnelle sur l'ensemble des OS.

Il faut ajouter : scm: git

requirements.yml

---

- name: test_jb
  src: https://bitbucket.acme.local/scm/jean/ansible-role-test_jb.git
  scm: git
  version: master

Conclusions définitives

Avec la nouvelle PKI et en définissant le secret bundle_cacert_secret (méthode K8S) ça fonctionne. Avec ajout du certificat dans /etc/ansible/

2025/11/07 21:44 · Jean-Baptiste

Exemple de script rsync d'envoie de fichiers via SSH - pushlogs

QQOQCP

Quoi:

  • Envoie de fichiers logs des composants suivants : xxx01, xxx02

Où:

  • Le serveur destinataire est un serveur SFTP (SSH) renseigné dans le fichier pushlogs.env
  • La liste des fichiers à envoyer est défine dans le fichier pushlogs.lst

Quand:

  • Définie dans le(s) crontab de l'utilisateur(s) propriétaire des fichiers
  • Normalement il s'agit de l'utilisateur 'plopuser'

Qui:

  • Auteur: JBL
  • Pour: ACME

Comment:

  • Une crontab de l'utilsateur 'plopuser' (ou autre) appelle le script bash pushlogs.sh
  • pushlogs.sh utilise la commande rsync en utilisant le protocole SSH
  • L'authentification se fait par clef SSH (RSA 4096)
  • pushlogs.sh va lire le fichier .pushlogs.env et .pushlogs.lst présent à la racine du HOMEDIR

Prérequis

  • Les commandes suivants doivent être présentes : rsync

Options

Général
  • Le script ne prend aucun argument
  • Les options sont présentes et documentées dans le fichier .pushlogs.env
Crontab

Les crontab peuvent utiliser nice et ionice afin de limiter les ressources. L'envoie des logs étant de priorité inférieur aux traitements métier. Exemple (dans /var/spool/cron/plopuser) :

# Push logs
05 02 * * * nice -n 10 ionice -n 7 bash ~/scripts/pushlogs.sh >> ~/logs/pushlogs.txt 2>> ~/logs/pushlogs.err
~/.pushlogs.env
  • Voir ce fichier.
  • Une limitation de la bande passe permet de ne pas impacter le métier (BMLIMIT)
  • Il peut être utilse de limité l'envoie des logs aux seules fichiers récemment modifiés. Exemple pour les fichiers des 2 derniers jours : FIND_OPTS=“-mtime -2”
~/.pushlogs.lst
  • Contient la liste dans fichiers / dossier à envoyer
  • Le chemin est relatif à l'homedir de l'utilisateur (normalement '/home/plopuser/')
  • Il est possible d'utiliser des wildcards “*”. Exemple :
./app*/L*/logs_backup/

Génération des clefs

Les paires de clefs ont été générées de la façon suivante :

ssh-keygen -N '' -t rsa -b 4096 -C "XXX01_rsync_pushlog" -f id_xxx01_rsync_pushlog
ssh-keygen -N '' -t rsa -b 4096 -C "XXX02_rsync_pushlog" -f id_xxx02_rsync_pushlog

.pushlogs.env

# Limit network bandwidth in KiB/s
BMLIMIT=5000
 
# root dir to backup. Should not be changed
BACKUP_ROOT_DIR="$HOME"
 
# SSH settings
SSH_USER=plopuser
SSH_HOST=localhost
SSH_DIR=/tmp/plop
#SSH_PORT: See SSH_OPTS. Example: SSH_OPTS='-p 2222'
 
# Extra find options
FIND_OPTS=''
#FIND_OPTS='-mtime -2'
 
# Extra rsync options
RSYNC_OPTS='-c --itemize-changes'
 
# Extra SSH rsync options
SSH_OPTS='-p 22'

.pushlogs.env

./app?/L*/logs_backup/
./app?/L*/log/
./app?/L*/templog
./app?/scripts/backup_logfiles_l*.out

pushlogs.sh

#! /bin/bash
 
set -euo pipefail
IFS=$' \t\n'
export LC_ALL=C
 
SCRIPT_NAME=$(basename "$0")
PIDFILE=/dev/shm/${SCRIPT_NAME%.sh}.pid
ENVFILE=${HOME}/.${SCRIPT_NAME%.sh}.env
LISTSCRFILE=${HOME}/.${SCRIPT_NAME%.sh}.lst
 
trap 'rm -f "$PIDFILE"' EXIT ERR
 
echo "$(date --rfc-3339=second)" DEBUT EXECUTION
 
set +e
if [ -f "$PIDFILE" ]; then
    PLOP_PID=$(head -1 "$PIDFILE")
    echo "WARNING EALREADY: Operation already in progress (114)" >&2
    kill "$PLOP_PID" >/dev/null 2>&1
    sleep 5
    kill -9 "$PLOP_PID" >/dev/null 2>&1
    sleep 5
    if [ -d /proc/"$PLOP_PID" ]; then
        echo "ERROR EDEADLOCK: Resource deadlock avoided (35)" >&2
        exit 35
    else
        rm -f "$PIDFILE"
    fi
else
    echo $$ >"$PIDFILE"
fi
set -e
 
# shellcheck source=pushlogs.env
source "$ENVFILE"
 
main() {
    echo "$(date --rfc-3339=second)" DEBUT COPIE
    cd "$BACKUP_ROOT_DIR" || exit 2
 
    # shellcheck disable=SC2068,SC2046
    find $(grep -v '^#' "$LISTSCRFILE") -type f ${FIND_OPTS[@]} -print0 |
        rsync -e "ssh -o StrictHostKeyChecking=no -o CheckHostIP=no ${SSH_OPTS[*]}" \
            --bwlimit="$BMLIMIT" ${RSYNC_OPTS[@]} --files-from=- --from0 "${BACKUP_ROOT_DIR}" "${SSH_USER}"@"${SSH_HOST}":"${SSH_DIR}"
 
    cd -
    echo "$(date --rfc-3339=second)" FIN
}
 
main

FIXME

2025/10/30 10:30 · Jean-Baptiste
blog.txt · Dernière modification : de 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki