Aller au contenu principal
JenkinsCI/CDDevOps

Jenkins #8 — Production : HA, Backup, Monitoring et Migration

30 min de lecture Jenkins — Chapitre 8

Fais tourner Jenkins en production comme un pro : haute disponibilité, stratégies de backup, monitoring avancé et migration entre environnements.

En dev, Jenkins qui tombe c’est un inconvénient. En production, c’est un blocage total : plus de builds, plus de déploiements, plus de releases. Un Jenkins de production doit être disponible, sauvegardé, monitoré, et reconstituable rapidement.

Ce cours couvre les quatre piliers d’un Jenkins production-ready : haute disponibilité, backup/restore, monitoring, et migration.

Haute disponibilité — le Jenkins stateless

Jenkins controller est un singleton stateful — il n’y a pas de clustering natif dans la version open source. Deux controllers ne peuvent pas partager le même $JENKINS_HOME. L’approche classique active/passive avec NFS fonctionne, mais elle est fragile.

L’approche moderne recommandée : rendre Jenkins stateless et reconstituable. Tout l’état est externalisé dans des systèmes fiables.

Jenkins Controller (éphémère, recréable en 5 min)
├── Configuration   → JCasC dans Git
├── Jobs            → Multibranch Pipelines dans Git
├── Plugins         → plugins.txt dans Git
├── Credentials     → HashiCorp Vault
├── Artifacts       → S3 / Nexus / Artifactory
└── Logs            → ELK / Loki / Datadog

Le Dockerfile qui matérialise cette approche — tout est embarqué, rien n’est configuré à la main :

FROM jenkins/jenkins:lts-jdk17

COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN jenkins-plugin-cli --plugin-file /usr/share/jenkins/ref/plugins.txt

COPY casc/ /var/jenkins_home/casc_configs/
ENV CASC_JENKINS_CONFIG=/var/jenkins_home/casc_configs
ENV JAVA_OPTS="-Djenkins.install.runSetupWizard=false \
    -Xms2g -Xmx4g -XX:+UseG1GC -XX:+UseStringDeduplication"

💡 L’avantage décisif : ton Jenkins est reconstituable en minutes. Un docker build + helm upgrade et c’est reparti. Pas besoin de shared storage NFS complexe, pas de failover à gérer. Le controller meurt, Kubernetes en recrée un — les agents en vol se reconnectent automatiquement.

🔥 Sur Kubernetes : déploie Jenkins en StatefulSet avec un PVC gp3 de 50 Gi. Le chart Helm officiel gère tout : probes de santé, rolling updates, persistence. Combine avec le pattern stateless pour avoir le meilleur des deux mondes — persistence pour l’historique des builds, code pour tout le reste.

Backup et restauration

Tout l’état de Jenkins est dans $JENKINS_HOME. Mais tout n’a pas la même criticité. Les secrets (master.key, hudson.util.Secret, credentials.xml) sont irremplaçables. Les workspaces et caches sont reconstituables depuis Git.

Script de backup automatisé

#!/bin/bash
# jenkins-backup.sh — backup quotidien vers S3
set -euo pipefail

JENKINS_HOME="/var/lib/jenkins"
BACKUP_DIR="/backup/jenkins"
DATE=$(date +%Y-%m-%d_%H%M)
BACKUP_FILE="${BACKUP_DIR}/jenkins-${DATE}.tar.gz"

# Mode quiet — pas de nouveaux builds pendant le backup
curl -sf -X POST "http://localhost:8080/quietDown" \
    -u "${JENKINS_USER}:${JENKINS_TOKEN}" || true

# Attendre la fin des builds en cours (max 5 min)
for i in $(seq 1 30); do
    RUNNING=$(curl -sf "http://localhost:8080/api/json?tree=busyExecutors" \
        -u "${JENKINS_USER}:${JENKINS_TOKEN}" | jq '.busyExecutors')
    [ "${RUNNING}" = "0" ] && break
    sleep 10
