Skip to content

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 host privilé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.