## Introduction

Server-side apply (SSA) change la façon dont Kubernetes gère la configuration des objets. Au lieu de compter sur `kubectl` pour calculer une fusion à trois voies côté client, le serveur d'API Kubernetes effectue la fusion et enregistre la propriété des champs. Ce changement est important pour l'automatisation CI/CD car il supprime l'ambiguïté sur qui a modifié un champ et empêche les écrasements accidentels entre les contrôleurs, les outils GitOps et les modifications manuelles.

Ce guide se concentre sur l'utilisation opérationnelle : activer SSA, construire un pipeline qui applique les manifestes en toute sécurité, détecter les conflits avant qu'ils ne cassent un déploiement, et revenir en arrière lorsqu'un changement tourne mal. Il inclut les commandes exactes, les sorties attendues et les signaux d'échec que vous verrez dans un vrai cluster.

Vous aurez besoin d'un cluster Kubernetes en cours d'exécution (version 1.16+ pour le SSA de base, 1.18+ pour la gestion complète des champs), de `kubectl` version 1.22+ recommandé, et d'un espace de noms où vous pouvez tester en toute sécurité.

## Inventaire des versions et de l'environnement

Avant d'utiliser SSA dans un pipeline, confirmez que votre cluster, votre client et vos ressources API prennent en charge la fonctionnalité. Exécutez d'abord ces vérifications en lecture seule :

```bash
kubectl version --short
```

La sortie attendue montre à la fois les versions client et serveur. Pour que SSA fonctionne de manière fiable, la version du serveur doit être au moins 1.18. La version du client importe moins car le serveur effectue la fusion, mais utiliser un `kubectl` récent garantit que le drapeau `--server-side` est disponible.

Ensuite, vérifiez que le serveur d'API a le feature gate `ServerSideApply` activé (il est activé par défaut dans toutes les versions prises en charge, mais un cluster personnalisé pourrait le désactiver) :

```bash
kubectl get --raw /metrics | grep server_side_apply
```

Si vous voyez des métriques comme `apiserver_request_total` avec `verb="PATCH"` et `dry_run=""`, la fonctionnalité est active. Vous pouvez aussi inspecter les plugins d'admission activés du serveur d'API :

```bash
kubectl get --raw /healthz?verbose | grep -i server-side-apply
```

Une réponse saine inclut `server-side-apply` dans la liste des vérifications.

### Prérequis pour CI/CD

- **Cluster Kubernetes** : v1.18+ préféré. Certaines fonctionnalités avancées comme `managedFields` sont stables en v1.22+.
- **Client kubectl** : v1.22+ pour éviter les tentatives de fusion côté client. Les clients plus anciens peuvent essayer d'envoyer un patch client-side apply sauf si vous forcez `--server-side`.
- **Permissions RBAC** : Le compte de service CI doit avoir les verbes `patch` et `update` sur les ressources cibles, plus `get` et `list` pour la détection de conflits.
- **Isolation par espace de noms** : Utilisez un espace de noms dédié pour tester le comportement SSA avant de l'activer pour les charges de travail en production.

Exécutez ce petit test pour confirmer que SSA fonctionne de bout en bout :

Créez une ConfigMap avec SSA :

```bash
kubectl apply --server-side -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: ssa-test
  namespace: default
data:
  key1: value1
EOF
```

Sortie attendue :

```
configmap/ssa-test serverside-applied
```

Inspectez les `managedFields` pour voir la propriété :

```bash
kubectl get configmap ssa-test -o yaml --show-managed-fields | grep -A 5 managedFields
```

Vous devriez voir une entrée avec `manager: kubectl` et `operation: Apply`. Cela confirme que SSA a enregistré le gestionnaire de champ.

Nettoyez l'objet de test avec :

```bash
kubectl delete configmap ssa-test
```

## Chemin de configuration sécurisé

SSA fonctionne mieux lorsque chaque acteur du système l'utilise de manière cohérente. Si certains outils utilisent encore le client-side apply (`kubectl apply` sans `--server-side`), la propriété des champs peut se fragmenter, entraînant des conflits.

### Standardiser sur SSA pour les déploiements

Pour un déploiement géré par votre pipeline CI, appliquez toujours avec `--server-side`. Voici une stratégie minimale :

1. Stockez les manifestes dans Git comme source de vérité.
2. Utilisez une étape CI qui applique les manifestes avec un nom de gestionnaire stable. Le nom du gestionnaire est la façon dont SSA suit la propriété. Utilisez un nom qui identifie votre pipeline, comme `ci-deployer`.
3. N'incluez `--force-conflicts` qu'après avoir vérifié que les conflits sont attendus. En fonctionnement normal, vous ne devriez pas forcer les conflits.