done

# Backup — exclure les fichiers reconstituables
tar czf "${BACKUP_FILE}" \
    --exclude="${JENKINS_HOME}/workspace" \
    --exclude="${JENKINS_HOME}/caches" \
    --exclude="${JENKINS_HOME}/war" \
    -C "$(dirname ${JENKINS_HOME})" "$(basename ${JENKINS_HOME})"

# Réactiver les builds + upload S3
curl -sf -X POST "http://localhost:8080/cancelQuietDown" \
    -u "${JENKINS_USER}:${JENKINS_TOKEN}" || true
aws s3 cp "${BACKUP_FILE}" "s3://my-backups/jenkins/${DATE}/" --storage-class STANDARD_IA

# Rotation locale — garder 30 jours
find "${BACKUP_DIR}" -name "jenkins-*.tar.gz" -mtime +30 -delete

Tester la restauration

⚠️ Un backup non testé n’est PAS un backup. Planifie un test mensuel : extrais le backup dans un répertoire temporaire, lance un Jenkins Docker dessus, vérifie que les jobs et credentials sont intacts.

# Test de restauration automatisé
LATEST=$(ls -t /backup/jenkins/jenkins-*.tar.gz | head -1)
TEMP=$(mktemp -d)
tar xzf "${LATEST}" -C "${TEMP}"

docker run -d --name jenkins-test \
    -v "${TEMP}/jenkins:/var/jenkins_home" \
    -p 9090:8080 jenkins/jenkins:lts-jdk17

sleep 60
curl -sf http://localhost:9090/login > /dev/null \
    && echo "✅ Restore OK" || echo "❌ Restore FAILED"

docker rm -f jenkins-test && rm -rf "${TEMP}"

🎯 Cron recommandé : backup complet quotidien à 2h du matin, backup des configs seules (config.xml, credentials.xml, secrets/) toutes les 6h. Le backup complet prend 5-10 minutes pour un Jenkins moyen, le backup config prend 2 secondes.

Monitoring avec Prometheus et Grafana

Le plugin Prometheus expose les métriques Jenkins sur /prometheus/. Combine avec Grafana pour un dashboard temps réel et des alertes proactives.

Métriques clés à surveiller

Les quatre métriques qui couvrent 90% des problèmes Jenkins :

  • jenkins_queue_size_value — jobs en attente. Si > 10 pendant 15 min, tu manques d’agents
  • jenkins_executor_in_use_value — saturation des agents. Au-dessus de 90%, les builds ralentissent
  • vm_memory_heap_usage — mémoire JVM du controller. Alerte à 80%, crash imminent à 95%
  • Taux d’échec — ratio builds failed / total. Au-dessus de 30% sur 1h, quelque chose est cassé

Alertes Prometheus

# prometheus-rules.yaml
groups:
  - name: jenkins
    rules:
      - alert: JenkinsQueueTooLong
        expr: jenkins_queue_size_value > 10
        for: 15m
        labels: { severity: warning }
        annotations:
          summary: "{{ $value }} jobs en attente depuis 15 min"

      - alert: JenkinsDown
        expr: up{job="jenkins"} == 0
        for: 5m
        labels: { severity: critical }
        annotations:
          summary: "Jenkins est down depuis 5 minutes"

      - alert: JenkinsHighFailureRate
        expr: >
          rate(default_jenkins_builds_failed_build_count[1h])
          / (rate(default_jenkins_builds_success_build_count[1h])
          + rate(default_jenkins_builds_failed_build_count[1h])) > 0.3
        for: 30m
        labels: { severity: warning }
        annotations:
          summary: "Taux d'échec Jenkins à {{ $value | humanizePercentage }}"

💡 Dashboard Grafana #9964 — c’est le dashboard communautaire de référence pour Jenkins. Importe-le et adapte-le à ton contexte. Il couvre les builds, la queue, les agents, la JVM et l’espace disque.

