## Introduction

Les Jobs Kubernetes sont essentiels pour exécuter des charges de travail par lots, telles que le traitement de données, les sauvegardes ou les tâches de maintenance. Mettre à niveau ou migrer un Job implique de modifier sa spécification, son image ou son environnement, et peut introduire des échecs si cela n'est pas géré avec soin. Ce guide propose une approche pratique pour planifier et exécuter les mises à niveau et migrations de Jobs avec un risque minimal. Nous couvrirons l'inventaire de l'environnement, les stratégies de configuration, la vérification, la récupération en cas d'échec et une liste de contrôle opérationnelle. En suivant ces étapes, vous pouvez réduire les retouches et assurer une transition fluide pour vos charges de travail par lots.

## Inventaire des versions et de l'environnement

Avant d'apporter des modifications, vous devez avoir une vision claire de votre environnement actuel. Cela inclut la version de Kubernetes, la spécification actuelle du Job et toutes les dépendances. Commencez par vérifier la version de votre cluster :

kubectl version --short 
 Sortie attendue :

Client Version: v1.24.0
Server Version: v1.23.5 
 Ensuite, listez les Jobs existants dans votre espace de noms :

kubectl get jobs -n <namespace> 
 Exemple de sortie :

NAME COMPLETIONS DURATION AGE
data-import-2023 1/1 2m 3d 
 Inspectez le manifeste actuel du Job pour comprendre sa configuration :

kubectl get job <job-name> -n <namespace> -o yaml 
 Examinez les champs comme spec.template.spec.containers[].image , les variables d'environnement, les limites de ressources et la politique de redémarrage. Notez toutes les ConfigMaps, Secrets ou PersistentVolumeClaims utilisées par le Job. Vérifiez que vous disposez des autorisations nécessaires pour créer, mettre à jour et supprimer des Jobs dans l'espace de noms. Vérifiez également si le Job est géré par un CronJob ; si c'est le cas, vous devrez mettre à jour la spécification du CronJob plutôt que le Job directement.

Documentez l'état actuel, y compris les paramètres de complétion et de parallélisme du Job, la limite de backoff et la durée limite active. Cet inventaire servira de base de référence pour un retour arrière si nécessaire.

### Exemple : manifeste de base d'un Job

Voici un exemple de manifeste de Job que vous pourriez rencontrer :

apiVersion: batch/v1
kind: Job
metadata:
 name: data-import-2023
spec:
 completions: 1
 parallelism: 1
 backoffLimit: 4
 activeDeadlineSeconds: 100
 template:
 spec:
 containers:
 - name: importer
 image: myapp:v1
 env:
 - name: DB_HOST
 valueFrom:
 configMapKeyRef:
 name: db-config
 key: host
 resources:
 requests:
 memory: "64Mi"
 cpu: "250m"
 limits:
 memory: "128Mi"
 cpu: "500m"
 restartPolicy: Never 
 Enregistrez ce manifeste de base à l'aide de la commande :

kubectl get job data-import-2023 -n <namespace> -o yaml > data-import-2023-backup.yaml 
 Cette sauvegarde est cruciale pour un retour arrière si quelque chose tourne mal pendant la migration.