Exemple de snippet CI (GitHub Actions, mais tout CI fonctionne) :

```yaml
- name: Apply with SSA
  run: |
    kubectl apply --server-side \
      --field-manager=ci-deployer \
      --validate=false \
      -f deploy/
```

Pourquoi `--validate=false` ? SSA effectue déjà une validation de schéma structurel côté serveur. Sauter la validation côté client peut accélérer les grandes opérations d'application et évite les problèmes de désalignement de versions entre les schémas client et serveur. Le serveur valide toujours.

### Contrôler la propriété des champs

SSA introduit `managedFields`, qui suit quel gestionnaire possède quels champs. Lorsque deux gestionnaires essaient de modifier le même champ, le serveur d'API renvoie une erreur de conflit. C'est une fonctionnalité de sécurité, pas un bug. Pour éviter les conflits en CI, ayez un seul gestionnaire pour chaque type de ressource. Par exemple, votre pipeline CI pourrait être le seul gestionnaire des objets `Deployment`, tandis qu'un autoscaler gère `replicas` séparément. SSA permet à différents gestionnaires de posséder différents champs.

Pour inspecter la propriété en détail :

```bash
kubectl get deployment my-app -o yaml --show-managed-fields | grep -A 20 managedFields
```

Recherchez des entrées comme :

```yaml
- apiVersion: apps/v1
  fieldsType: FieldsV1
  fieldsV1:
    f:spec:
      f:replicas: {}
      f:template:
        f:spec:
          f:containers:
            k:{"name":"app"}:
              f:image: {}
              f:resources: {}
  manager: ci-deployer
  operation: Apply
  time: "2025-01-10T12:00:00Z"
```

Cela montre que `ci-deployer` possède les champs pour `replicas`, l'`image` du conteneur et les `resources`. Si votre autoscaler essaie plus tard de modifier `replicas`, il devrait utiliser SSA avec son propre gestionnaire et pourrait entrer en conflit s'il revendique également la propriété de ce champ.

### Déployer les changements progressivement

Utilisez `kubectl apply --server-side --dry-run=server` pour voir l'effet sans persister :

```bash
kubectl apply --server-side --dry-run=server -f deploy/my-app.yaml
```

La sortie attendue inclut une note indiquant que la requête était un dry-run et qu'aucun changement n'a été appliqué. C'est utile dans une étape de revue de pull request pour révéler les conflits potentiels avant la fusion.

## Vérification et diagnostics

Après avoir appliqué un changement, vérifiez que l'état du cluster correspond à votre intention et qu'aucun changement de propriété de champ inattendu ne s'est produit.

### Vérifier les ressources appliquées

Pour un déploiement :

```bash
kubectl rollout status deployment/my-app --timeout=120s
```

Succès attendu :

```
deployment "my-app" successfully rolled out
```

Si le déploiement stagne, examinez les événements des pods :

```bash
kubectl describe deployment my-app
```

Recherchez des conditions comme `Progressing` et `Available`. Vérifiez aussi le replicaset :

```bash
kubectl get replicasets -l app=my-app
```

Si les pods sont en crash-loop, obtenez les logs de l'instance précédente du conteneur :

```bash
kubectl logs deployment/my-app --previous --tail=50
```

### Diagnostiquer les conflits SSA

Une erreur courante lors de l'application SSA ressemble à :

```
error: Apply failed with 1 conflict: conflict with "kubectl-client-side-apply" using apps/v1: .spec.template.spec.containers[name="app"].image
```

Cela signifie qu'un autre gestionnaire (ici, `kubectl-client-side-apply`) possède déjà le champ `image`, et que votre gestionnaire a essayé de le modifier. Pour voir les propriétaires actuels de ce champ, utilisez :

```bash
kubectl get deployment my-app -o yaml | grep -B 5 -A 10 'f:image'
```

La sortie montre le chemin du champ et le gestionnaire qui le possède. Vous pouvez alors décider :

- Si le gestionnaire en conflit est obsolète, vous pouvez prendre possession en appliquant avec `--force-conflicts`. Mais soyez prudent : cela écrase l'intention de l'autre gestionnaire.
- Si le conflit est valide, coordonnez-vous avec l'autre gestionnaire ou ajustez votre pipeline pour ne pas modifier ce champ.

### Déboguer avec le dry-run côté serveur

Utilisez `--dry-run=server` avec un gestionnaire de champ spécifique pour voir les changements de propriété :

