Centralisation des Tâches Planifiées (Cronjob Docker)
Centralisation des Tâches Planifiées (Cronjob Docker)
Ce projet documente la mise en place d'un conteneur Docker dédié à l'exécution centralisée de tâches planifiées. Il repose sur une image outillée (ansible, python, bash) et l'orchestrateur Supercronic.
Architecture Technique
- Conteneur : Image basée sur Alpine Linux avec outils DevOps (
cytopia/ansible:latest-tools). - Ordonnanceur : Supercronic (alternative à cron native pour Docker, gérant mieux les logs et signaux).
- Monitoring : Wrapper Bash interceptant les codes de sortie pour l'envoi d'alertes SMTP.
- Réseau : Mode
hostprivilégié pour faciliter l'interaction avec le réseau local.
Configuration Docker Compose
Démarrage du service avec montage des volumes nécessaires (scripts, clés SSH, données).
services:
cronjob:
container_name: cronjob
restart: always
image: cytopia/ansible:latest-tools
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TIME_ZONE}
volumes:
- './scripts:/cronjob' # Scripts à exécuter
- './ssh_keys:/home/user/.ssh' # Clés pour connexions distantes
- './ansible:/ansible' # Configuration Ansible
- '/data/downloads:/downloads' # Accès aux données partagées
command: >
/bin/sh -c "/cronjob/setup.sh"
network_mode: host
Logique d'Initialisation (setup.sh)
Le script de démarrage assure l'installation des dépendances et la configuration de l'environnement à la volée.
Installation de Supercronic
Téléchargement et mise en place du binaire Supercronic pour gérer les crons dans un environnement conteneurisé.
# (Exemple simplifié)
SUPERCRONIC_URL="https://github.com/aptible/supercronic/releases/..."
curl -fsSLO "$SUPERCRONIC_URL"
chmod +x "$SUPERCRONIC"
Wrapper de Supervision
Un script intermédiaire (cron-wrapper) est généré pour encapsuler chaque job. Il détecte les codes d'erreur critiques (1 ou 2) et déclenche une notification par email.
#!/bin/bash
CMD="$@"
"$@"
EXIT_CODE=$?
# Si erreur critique, envoi de mail via curl SMTP
if [ "$EXIT_CODE" -eq 1 ] || [ "$EXIT_CODE" -eq 2 ]; then
(
echo "Subject: Alerte Cronjob - Erreur $EXIT_CODE"
echo "La commande '$CMD' a échoué."
) | curl --url "smtp://smtp.server.local:25" \
--mail-from "cron@domain.tld" \
--mail-rcpt "admin@domain.tld" \
--upload-file -
fi
exit $EXIT_CODE
Définition du Crontab
Le fichier crontab est généré dynamiquement lors du lancement. Chaque tâche est préfixée par le wrapper.
cat > /etc/crontabs/root << 'EOF'
# Maintenance Infrastructure
0 4 * * 2 /usr/local/bin/cron-wrapper /cronjob/maintenance.sh
# Monitoring & Sécurité
15 */1 * * * /usr/local/bin/cron-wrapper /cronjob/check_status.sh
0 6 * * * /usr/local/bin/cron-wrapper /cronjob/security_update.sh
# Tâches Applicatives (Nettoyage, Sync)
*/10 * * * * /usr/local/bin/cron-wrapper python3 /cronjob/content_cleaner.py
EOF
exec supercronic /etc/crontabs/root
Script d'Exécution Ansible (ansible.sh)
Ce script est utilisé pour l'exécution des playbooks Ansible. Il gère :
* Le chargement des variables d'environnement (notamment le mot de passe Vault).
* La configuration de ansible.cfg et du fichier de mot de passe Vault.
* L'exécution d'un playbook spécifique (option -c) ou de tous les playbooks trouvés.
* La journalisation des exécutions.
#!/bin/bash
LOG_DIR="/ansible/log"
ANSIBLE_USER_DIR="/home/user"
TIMESTAMP=$(date +'%Y%m%d_%H%M%S')
LOG_FILE="$LOG_DIR/.$TIMESTAMP-ansible_result.txt"
ENV_FILE="$ANSIBLE_USER_DIR/.env"
VAULT_PASSWORD=""
if [[ -f "$ENV_FILE" ]]; then
set -o allexport
# shellcheck disable=SC1090
. "$ENV_FILE"
set +o allexport
fi
VAULT_PASSWORD="${ANSIBLE_PASSWD}"
if [[ -z "$VAULT_PASSWORD" ]]; then
echo "Vault password not configured" >&2
exit 1
fi
mkdir /etc/ansible 2>/dev/null
rm /etc/ansible/uid 2>/dev/null
printf '%s\n' "$VAULT_PASSWORD" >/etc/ansible/uid
rsync -a "$ANSIBLE_USER_DIR/variable-ansible_config.cfg" /etc/ansible/ansible.cfg
SINGLE_PLAYBOOK=""
while getopts ":c:" opt; do
case $opt in
c)
SINGLE_PLAYBOOK="$OPTARG"
;;
\?)
echo "Option invalide: -$OPTARG" >&2
exit 1
;;
:)
echo "L'option -c requiert un argument" >&2
exit 1
;;
esac
done
shift $((OPTIND - 1))
if [[ -n "$SINGLE_PLAYBOOK" ]]; then
SINGLE_PLAYBOOK_PATH="$ANSIBLE_USER_DIR/$SINGLE_PLAYBOOK"
if [[ ! -f "$SINGLE_PLAYBOOK_PATH" ]]; then
echo "Playbook demandé introuvable : $SINGLE_PLAYBOOK_PATH" >&2
exit 1
fi
PLAYBOOKS="$SINGLE_PLAYBOOK_PATH"
else
PLAYBOOKS=$(find "$ANSIBLE_USER_DIR" -maxdepth 1 -name "playbook*.yaml" -type f | sort)
fi
echo "Playbooks à exécuter :"
echo "$PLAYBOOKS"
echo "$PLAYBOOKS" | xargs -I {} bash -c '
echo "--- $(date "+%Y-%m-%d %H:%M:%S") - Début de l''exécution de {} ---" >> "$1"
ansible-playbook -i "$2/variable_ansible_inventory.yaml" {} >> "$1" 2>&1
echo "--- $(date "+%Y-%m-%d %H:%M:%S") - Fin de l''exécution de {} ---" >> "$1"
echo "" >> "$1"
' _ "$LOG_FILE" "$ANSIBLE_USER_DIR"
echo "Nettoyage des anciens fichiers de log..."
ls -1t "$LOG_DIR"/.*-ansible_result.txt | tail -n +10 | xargs -d '\n' -- rm -f
Stratégie de Planification
Les tâches sont réparties pour lisser la charge sur l'infrastructure :
| Type | Fréquence | Usage |
|---|---|---|
| Maintenance | Hebdomadaire | Mises à jour lourdes, backups Ansible. |
| Sécurité | Quotidien (Matin) | Mise à jour des listes de blocage (Crowdsec/Firewall). |
| Applicatif | Toutes les 4h | Rafraîchissement des caches applications / clients lourds. |
| Surveillance | Fréquent (10-15min) | Vérification de services, rechargement de confs, alertes temps réel. |