<style>
.eno-quiz-widget{margin:2rem 0;padding:1.5rem;border-radius:12px;background:var(--eno-surface-lowest,#f7f7f8);border:1px solid var(--eno-border-soft,#e2e2e6);font-family:var(--eno-font-body,Inter,sans-serif)}
.eno-quiz-widget .eno-quiz-kicker{font-family:var(--eno-font-label,"JetBrains Mono",monospace);font-size:.75rem;letter-spacing:.05em;text-transform:uppercase;color:var(--eno-text-muted,#5f5f68);margin:0 0 .5rem}
.eno-quiz-widget .eno-quiz-question{font-family:var(--eno-font-heading,"Hanken Grotesk",sans-serif);font-size:1.0625rem;font-weight:600;margin:0 0 1rem;color:var(--eno-text-strong,#1a1a1f)}
.eno-quiz-widget .eno-quiz-options{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.5rem}
.eno-quiz-widget .eno-quiz-option{display:block;width:100%;min-height:44px;text-align:left;padding:.625rem .875rem;border-radius:8px;border:1.5px solid var(--eno-border-soft,#e2e2e6);background:#fff;font-size:.9375rem;cursor:pointer;transition:border-color var(--eno-motion-base,180ms ease-out),background var(--eno-motion-base,180ms ease-out)}
.eno-quiz-widget .eno-quiz-option:hover{border-color:var(--eno-primary,#0059bb)}
.eno-quiz-widget .eno-quiz-option:focus-visible{outline:none;box-shadow:0 0 0 3px rgb(0 89 187 / 0.15)}
.eno-quiz-widget .eno-quiz-option[aria-pressed="true"]{border-color:var(--eno-primary,#0059bb);background:rgb(0 89 187 / 0.06)}
.eno-quiz-widget .eno-quiz-option[data-correct="true"].eno-quiz-revealed{border-color:var(--eno-success,#17803a);background:rgb(23 128 58 / 0.08)}
.eno-quiz-widget .eno-quiz-option[data-correct="false"].eno-quiz-revealed.eno-quiz-was-selected{border-color:var(--eno-error,#ba1a1a);background:var(--eno-error-soft,#ffdad6)}
.eno-quiz-widget .eno-quiz-option-icon{display:inline-block;width:1.1em;margin-right:.4em;font-weight:700}
.eno-quiz-widget .eno-quiz-submit{margin-top:1rem;min-height:44px;padding:.5rem 1.25rem;border-radius:8px;border:none;background:var(--eno-primary,#0059bb);color:#fff;font-weight:600;font-size:.9375rem;cursor:pointer;transition:opacity var(--eno-motion-base,180ms ease-out)}
.eno-quiz-widget .eno-quiz-submit:disabled{opacity:.5;cursor:not-allowed}
.eno-quiz-widget .eno-quiz-submit:focus-visible{outline:none;box-shadow:0 0 0 3px rgb(0 89 187 / 0.15)}
.eno-quiz-widget .eno-quiz-explanation{margin-top:1rem;padding:.875rem 1rem;border-radius:8px;font-size:.9375rem;line-height:1.5;display:none}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-visible{display:block}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-correct{background:rgb(23 128 58 / 0.08);color:var(--eno-success,#17803a)}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-incorrect{background:var(--eno-error-soft,#ffdad6);color:var(--eno-error,#ba1a1a)}
@media (prefers-reduced-motion: reduce){.eno-quiz-widget *{transition:none!important}}
</style><div class="eno-quiz-widget" role="group" aria-label="Question rapide">
Question rapide 1 sur 2

Quelle est la méthode recommandée pour mettre à niveau ou migrer un Job Kubernetes afin de minimiser les risques ?

- Modifier le Job existant sur place pour changer son image.
- Créer un nouveau Job avec un nom différent et une spécification mise à jour, puis basculer les dépendances après validation.
- Supprimer immédiatement le Job existant et le recréer avec le même nom.
- Utiliser kubectl edit job pour mettre à jour le Job directement.

<button type="button" class="eno-quiz-submit" disabled>Valider</button>
<div class="eno-quiz-explanation">Le guide recommande d&#39;éviter les modifications sur place et de créer plutôt un nouveau Job avec un nom différent pour des tests côte à côte et une restauration facile.</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
  document.querySelectorAll('.eno-quiz-widget:not([data-eno-quiz-bound])').forEach(function (widget) {
    widget.setAttribute('data-eno-quiz-bound', '1');
    var options = Array.prototype.slice.call(widget.querySelectorAll('.eno-quiz-option'));
    var submitBtn = widget.querySelector('.eno-quiz-submit');
    var explanation = widget.querySelector('.eno-quiz-explanation');
    var selected = null;
    options.forEach(function (opt) {
      opt.addEventListener('click', function () {
        if (widget.hasAttribute('data-eno-quiz-answered')) return;
        options.forEach(function (o) { o.setAttribute('aria-pressed', 'false'); });
        opt.setAttribute('aria-pressed', 'true');
        selected = opt;
        submitBtn.disabled = false;
      });
    });
    submitBtn.addEventListener('click', function () {
      if (!selected || widget.hasAttribute('data-eno-quiz-answered')) return;
      widget.setAttribute('data-eno-quiz-answered', '1');
      submitBtn.disabled = true;
      var correct = selected.getAttribute('data-correct') === 'true';
      options.forEach(function (o) {
        o.classList.add('eno-quiz-revealed');
        if (o === selected) o.classList.add('eno-quiz-was-selected');
        var icon = o.querySelector('.eno-quiz-option-icon');
        if (o.getAttribute('data-correct') === 'true') icon.textContent = '\u2713';
        else if (o === selected) icon.textContent = '\u2717';
      });
      explanation.classList.add('eno-quiz-visible', correct ? 'eno-quiz-correct' : 'eno-quiz-incorrect');
    });
  });
});
</script>

## Chemin de configuration sûr

Lors de la mise à niveau ou de la migration d'un Job, évitez de modifier le Job existant sur place si possible. Créez plutôt un nouveau Job avec la spécification mise à jour et un nom différent, puis basculez le trafic ou les dépendances vers celui-ci après validation. Cela permet des tests côte à côte et un retour arrière facile.

Par exemple, supposons que vous deviez mettre à jour l'image d'un Job de traitement de données de myapp:v1 à myapp:v2 . Créez un nouveau manifeste de Job, disons data-process-v2.yaml :

apiVersion: batch/v1
kind: Job
metadata:
 name: data-process-v2
 labels:
 app: data-process
 version: v2
spec:
 template:
 spec:
 containers:
 - name: processor
 image: myapp:v2
 # autres paramètres identiques à l'original
 restartPolicy: Never
 backoffLimit: 4 
 Appliquez le nouveau Job :

kubectl apply -f data-process-v2.yaml -n <namespace> 
 Avant d'appliquer, envisagez d'utiliser kubectl diff pour voir les changements :

kubectl diff -f data-process-v2.yaml 
 Cette commande affiche les différences entre l'état actuel et le manifeste proposé, vous aidant à repérer les modifications non intentionnelles.

Si le Job fait partie d'un flux de travail plus large (par exemple, déclenché par un système externe), vous devrez peut-être mettre à jour le déclencheur pour pointer vers le nouveau nom de Job. Pour les CronJobs, mettez à jour le spec.jobTemplate du CronJob avec la nouvelle image, et conservez éventuellement l'historique de l'ancien Job pour un retour arrière.

Utilisez des étiquettes et des annotations pour suivre les versions. Par exemple :

metadata:
 labels:
 app: data-process
 version: v2 
 Cela facilite le filtrage et la gestion des Jobs.

Si vous devez modifier un Job existant sur place, sachez que certains champs sont immuables après la création (par exemple, spec.template ). Dans ce cas, vous devez supprimer et recréer, mais cela peut entraîner une interruption. L'approche côte à côte est plus sûre.

### Mise à jour d'un CronJob

Si votre Job est géré par un CronJob, mettez à jour le manifeste du CronJob plutôt que le Job directement. Par exemple, pour mettre à jour l'image dans un CronJob :

kubectl edit cronjob my-cronjob -n <namespace> 
 Dans l'éditeur, modifiez l'image dans spec.jobTemplate.spec.template.spec.containers[].image pour myapp:v2 . Enregistrez et quittez. Le contrôleur CronJob utilisera la nouvelle image pour les exécutions suivantes. Les Jobs existants créés par le CronJob ne seront pas affectés ; ils continueront jusqu'à leur achèvement avec l'ancienne spécification.

Pour tester la nouvelle image sans attendre la prochaine planification, vous pouvez créer manuellement un Job à partir du CronJob :

kubectl create job manual-test --from=cronjob/my-cronjob -n <namespace> 
 Cela crée un Job utilisant le modèle actuel du CronJob, vous permettant de vérifier les changements immédiatement.

## Vérification et diagnostics

Après avoir déployé le nouveau Job, vous devez vérifier qu'il fonctionne correctement. Utilisez kubectl describe pour voir les événements :

kubectl describe job data-process-v2 -n <namespace> 
 Vérifiez le statut du Job :

kubectl get job data-process-v2 -n <namespace> -o yaml 
 Recherchez les compteurs status.succeeded et status.failed . Surveillez les journaux du Pod créé par le Job :

kubectl logs job/data-process-v2 -n <namespace> 
 Sortie attendue (exemple) :

Traitement du fichier 1 sur 100
Traitement du fichier 2 sur 100
...
Job terminé avec succès. 
 Si le Job est toujours en cours d'exécution, vous pouvez surveiller sa progression :

kubectl get pods -l job-name=data-process-v2 -n <namespace> --watch 
 Configurez des alertes ou des notifications pour l'achèvement/échec du Job si vous utilisez un système de surveillance. Pour une vérification rapide, vous pouvez exécuter une commande qui attend l'achèvement :

kubectl wait --for=condition=complete job/data-process-v2 --timeout=300s -n <namespace> 
 Si le Job échoue, inspectez les journaux du Pod pour détecter les erreurs et ajustez. Vous pouvez également vérifier l'utilisation des ressources pour vous assurer que la nouvelle version ne dépasse pas les limites.

### Exemple : vérification d'un Job réussi

Après avoir appliqué le nouveau Job, exécutez :

kubectl get job data-process-v2 -n <namespace> -o jsonpath='{.status.succeeded}' 
 Si la sortie est 1 , le Job s'est terminé avec succès. Vous pouvez également vérifier l'heure d'achèvement :

kubectl get job data-process-v2 -n <namespace> -o jsonpath='{.status.completionTime}' 
 Comparez cela avec les métriques du Job précédent pour vous assurer que les performances sont acceptables.

<style>
.eno-quiz-widget{margin:2rem 0;padding:1.5rem;border-radius:12px;background:var(--eno-surface-lowest,#f7f7f8);border:1px solid var(--eno-border-soft,#e2e2e6);font-family:var(--eno-font-body,Inter,sans-serif)}
.eno-quiz-widget .eno-quiz-kicker{font-family:var(--eno-font-label,"JetBrains Mono",monospace);font-size:.75rem;letter-spacing:.05em;text-transform:uppercase;color:var(--eno-text-muted,#5f5f68);margin:0 0 .5rem}
.eno-quiz-widget .eno-quiz-question{font-family:var(--eno-font-heading,"Hanken Grotesk",sans-serif);font-size:1.0625rem;font-weight:600;margin:0 0 1rem;color:var(--eno-text-strong,#1a1a1f)}
.eno-quiz-widget .eno-quiz-options{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.5rem}
.eno-quiz-widget .eno-quiz-option{display:block;width:100%;min-height:44px;text-align:left;padding:.625rem .875rem;border-radius:8px;border:1.5px solid var(--eno-border-soft,#e2e2e6);background:#fff;font-size:.9375rem;cursor:pointer;transition:border-color var(--eno-motion-base,180ms ease-out),background var(--eno-motion-base,180ms ease-out)}
.eno-quiz-widget .eno-quiz-option:hover{border-color:var(--eno-primary,#0059bb)}
.eno-quiz-widget .eno-quiz-option:focus-visible{outline:none;box-shadow:0 0 0 3px rgb(0 89 187 / 0.15)}
.eno-quiz-widget .eno-quiz-option[aria-pressed="true"]{border-color:var(--eno-primary,#0059bb);background:rgb(0 89 187 / 0.06)}
.eno-quiz-widget .eno-quiz-option[data-correct="true"].eno-quiz-revealed{border-color:var(--eno-success,#17803a);background:rgb(23 128 58 / 0.08)}
.eno-quiz-widget .eno-quiz-option[data-correct="false"].eno-quiz-revealed.eno-quiz-was-selected{border-color:var(--eno-error,#ba1a1a);background:var(--eno-error-soft,#ffdad6)}
.eno-quiz-widget .eno-quiz-option-icon{display:inline-block;width:1.1em;margin-right:.4em;font-weight:700}
.eno-quiz-widget .eno-quiz-submit{margin-top:1rem;min-height:44px;padding:.5rem 1.25rem;border-radius:8px;border:none;background:var(--eno-primary,#0059bb);color:#fff;font-weight:600;font-size:.9375rem;cursor:pointer;transition:opacity var(--eno-motion-base,180ms ease-out)}
.eno-quiz-widget .eno-quiz-submit:disabled{opacity:.5;cursor:not-allowed}
.eno-quiz-widget .eno-quiz-submit:focus-visible{outline:none;box-shadow:0 0 0 3px rgb(0 89 187 / 0.15)}
.eno-quiz-widget .eno-quiz-explanation{margin-top:1rem;padding:.875rem 1rem;border-radius:8px;font-size:.9375rem;line-height:1.5;display:none}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-visible{display:block}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-correct{background:rgb(23 128 58 / 0.08);color:var(--eno-success,#17803a)}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-incorrect{background:var(--eno-error-soft,#ffdad6);color:var(--eno-error,#ba1a1a)}
@media (prefers-reduced-motion: reduce){.eno-quiz-widget *{transition:none!important}}
</style><div class="eno-quiz-widget" role="group" aria-label="Question rapide">
Question rapide 2 sur 2

Quelle commande peut être utilisée pour afficher les différences entre l'état actuel et un manifeste de Job proposé avant de l'appliquer ?

- kubectl get job <name> -o yaml
- kubectl describe job <name>
- kubectl diff -f <file>
- kubectl apply --dry-run=client -f <file>

<button type="button" class="eno-quiz-submit" disabled>Valider</button>
<div class="eno-quiz-explanation">Le guide indique : « Avant d&#39;appliquer, envisagez d&#39;utiliser kubectl diff pour voir les modifications : kubectl diff -f data-process-v2.yaml ».</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
  document.querySelectorAll('.eno-quiz-widget:not([data-eno-quiz-bound])').forEach(function (widget) {
    widget.setAttribute('data-eno-quiz-bound', '1');
    var options = Array.prototype.slice.call(widget.querySelectorAll('.eno-quiz-option'));
    var submitBtn = widget.querySelector('.eno-quiz-submit');
    var explanation = widget.querySelector('.eno-quiz-explanation');
    var selected = null;
    options.forEach(function (opt) {
      opt.addEventListener('click', function () {
        if (widget.hasAttribute('data-eno-quiz-answered')) return;
        options.forEach(function (o) { o.setAttribute('aria-pressed', 'false'); });
        opt.setAttribute('aria-pressed', 'true');
        selected = opt;
        submitBtn.disabled = false;
      });
    });
    submitBtn.addEventListener('click', function () {
      if (!selected || widget.hasAttribute('data-eno-quiz-answered')) return;
      widget.setAttribute('data-eno-quiz-answered', '1');
      submitBtn.disabled = true;
      var correct = selected.getAttribute('data-correct') === 'true';
      options.forEach(function (o) {
        o.classList.add('eno-quiz-revealed');
        if (o === selected) o.classList.add('eno-quiz-was-selected');
        var icon = o.querySelector('.eno-quiz-option-icon');
        if (o.getAttribute('data-correct') === 'true') icon.textContent = '\u2713';
        else if (o === selected) icon.textContent = '\u2717';
      });
      explanation.classList.add('eno-quiz-visible', correct ? 'eno-quiz-correct' : 'eno-quiz-incorrect');
    });
  });
});
</script>

## Modes d'échec et récupération

Les Jobs peuvent échouer pour diverses raisons : erreurs de tirage d'image, plantages d'application, épuisement des ressources, mauvaise configuration ou problèmes de dépendances externes. La politique de redémarrage du Job ( restartPolicy: Never ou OnFailure ) et la backoffLimit déterminent comment les échecs sont gérés.

Modes d'échec courants :

- Erreur de tirage d'image : Vérifiez le nom de l'image, l'étiquette, les identifiants du registre.

- CrashLoopBackOff : Erreur d'application ou configuration manquante.

- OOMKilled : Limites de ressources trop basses.

- Délai dépassé : activeDeadlineSeconds réglé trop bas.

Pour récupérer, diagnostiquez d'abord avec kubectl describe pod et kubectl logs . Par exemple :

kubectl describe pod <pod-name> -n <namespace> 
 Recherchez des événements comme Failed to pull image ou Back-off restarting failed container .

Si le nouveau Job échoue, vous pouvez revenir en arrière en rebasculant vers l'ancien Job (s'il est toujours disponible) ou en inversant le mécanisme de déclenchement. Si vous avez utilisé un déploiement côte à côte, l'ancien Job reste intact. Si vous avez modifié sur place, vous devrez peut-être recréer l'ancien Job à partir de votre manifeste de base.

Pour un Job en échec, vous pouvez également ajuster le manifeste et le réappliquer, mais notez que les Jobs sont immuables dans certains champs. Il est souvent plus facile de supprimer et de créer un nouveau Job avec un nom différent.

Exemple de commande de retour arrière :

kubectl delete job data-process-v2 -n <namespace>
kubectl apply -f data-process-v1.yaml -n <namespace> 
 Conservez toujours des sauvegardes des manifestes de Jobs précédents et de toutes les ConfigMaps ou Secrets associés.

### Stratégie de retour arrière

Une stratégie de retour arrière robuste implique d'avoir des manifestes versionnés. Stockez chaque manifeste de Job dans un contrôle de version. Par exemple, conservez data-process-v1.yaml et data-process-v2.yaml dans un dépôt Git. Si la nouvelle version échoue, exécutez :

kubectl delete job data-process-v2 -n <namespace>
kubectl apply -f data-process-v1.yaml -n <namespace> 
 Cela recrée l'ancien Job. Cependant, notez que ce nouveau Job aura un UID différent et devra peut-être être traité comme une nouvelle exécution. Assurez-vous que tous les systèmes externes qui déclenchent le Job sont mis à jour pour faire référence au nom correct.

## Liste de contrôle opérationnelle

Utilisez cette liste de contrôle pour garantir une mise à niveau ou une migration de Job fluide :

<div class="my-stack-md overflow-x-auto">
<table class="min-w-[42rem] border-collapse text-left">
<thead><tr><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Étape</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Action</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Commande/Notes</th></tr></thead>
<tbody><tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">1</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Vérifier les versions du cluster et du Job</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl version</code>, <code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl get job &lt;name&gt; -o yaml</code></td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">2</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Sauvegarder les manifestes actuels</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl get job &lt;name&gt; -o yaml &gt; job-backup.yaml</code></td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">3</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Créer un nouveau manifeste de Job avec les changements</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Modifier le YAML avec la nouvelle image/config</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">4</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Diffuser avant d&#39;appliquer</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl diff -f new-job.yaml</code></td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">5</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Appliquer le nouveau Job</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl apply -f new-job.yaml</code></td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">6</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Surveiller le statut du Job</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl get jobs -w</code></td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">7</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Vérifier les journaux pour les erreurs</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl logs job/&lt;name&gt;</code></td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">8</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Vérifier l&#39;achèvement</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl wait --for=condition=complete job/&lt;name&gt; --timeout=300s</code></td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">9</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Mettre à jour les dépendances/déclencheurs</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Mettre à jour le CronJob ou les systèmes externes</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">10</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Nettoyer l&#39;ancien Job s&#39;il n&#39;est plus nécessaire</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl delete job &lt;old-name&gt;</code> (après validation)</td></tr></tbody>
</table>
</div>
Examinez chaque étape avant de procéder. Automatisez lorsque c'est possible à l'aide de scripts ou de CI/CD, mais assurez des vérifications manuelles pour les changements critiques.

### Exemple de liste de contrôle pré-migration

Avant d'exécuter la migration, passez en revue cette liste de contrôle :

- [ ] La version du cluster répond à l'exigence minimale pour la nouvelle image (par exemple, Kubernetes v1.20+).

- [ ] Le manifeste actuel du Job est sauvegardé dans le contrôle de version.

- [ ] La nouvelle image a été testée dans un environnement de préproduction.

- [ ] Les quotas de ressources dans l'espace de noms permettent le nouveau Job.

- [ ] Le plan de retour arrière est documenté et testé.

- [ ] Les membres de l'équipe sont informés de la fenêtre de migration.

## Conclusion

La mise à niveau et la migration des Jobs Kubernetes nécessitent une planification et une exécution minutieuses. En inventoriant votre environnement, en utilisant des déploiements côte à côte, en vérifiant avec des contrôles observables et en ayant un plan de retour arrière, vous pouvez minimiser les risques et les temps d'arrêt. Suivez la liste de contrôle opérationnelle pour garantir la cohérence. Un processus de migration clair réduit les retouches et aide votre équipe à gérer les charges de travail par lots en toute confiance. Commencez par un pilote étroit pour valider les changements avant un déploiement plus large, et gardez toujours des options de retour arrière disponibles.