```bash
kubectl apply --server-side --dry-run=server --field-manager=ci-deployer -f deploy/my-app.yaml -o yaml | grep -A 10 managedFields
```

Cela montre à quoi ressembleraient les `managedFields` après l'application sans réellement appliquer. Cela vous aide à repérer si votre gestionnaire prendrait le contrôle de champs non intentionnels.

## Modes de défaillance et récupération

SSA introduit de nouveaux modes de défaillance, notamment autour de la propriété des champs et des conflits. Planifier la récupération avant qu'une défaillance ne se produise réduit les temps d'arrêt et la confusion.

### Défaillance : un conflit d'application empêche le déploiement

**Symptôme** : Le pipeline CI échoue avec une erreur de conflit comme ci-dessus.

**Pourquoi cela arrive** : Deux gestionnaires revendiquent le même champ. Cela se produit souvent lors de la première adoption de SSA et que les ressources existantes ont `kubectl-client-side-apply` comme gestionnaire.

**Récupération** : Migrez la propriété délibérément.

1. Identifiez le(s) champ(s) en conflit à partir de l'erreur.
2. Décidez qui devrait posséder ces champs à l'avenir.
3. Si votre gestionnaire CI doit les posséder, exécutez une commande unique pour prendre possession en forçant le conflit :

```bash
kubectl apply --server-side --force-conflicts --field-manager=ci-deployer -f deploy/my-app.yaml
```

4. Vérifiez la nouvelle propriété :

```bash
kubectl get deployment my-app -o yaml | grep -A 10 managedFields
```

5. Assurez-vous que toutes les applications futures utilisent le même `--field-manager` et évitez `--force-conflicts` sauf en cas de nécessité absolue.

### Défaillance : réinitialisation inattendue d'un champ

**Symptôme** : Un champ que vous n'aviez pas l'intention de modifier revient à une valeur par défaut ou disparaît.

**Pourquoi cela arrive** : Avec SSA, si un gestionnaire applique un manifeste qui omet un champ qu'il possédait auparavant, le serveur interprète cela comme une instruction de supprimer le champ. Par exemple, si votre manifeste n'inclut plus `resources.limits` mais que votre gestionnaire le possédait auparavant, SSA supprimera les limites.

**Récupération** : Empêchez cela en incluant toujours la spécification complète souhaitée dans vos manifestes. Utilisez un outil de templating comme Kustomize ou Helm pour maintenir des spécifications complètes. Examinez également les diffs en CI avant d'appliquer. Si une réinitialisation a déjà eu lieu, restaurez le champ en appliquant un manifeste avec la valeur correcte en utilisant le même gestionnaire de champ.

### Défaillance : application partielle due à une erreur de validation

**Symptôme** : `kubectl apply --server-side` signale une erreur de validation pour une ressource, mais d'autres ressources du même lot peuvent déjà avoir été appliquées.

**Pourquoi cela arrive** : Contrairement au client-side apply qui valide tout avant d'envoyer, le server-side apply traite les ressources individuellement. Certaines peuvent réussir avant que celle en échec ne soit atteinte.

**Récupération** : Utilisez `kubectl apply --server-side --dry-run=server` sur le répertoire complet avant l'application réelle. Cela capture les erreurs de validation sans effets secondaires. Si une application partielle se produit, vérifiez quelles ressources ont été appliquées :

```bash
kubectl get all -n my-app -o name
```

Puis réappliquez les manifestes corrigés. Comme SSA est idempotent, réappliquer est sûr.

### Stratégies de rollback

Le rollback avec SSA est similaire au client-side apply, mais vous devez vous assurer que le manifeste de rollback inclut tous les champs que votre gestionnaire possède pour éviter des réinitialisations involontaires.

**Option 1 : Réappliquer un manifeste précédent connu bon**

```bash
kubectl apply --server-side --field-manager=ci-deployer -f deploy/known-good/my-app.yaml
```

Cela restaure la spécification à un état précédent. Assurez-vous que le manifeste est complet.

**Option 2 : Utiliser `kubectl rollout undo`**

`kubectl rollout undo` ramène le déploiement à la révision précédente. Cependant, il utilise la configuration stockée côté serveur, qui inclut les champs gérés par SSA. Cela ne change pas la propriété des champs ; le gestionnaire qui a fait le changement possède toujours les champs. Donc après l'annulation, les champs sont dans l'état plus ancien mais toujours gérés par le même gestionnaire. C'est souvent suffisant pour un rollback rapide.

```bash
kubectl rollout undo deployment/my-app
```

Pour vérifier :