🔥 Logs centralisés : envoie les logs Jenkins vers Loki (léger) ou ELK (complet) avec Promtail ou Filebeat. Les logs de build dans $JENKINS_HOME/jobs/*/builds/*/log sont précieux pour le debugging post-mortem. Sans centralisation, ils disparaissent quand le disque est purgé.

Migration et maintenance

Migration VM → Kubernetes

La migration se fait en quatre étapes : backup, création du PVC, copie des données, déploiement Helm.

# 1. Backup du Jenkins actuel (sans workspace/caches)
tar czf jenkins-migration.tar.gz \
    --exclude='workspace' --exclude='caches' /var/lib/jenkins/

# 2. Pod temporaire pour copier vers le PVC
kubectl run jenkins-copy --image=alpine --command -- sleep infinity \
    --overrides='{"spec":{"containers":[{"name":"alpine","image":"alpine",
    "command":["sleep","infinity"],"volumeMounts":[{"name":"data",
    "mountPath":"/jenkins"}]}],"volumes":[{"name":"data",
    "persistentVolumeClaim":{"claimName":"jenkins-pvc"}}]}}'

# 3. Copier et décompresser
kubectl cp jenkins-migration.tar.gz default/jenkins-copy:/tmp/
kubectl exec jenkins-copy -- tar xzf /tmp/jenkins-migration.tar.gz -C /jenkins/
kubectl exec jenkins-copy -- chown -R 1000:1000 /jenkins/
kubectl delete pod jenkins-copy

# 4. Déployer Jenkins avec le PVC existant
helm install jenkins jenkins/jenkins \
    --set persistence.existingClaim=jenkins-pvc \
    --values jenkins-values.yaml

Maintenance régulière

Un Jenkins de production nécessite une maintenance proactive. Sans elle, le disque se remplit, les plugins deviennent vulnérables, et les performances se dégradent silencieusement.

⚠️ Nettoyage des vieux builds : configure un buildDiscarder dans chaque pipeline avec logRotator(daysToKeepStr: '90', numToKeepStr: '50'). Sans ça, un job qui tourne 10 fois par jour accumule 3600 builds par an — chacun avec ses logs, artefacts et métadonnées.

⚠️ Mises à jour Jenkins : teste d’abord sur un environnement de staging. Ne fais jamais une mise à jour majeure un vendredi. Garde toujours un backup pré-upgrade. Si ça casse, downgrade le package et restaure le backup.

⚠️ JVM Tuning : commence avec -Xms2g -Xmx4g -XX:+UseG1GC. Augmente le heap si tu vois des OutOfMemoryError dans les logs. Le G1GC est le meilleur choix pour Jenkins — pauses courtes et prédictibles.

🎯 Checklist maintenance mensuelle :

  • Vérifier les plugins avec des mises à jour de sécurité
  • Tester la restauration du backup
  • Nettoyer les workspaces orphelins
  • Vérifier l’espace disque et les métriques JVM
  • Auditer les credentials inutilisés
  • Revoir les permissions RBAC

Résumé de la série Jenkins

En 8 cours, tu as couvert tout ce qu’il faut pour déployer et opérer un Jenkins de production :

  • Cours 1-3 : les fondations — installation, pipelines déclaratifs et avancés, shared libraries
  • Cours 4-5 : l’écosystème — plugins essentiels, intégration Docker, DinD vs Kaniko
  • Cours 6 : le scaling — Jenkins sur Kubernetes avec Helm, pod templates, agents dynamiques
  • Cours 7-8 : la production — sécurité RBAC, backup, monitoring, migration

Les trois règles d’or qui résument tout : Pipeline as Code (Jenkinsfile dans Git, toujours), agents éphémères (Docker ou K8s, jamais de builds sur le controller), Configuration as Code (JCasC + plugins.txt versionnés). Avec ces trois principes, ton Jenkins est reproductible, scalable et maintenable.

🖥️ Pratique sur ton propre serveur

Pour suivre Jenkins en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.

Obtenir 200$

Articles liés