Files
factory/ansible
arcodangeandClaude Opus 5 93e7abfc57 fix(ci,crowdsec): écarter le runner de pi1, figer la résolution de la forge, couper le cache Redis du bouncer
Trois correctifs issus d'une même soirée de panne.

1. Runner hors du control-plane (03_cicd.yml)

`capacity: 1` ne borne que CHAQUE runner, pas le cluster : avec deux runners,
deux builds lourds tournent en parallèle. Le 2026-08-26 ils ont saturé pi1
(charge 7,38 sur 15 min, 5,7 Go/8), le démon Docker a cessé de répondre et les
DEUX jobs sont morts à la même seconde — 19:49:27, runs #152 et #154,
`context deadline exceeded` sur docker.sock. pi1 porte l'apiserver et
l'ingress. Même famille que 2026-07-23 et 2026-08-15.

Le parallélisme tombe à 1 (pi3 seul), assumé : le runner du Mac (label
`laptop`) absorbe les jobs lourds et va ~10× plus vite — mesuré sur kadans,
184 s contre 1 065 s sur pi3 et 1 915 s sur pi1.

2. Résolution de la forge figée (03_cicd.yml, group_vars/all/gitea.yml)

Les hôtes à runner résolvent `.lab` via un Pi-hole, puis retombent sur les
nameservers IPv6 du routeur, qui répondent NXDOMAIN — réponse valide, donc
retenue. D'où des pulls qui échouent par intermittence pendant que
`getent hosts` réussit. `extra_hosts` + `--add-host` court-circuitent le DNS.

L'IP est dérivée de l'inventaire (premier hôte du groupe `gitea`) plutôt
qu'écrite en dur. Vérifié que c'est équivalent : le registre répond 401 sur
/v2/ via .202 comme via .201, le svclb Traefik écoutant sur 443 de chaque nœud.

⚠ Ça ne couvre PAS le namespace réseau de buildkit, qui n'hérite d'aucun des
deux — corrigé séparément côté cms (pull côté démon, build sans `--pull`).

3. Cache Redis du bouncer coupé (roles/crowdsec)

`redisCacheUnreachableBlock: false` n'est pas honoré par le plugin : redis-0
étant 0/1, TOUTES les requêtes externes prenaient un 403 alors que
`cscli decisions list` était vide. Logs Traefik : `isBanned:false
redis:unreachable` → 403. Le cache mémoire suffit — en mode `stream` les
décisions viennent de la LAPI de toute façon.

⚠ NE PAS « réparer » Redis en `--save ""` : il sert aussi kadans-jobs (DB 1,
file de jobs) et telegram-gateway (DB 0, sessions d'auth 24 h).

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-26 22:55:38 +02:00
..
2024-08-16 13:53:03 +02:00

Use Ansible

Run locally (uv)

A project-local venv is defined in pyproject.toml at the repo root (ansible-core + the kubernetes, jmespath, dnspython libraries that kubernetes.core and friends need at runtime).

uv sync                                                # creates .venv/ and installs ansible-core + python deps
uv run ansible-galaxy collection install -r ansible/requirements.yml
uv run ansible-playbook -i ansible/arcodange/factory/inventory ansible/arcodange/factory/playbooks/<playbook>.yml

The localhost entry in the inventory uses ansible_python_interpreter: "{{ ansible_playbook_python }}", so uv run is enough — Ansible picks up the venv's Python automatically without any hardcoded path.

Run with docker ssh agent side proxy

build docker images

git clone -q --depth 1 --branch master https://github.com/arcodange/ssh-agent.git /tmp/ssh-agent
(cd /tmp/ssh-agent ; docker build -t docker-ssh-agent:latest -f Dockerfile . ; rm -rf /tmp/ssh-agent)
(cd ansible; docker build -t arcodange-ansible:0.0.0 .)

run in container

# git clone -q --depth 1 --branch master https://github.com/arcodange/ssh-agent.git /tmp/ssh-agent
# (cd /tmp/ssh-agent ; docker build -t docker-ssh-agent:latest -f Dockerfile . ; rm -rf /tmp/ssh-agent)
# (cd ansible; docker build -t arcodange-ansible:0.0.0 .)
docker run -d --name=ssh-agent docker-ssh-agent:latest
docker run --rm --volumes-from=ssh-agent -v ~/.ssh:/.ssh -it docker-ssh-agent:latest ssh-add /root/.ssh/id_rsa
docker run --rm -u root --name test --volumes-from=ssh-agent -v $PWD:/home/arcodange/code \
-v "$HOME"/.kube/config:/home/arcodange/.kube/config \
-e ANSIBLE_VAULT_PASSWORD_FILE=$ANSIBLE_VAULT_PASSWORD_FILE -v $ANSIBLE_VAULT_PASSWORD_FILE:$ANSIBLE_VAULT_PASSWORD_FILE \
arcodange-ansible:0.0.0 \
ansible-playbook ansible/arcodange/factory/playbooks/03_cicd.yml -i ansible/arcodange/factory/inventory -vv

use vault with single password

Important

Required for gitea mailer

kubectl create secret generic arcodange-ansible-vault --from-literal="pass=<ansible_vault_password>" -n kube-system`

to be set as a file variable for gitea runners

ANSIBLE_VAULT_PASSWORD_FILE=~/.local/bin/read-vault-key.sh;
mkdir -p `dirname $ANSIBLE_VAULT_PASSWORD_FILE`; set +o histexpand;
echo -e "#!/bin/bash\nkubectl get secret -n kube-system arcodange-ansible-vault --template='{{index .data.pass | base64decode}}'" > $ANSIBLE_VAULT_PASSWORD_FILE;
set -o histexpand; chmod +x $ANSIBLE_VAULT_PASSWORD_FILE; echo "export ANSIBLE_VAULT_PASSWORD_FILE=$ANSIBLE_VAULT_PASSWORD_FILE" >> `find ~ -maxdepth 1 -type f  -name '\.*profile' -or -name '\.bashrc' -or -name '\.zshenv' | head -n1`
export ANSIBLE_VAULT_PASSWORD_FILE

a tool to reuse a ssh agent (not required)

FIND_SSH_AGENT=$HOME/.local/bin/ssh-find-agent
curl -s https://raw.githubusercontent.com/wwalker/ssh-find-agent/master/ssh-find-agent.sh > $FIND_SSH_AGENT
chmod +x $FIND_SSH_AGENT
echo 'ssh_find_agent "$@"' >> $FIND_SSH_AGENT
which brew && brew install coreutils # if on macos
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa

dev

test an expression

ansible -i ,localhost -c local localhost -m raw -a "echo hello world {{ inventory_hostname }} : {{ hostvars | to_nice_json | regex_replace(\"['\n]\",' ') }}"

local python environment with uv

Install UV (one-time)

python3 -m pip install uv
python3 -m uv python install 3.12
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshenv

Bootstrap the project venv

uv sync                                                # honors .python-version (3.12) and pyproject.toml
uv run ansible-galaxy collection install -r ansible/requirements.yml
# `--token <token>` is only needed if you hit galaxy.ansible.com rate limits

Run

uv run ansible-galaxy collection install ./ansible/arcodange/factory -f
uv run ansible-playbook -i ansible/arcodange/factory/inventory ansible/arcodange/factory/playbooks/02_setup.yml