```bash
kubectl rollout status deployment/my-app
```

**Option 3 : Git revert plus apply**

Dans un flux GitOps, annuler le commit et laisser le pipeline appliquer avec SSA est le plus propre, car cela garde l'historique Git comme piste d'audit et utilise le même gestionnaire. C'est l'approche recommandée pour CI/CD.

## Liste de contrôle opérationnelle

Utilisez cette liste de contrôle avant de promouvoir SSA en CI/CD de production. Chaque élément a un propriétaire et une fréquence de revue.

| # | Élément | Propriétaire | Fréquence |
|---|------|-------|-----------|
| 1 | Confirmer que toutes les ressources de production sont gérées avec `--server-side` et un nom `--field-manager` cohérent. | Responsable DevOps (ex. Priya Shah) | Mensuel |
| 2 | Vérifier qu'aucun gestionnaire `kubectl-client-side-apply` ne reste sur les ressources critiques. | Ingénieur de release (ex. Marco Diaz) | Hebdomadaire |
| 3 | Exécuter `--dry-run=server` sur tous les manifestes en CI avant la fusion pour détecter les conflits tôt. | Pipeline CI (automatique) | Chaque PR |
| 4 | Tester la procédure de rollback dans un espace de noms de staging au moins une fois par sprint. | Ingénieur QA (ex. Lena Park) | Bihebdomadaire |
| 5 | Revoir les permissions RBAC des comptes de service CI pour s'assurer qu'ils n'ont que les portées `patch` et `update` nécessaires. | Responsable sécurité (ex. Ahmed Khan) | Trimestriel |
| 6 | Auditer `managedFields` pour toute propriété de gestionnaire inattendue ou dérive de champ. | Ingénieur plateforme (ex. Chris O'Brien) | Mensuel |

### Référence des commandes

Exécutez régulièrement ces commandes pour vérifier l'hygiène SSA :

Lister tous les gestionnaires à travers les ressources dans un espace de noms :

```bash
kubectl get configmaps,secrets,deployments -n my-app -o yaml | grep 'manager:' | sort | uniq -c
```

Afficher les champs possédés par un gestionnaire spécifique :

```bash
kubectl get deployment my-app -o yaml | yq eval '.metadata.managedFields[] | select(.manager == "ci-deployer") | .fieldsV1' -
```

(Si vous n'avez pas `yq`, utilisez `grep` avec contexte.)

Détecter les ressources n'utilisant pas SSA en vérifiant l'absence de champs gérés :

```bash
kubectl get deployment -o json | jq -r '.items[] | select(.metadata.managedFields | length == 0) | .metadata.name'
```

Cela renvoie les noms des ressources qui ont probablement été créées sans SSA.

## Pièges courants et comment les éviter

### Piège 1 : Mélanger client-side et server-side apply

**L'erreur** : Utiliser `kubectl apply` (côté client) pour certaines mises à jour et `kubectl apply --server-side` pour d'autres sur la même ressource. Le client-side apply utilise un algorithme de fusion et un nom de gestionnaire différents, provoquant une fragmentation de la propriété et des conflits mystérieux.

**Pourquoi cela arrive** : Les équipes adoptent SSA progressivement et oublient quelles commandes sont utilisées dans différents scripts ou documentations.

**Comment éviter** : Appliquez une politique : une fois qu'une ressource est gérée avec SSA, toutes les modifications ultérieures doivent utiliser SSA avec un `--field-manager` cohérent. Mettez à jour tous les scripts et documents. Ajoutez une vérification CI qui recherche `kubectl apply` sans `--server-side` dans les définitions de pipeline.

**Récupération** : Si une utilisation mixte se produit, choisissez un gestionnaire unique et réappliquez l'état souhaité avec `--server-side --force-conflicts` une fois pour consolider la propriété, puis tenez-vous-en à SSA par la suite.

### Piège 2 : Omettre des champs dans les manifestes entraîne une suppression silencieuse

**L'erreur** : Supprimer un champ (comme une limite de ressource) d'un manifeste et appliquer avec SSA supprime ce champ de l'objet en direct car le serveur interprète l'omission comme une intention de suppression.

**Pourquoi cela arrive** : Avec le client-side apply, les champs omis restent souvent inchangés, donc les développeurs supposent la même chose avec SSA.

**Comment éviter** : Générez toujours les manifestes à partir de modèles complets. Utilisez des overlays Kustomize ou des valeurs Helm pour vous assurer que tous les champs nécessaires sont présents. En CI, diff le manifeste appliqué par rapport à l'objet en direct pour montrer les champs supprimés (par exemple, `kubectl diff -f deploy/` avant d'appliquer).

**Récupération** : Si un champ a été supprimé involontairement, restaurez-le en appliquant un manifeste qui inclut ce champ avec la valeur correcte, en utilisant le même gestionnaire de champ. Le champ réapparaîtra et la propriété restera avec ce gestionnaire.

### Piège 3 : Utiliser `--force-conflicts` systématiquement

**L'erreur** : Ajouter `--force-conflicts` à chaque commande d'application pour éviter de traiter les erreurs de conflit. Cela masque les vrais conflits et peut écraser les modifications apportées par d'autres contrôleurs ou utilisateurs.

**Pourquoi cela arrive** : Les développeurs voient les erreurs de conflit comme des nuisances et passent en force.

**Comment éviter** : N'utilisez jamais `--force-conflicts` dans les pipelines automatisés. Enquêtez sur chaque conflit. Si un conflit est légitime, coordonnez la propriété des champs. N'utilisez `--force-conflicts` que dans une étape de migration contrôlée et unique.

**Récupération** : Si vous avez forcé des conflits, examinez les changements récents pour voir si des écrasements involontaires se sont produits. Utilisez les journaux d'audit et l'historique Git pour restaurer les valeurs correctes.

### Piège 4 : Ne pas définir un gestionnaire de champ cohérent

**L'erreur** : Différents jobs CI ou membres de l'équipe utilisent des noms de gestionnaire différents (par exemple, `kubectl`, `deploy-script`, `jenkins`), conduisant à plusieurs propriétaires pour différents sous-ensembles de champs. Cela rend difficile de savoir qui contrôle quoi et peut causer des conflits lorsqu'un gestionnaire essaie de modifier des champs possédés par un autre.

**Pourquoi cela arrive** : Le drapeau `--field-manager` est souvent omis, et le gestionnaire par défaut est `kubectl` côté client ou le nom de l'utilisateur côté serveur. En CI, l'utilisateur peut être le compte de service, qui n'est pas descriptif.

**Comment éviter** : Définissez explicitement `--field-manager` sur un identifiant stable pour votre pipeline (par exemple, `ci-deployer`). Documentez-le et incluez-le dans toutes les commandes d'application.

**Récupération** : Migrez vers un gestionnaire unique en appliquant toutes les ressources avec le gestionnaire souhaité en utilisant `--force-conflicts` une fois, puis imposez la cohérence.

### Piège 5 : Ignorer `managedFields` lors du débogage

**L'erreur** : Lorsqu'une ressource se comporte de manière inattendue après une application SSA, les ingénieurs n'inspectent pas `managedFields` pour comprendre qui a changé quoi. Ils peuvent rejeter la faute sur les autres ou apporter des corrections incorrectes.

**Pourquoi cela arrive** : `managedFields` est verbeux et souvent omis de la sortie par défaut de `kubectl get`, donc il est facilement négligé.

**Comment éviter** : Incluez l'inspection de `managedFields` dans votre liste de contrôle de débogage. Utilisez `kubectl get <ressource> -o yaml | grep -A 30 managedFields` pour voir les opérations récentes. Des outils comme `kubectl fields` (si disponibles) peuvent simplifier cela.

**Récupération** : Si vous trouvez une propriété de champ inattendue, tracez le gestionnaire jusqu'à sa source et corrigez le processus.

## Conclusion

Server-side apply apporte un suivi rigoureux de la propriété des champs au niveau des champs à la configuration Kubernetes, ce qui est un atout pour l'automatisation CI/CD. Il empêche les écrasements accidentels, fournit des signaux de conflit clairs et permet à plusieurs contrôleurs de gérer en toute sécurité différentes parties d'une ressource. Cependant, cela exige de la discipline : des noms de gestionnaire de champ cohérents, des manifestes complets et une compréhension approfondie du comportement des omissions et des conflits.

Commencez par des ressources à faible risque comme les ConfigMaps et les Secrets, puis étendez aux Deployments et aux CRDs. Utilisez la vérification dry-run en CI, surveillez `managedFields` pour la dérive, et ayez une procédure de rollback testée. Avec ces pratiques, votre pipeline Kubernetes sera plus prévisible et moins sujet à la dérive de configuration.

Comme prochaine étape, choisissez un déploiement existant dans votre cluster, inspectez ses `managedFields`, et essayez d'appliquer un petit changement avec `--server-side` dans un environnement de staging. Observez comment la propriété est enregistrée et comment les conflits apparaissent. Cette expérience pratique renforcera la confiance nécessaire pour adopter SSA dans vos pipelines.