1 - ReplicaSet

Un ReplicaSet (ensemble de réplicas en français) a pour but de maintenir un ensemble stable de Pods à un moment donné. Cet objet est souvent utilisé pour garantir la disponibilité d'un certain nombre identique de Pods.

Comment un ReplicaSet fonctionne

Un ReplicaSet est défini avec des champs, incluant un selecteur qui spécifie comment identifier les Pods qu'il peut posséder, un nombre de replicas indiquant le nombre de Pods qu'il doit maintenir et un modèle de Pod spécifiant les données que les nouveaux Pods que le replicatSet va créer jusqu'au nombre de replicas demandé.

Un ReplicaSet va atteindre son objectif en créant et supprimant des Pods pour atteindre le nombre de réplicas désirés. Quand un ReplicaSet a besoin de créer de nouveaux Pods, il utilise alors son Pod template.

Le lien d'un ReplicaSet à ses Pods est fait par le champ metadata.ownerReferences, qui spécifie la ressource de l'objet par lequel il est détenu. Tous les Pods acquis par un ReplicaSet ont leurs propres informations d'identification de leur Replicaset, avec leur propre champ ownerReferences. C'est par ce lien que le ReplicaSet connait l'état des Pods qu'il maintient et agit en fonction de ces derniers.

Un ReplicaSet identifie des nouveaux Pods à acquérir en utilisant son selecteur. Si il y a un Pod qui n'a pas de OwnerReference ou que OwnerReference n'est pas un controller et qu'il correspond à un sélecteur de ReplicaSet, il va immédiatement être acquis par ce ReplicaSet.

Quand utiliser un ReplicaSet ?

Un ReplicaSet garantit qu’un nombre spécifié de réplicas de Pod soient exécutés à un moment donné. Cependant, un Deployment est un concept de plus haut niveau qui gère les ReplicaSets et fournit des mises à jour déclaratives aux Pods ainsi que de nombreuses autres fonctionnalités utiles. Par conséquent, nous vous recommandons d’utiliser des Deployments au lieu d’utiliser directement des ReplicaSets, sauf si vous avez besoin d'une orchestration personnalisée des mises à jour ou si vous n'avez pas besoin de mises à jour.

Cela signifie qu'il est possible que vous n'ayez jamais besoin de manipuler des objets ReplicaSet : utilisez plutôt un déploiement et définissez votre application dans la section spec.

Exemple

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # modify replicas according to your case
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3

Enregistrer ce manifeste dans frontend.yaml et le soumettre à un cluster Kubernetes va créer le ReplicaSet défini et les pods qu’il gère.

kubectl apply -f https://kubernetes.io/examples/controllers/frontend.yaml

Vous pouvez ensuite récupérer les ReplicaSets actuellement déployés :

kubectl get rs

Et voir le frontend que vous avez créé :

NAME       DESIRED   CURRENT   READY   AGE
frontend   3         3         3       6s

Vous pouvez également vérifier l'état du ReplicaSet :

kubectl describe rs/frontend

Et vous verrez une sortie similaire à :

Name:		frontend
Namespace:	default
Selector:	tier=frontend,tier in (frontend)
Labels:		app=guestbook
		tier=frontend
Annotations:	<none>
Replicas:	3 current / 3 desired
Pods Status:	3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:       app=guestbook
                tier=frontend
  Containers:
   php-redis:
    Image:      gcr.io/google_samples/gb-frontend:v3
    Port:       80/TCP
    Requests:
      cpu:      100m
      memory:   100Mi
    Environment:
      GET_HOSTS_FROM:   dns
    Mounts:             <none>
  Volumes:              <none>
Events:
  FirstSeen    LastSeen    Count    From                SubobjectPath    Type        Reason            Message
  ---------    --------    -----    ----                -------------    --------    ------            -------
  1m           1m          1        {replicaset-controller }             Normal      SuccessfulCreate  Created pod: frontend-qhloh
  1m           1m          1        {replicaset-controller }             Normal      SuccessfulCreate  Created pod: frontend-dnjpy
  1m           1m          1        {replicaset-controller }             Normal      SuccessfulCreate  Created pod: frontend-9si5l

Et enfin, vous pourrez afficher les Pods déployés :

kubectl get Pods

Vous devriez voir des informations sur les Pods avec une sortie similaire à :

NAME             READY     STATUS    RESTARTS   AGE
frontend-9si5l   1/1       Running   0          1m
frontend-dnjpy   1/1       Running   0          1m
frontend-qhloh   1/1       Running   0          1m

Vous pouvez également vérifier que la OwnerReference de ces pods est définie sur le frontend ReplicaSet. Pour ce faire, récupérez le yaml de l’un des pods :

kubectl get pods frontend-9si5l -o yaml

La sortie sera similaire à celle-ci, avec les informations de l'interface ReplicaSet frontend définies dans le champ ownerReferences des métadonnées:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: 2019-01-31T17:20:41Z
  generateName: frontend-
  labels:
    tier: frontend
  name: frontend-9si5l
  namespace: default
  ownerReferences:
  - apiVersion: extensions/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: ReplicaSet
    name: frontend
    uid: 892a2330-257c-11e9-aecd-025000000001
...

Acquisitions de Pod en dehors du template

Bien que vous puissiez créer des pods manuellement sans problème, il est fortement recommandé de s’assurer que ces pods n'ont pas de labels correspondant au sélecteur de l’un de vos ReplicaSets. Car un ReplicaSet n’est pas limité à posséder les pods spécifiés par son modèle - il peut acquérir d’autres pods de la manière spécifiée dans les sections précédentes.

Prenez l'exemple précédent de ReplicaSet, ainsi que les pods spécifiés dans le manifeste suivant :

apiVersion: v1
kind: Pod
metadata:
  name: pod1
  labels:
    tier: frontend
spec:
  containers:
  - name: hello1
    image: gcr.io/google-samples/hello-app:2.0

---

apiVersion: v1
kind: Pod
metadata:
  name: pod2
  labels:
    tier: frontend
spec:
  containers:
  - name: hello2
    image: gcr.io/google-samples/hello-app:1.0

Ces pods n’ayant pas de contrôleur (ni d’objet) en tant que référence propriétaire, ils correspondent au sélecteur de du ReplicaSet frontend, ils seront donc immédiatement acquis par ce ReplicaSet.

Supposons que vous créiez les pods une fois le ReplicaSet frontend déployé et qui a déjà déployé ses replicas de Pods initiaux afin de remplir son exigence de nombre de replicas :

kubectl apply -f https://kubernetes.io/examples/pods/pod-rs.yaml

Les nouveaux pods seront acquis par le ReplicaSet, puis immédiatement terminés car le ReplicaSet dépasserait alors le compte désiré.

En récupérant les pods :

kubectl get Pods

La sortie montre que les nouveaux pods sont soit déjà terminés, soit en voie de l'être :

NAME             READY   STATUS        RESTARTS   AGE
frontend-9si5l   1/1     Running       0          1m
frontend-dnjpy   1/1     Running       0          1m
frontend-qhloh   1/1     Running       0          1m
pod2             0/1     Terminating   0          4s

Cependant, si vous créez d'abord les pods :

kubectl apply -f https://kubernetes.io/examples/pods/pod-rs.yaml

Et puis créez le ReplicaSet :

kubectl apply -f https://kubernetes.io/examples/controllers/frontend.yaml

Vous verrez que le ReplicaSet a acquis les pods et n'a créé que les nouveaux Pods manquants, conformément à ses spécifications, jusqu'au nombre souhaité de Pods. En récupérant les Pods :

kubectl get Pods

La sortie va donner :

NAME             READY   STATUS    RESTARTS   AGE
frontend-pxj4r   1/1     Running   0          5s
pod1             1/1     Running   0          13s
pod2             1/1     Running   0          13s

De cette manière, un ReplicaSet peut avoir un ensemble de Pods hétérogène.

Écrire un manifest de ReplicaSet

Comme avec tous les autres objets API Kubernetes, un ReplicaSet a besoin des champs apiVersion, kind et metadata. Pour ReplicaSets, l'attribut kind est toujours ReplicaSet.

Dans Kubernetes 1.9, la version de l'API apps/v1 pour le type ReplicaSet est la version actuelle et activée par défaut. La version de l'API apps/v1beta2 est obsolète.

Reportez-vous aux premières lignes de l'exemple frontend.yaml pour obtenir des conseils.

Un ReplicaSet a également besoin de .spec section.

Pod Template

L'attribut .spec.template est un modèle de pod qui requiert d'avoir des labels. Dans notre exemple frontend.yaml, nous avons un label : tier: frontend. Il faut faire attention à ne pas avoir des selecteurs que d'autres controllers utilisent, afin d'éviter que le ReplicaSet n'adopte ce pod.

Pour le champ restart policy, .spec.template.spec.restartPolicy, la seule valeur autorisée est Always, qui est la valeur par défaut.

Sélecteur de Pod

Le champ .spec.selector est un label selector. Tel que discuté précédemment, ce sont les labels utilisés pour identifier les Pods potentiels à acquérir. Dans notre exemple avec frontend.yaml, le sélecteur était :

matchLabels:
	tier: frontend

Dans le ReplicaSet, .spec.template.metadata.labels doit correspondre à spec.selector, ou sinon il sera rejeté par l'API.

Replicas

Vous pouvez spécifier le nombre de pods à exécuter simultanément en définissant .spec.replicas. Le ReplicaSet va créer/supprimer ses pods pour correspondre à ce nombre.

Si vous ne spécifiez pas .spec.replicas, la valeur par défaut est 1.

Travailler avec des ReplicaSets

Suppression d'un ReplicaSet et de ses pods

Pour supprimer un ReplicaSet et tous ses pods, utilisez kubectl delete. The Garbage collector supprime automatiquement tous les pods associés par défaut.

Lors de l’utilisation de l’API REST ou de la bibliothèque client-go, vous devez définir propagationPolicy sur Background ou Foreground dans l'option -d. Par exemple :

kubectl proxy --port=8080
curl -X DELETE  'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \
> -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
> -H "Content-Type: application/json"

Supprimer juste un ReplicaSet

Vous pouvez supprimer un ReplicaSet sans affecter ses pods à l’aide de kubectl delete avec l'option --cascade=false. Lorsque vous utilisez l'API REST ou la bibliothèque client-go, vous devez définir propagationPolicy sur Orphan. Par exemple :

kubectl proxy --port=8080
curl -X DELETE  'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \
> -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
> -H "Content-Type: application/json"

Une fois l’original supprimé, vous pouvez créer un nouveau ReplicaSet pour le remplacer. Tant que l'ancien et le nouveau .spec.selector sont identiques, le nouveau adoptera les anciens Pods. Cependant, le ReplicaSet ne fera aucun effort pour que les pods existants correspondent à un nouveau Pod template. Pour mettre à jour les Pods à une nouvelle spec de manière contrôlée, utilisez un Deployment, car les ReplicaSets ne supportent pas de rolling update directement.

Isoler les pods d'un ReplicaSet

Vous pouvez supprimer les pods d'un ReplicaSet en modifiant leurs labels. Cette technique peut être utilisée pour enlever les pods pour le débogage, récupération de données, etc. Les pods ainsi supprimés seront automatiquement remplacés (en supposant que le nombre de réplicas n’est pas également modifié).

Scaling d'un ReplicaSet

Un ReplicaSet peut facilement être scalé en mettant simplement à jour le champ .spec.replicas. Le contrôleur ReplicaSet garantit que le nombre souhaité de pods avec un sélecteur de label correspondant soient disponibles et opérationnels.

ReplicaSet en tant que Horizontal Pod Autoscaler Target

Un ReplicaSet peut également être une cible pour Horizontal Pod Autoscalers (HPA). Un ReplicaSet peut être mis à l'échelle automatiquement par un HPA. Voici un exemple HPA qui cible le ReplicaSet que nous avons créé dans l'exemple précédent.

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: frontend-scaler
spec:
  scaleTargetRef:
    kind: ReplicaSet
    name: frontend
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 50

Enregistrer ce manifeste dans hpa-rs.yaml et le soumettre à un cluster Kubernetes devrait créer le HPA défini qui scale automatiquement le ReplicaSet cible en fonction de l'utilisation du processeur des pods répliqués.

kubectl apply -f https://k8s.io/examples/controllers/hpa-rs.yaml

Vous pouvez aussi utiliser la commande kubectl autoscale pour accomplir la même chose. (et c'est plus facile !)

kubectl autoscale rs frontend --max=10

Alternatives au ReplicaSet

Deployment (recommandé)

Le Deployment est un object qui peut posséder les ReplicaSets et les mettres à jour ainsi que leurs Pods de façon déclarative, côté serveur et avec des rolling updates.

Alors que les ReplicaSets peuvent être utilisés indépendamment, ils sont principalement utilisés aujourd'hui par Deployments comme mécanisme pour orchestrer la création, suppresion et mises à jour des Pods. Lorsque vous utilisez des Deployments, vous n’aurez plus à vous soucier de la gestion des ReplicaSets ainsi créés. Les déploiements possèdent et gèrent leurs ReplicaSets. C'est pourquoi il est recommandé d’utiliser les déploiements lorsque vous voulez des ReplicaSets.

Pods nus

Contrairement au cas où un utilisateur a créé directement des pods, un ReplicaSet remplace les pods supprimés ou terminés pour quelque raison que ce soit, par exemple en cas de défaillance d'un nœud ou de maintenance de nœud perturbateur, telle qu'une mise à jour kernel. Pour cette raison, nous vous recommandons d'utiliser un ReplicaSet même si votre application ne nécessite qu'un seul pod. Pensez-y de la même manière qu’un superviseur de processus, mais il supervise plusieurs pods sur plusieurs nœuds au lieu de processus individuels sur un seul nœud. Un ReplicaSet délègue les redémarrages de conteneurs locaux à un agent du nœud (par exemple, Kubelet ou Docker).

Job

Utilisez un Job au lieu d'un ReplicaSet pour les pods qui doivent se terminer seuls (c'est à dire des batch jobs).

DaemonSet

Utilisez un DaemonSet au lieu d’un ReplicaSet pour les pods qui fournissent une fonction au niveau du noeud, comme le monitoring ou la gestion des logs de ce noeud. Ces pods ont une durée de vie qui est liée durée de vie d’une machine : le pod doit être en cours d’exécution sur la machine avant le démarrage des autres Pods et sont sûrs de se terminer lorsque la machine est prête à être redémarrée/arrêtée.

ReplicationController

Les ReplicaSets sont les successeurs de ReplicationControllers. Les deux servent le même objectif et se comportent de la même manière, à la différence près que ReplicationController ne prend pas en charge les les exigences de sélecteur décrites dans le labels user guide. En tant que tels, les ReplicaSets sont préférés aux ReplicationControllers.

2 - Déploiements

Un Deployment (déploiement en français) fournit des mises à jour déclaratives pour Pods et ReplicaSets.

Vous décrivez un état désiré dans un déploiement et le controlleur déploiement change l'état réel à l'état souhaité à un rythme contrôlé. Vous pouvez définir des Deployments pour créer de nouveaux ReplicaSets, ou pour supprimer des déploiements existants et adopter toutes leurs ressources avec de nouveaux déploiements.

Cas d'utilisation

Voici des cas d'utilisation typiques pour les déploiements:

Création d'un déploiement

Voici un exemple de déploiement. Il crée un ReplicaSet pour faire apparaître trois pods nginx:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

Dans cet exemple:

  • Un déploiement nommé nginx-deployment est créé, indiqué par le champ .metadata.name.

  • Le déploiement crée trois pods répliqués, indiqués par le champ replicas.

  • Le champ selector définit comment le déploiement trouve les pods à gérer. Dans ce cas, vous sélectionnez simplement un label définie dans le template de pod (app:nginx). Cependant, des règles de sélection plus sophistiquées sont possibles, tant que le modèle de pod satisfait lui-même la règle.

  • Le champ template contient les sous-champs suivants:

    • Les Pods reçoivent le label app:nginx dans le champ labels.
    • La spécification du template de pod dans le champ .template.spec, indique que les pods exécutent un conteneur, nginx, qui utilise l'image nginx Docker Hub à la version 1.7.9.
    • Créez un conteneur et nommez-le nginx en utilisant le champ name.

Suivez les étapes ci-dessous pour créer le déploiement ci-dessus:

Avant de commencer, assurez-vous que votre cluster Kubernetes est opérationnel.

  1. Créez le déploiement en exécutant la commande suivante:

    kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
    
  2. Exécutez kubectl get deployments pour vérifier si le déploiement a été créé. Si le déploiement est toujours en cours de création, la sortie est similaire à:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   0/3     0            0           1s
    

    Lorsque vous inspectez les déploiements de votre cluster, les champs suivants s'affichent:

    • NAME répertorie les noms des déploiements dans le cluster.
    • DESIRED affiche le nombre souhaité de répliques de l'application, que vous définissez lorsque vous créez le déploiement. C'est l'état désiré.
    • CURRENT affiche le nombre de réplicas en cours d'exécution.
    • UP-TO-DATE affiche le nombre de réplicas qui ont été mises à jour pour atteindre l'état souhaité.
    • AVAILABLE affiche le nombre de réplicas de l'application disponibles pour vos utilisateurs.
    • AGE affiche la durée d'exécution de l'application.

    Notez que le nombre de réplicas souhaitées est de 3 selon le champ .spec.replicas.

  3. Pour voir l'état du déploiement, exécutez:

    kubectl rollout status deployment.v1.apps/nginx-deployment
    

    La sortie est similaire à ceci:

    Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
    deployment "nginx-deployment" successfully rolled out
    
  4. Exécutez à nouveau kubectl get deployments quelques secondes plus tard. La sortie est similaire à ceci:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           18s
    

    Notez que le déploiement a créé les trois répliques et que toutes les répliques sont à jour (elles contiennent le dernier modèle de pod) et disponibles.

  5. Pour voir le ReplicaSet (rs) créé par le déploiement, exécutez kubectl get rs. La sortie est similaire à ceci:

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-75675f5897   3         3         3       18s
    

    Notez que le nom du ReplicaSet est toujours formaté comme: [DEPLOYMENT-NAME]-[RANDOM-STRING]. La chaîne aléatoire est générée aléatoirement et utilise le pod-template-hash comme graine.

  6. Pour voir les labels générées automatiquement pour chaque Pod, exécutez kubectl get pods --show-labels. La sortie est similaire à ceci:

    NAME                                READY     STATUS    RESTARTS   AGE       LABELS
    nginx-deployment-75675f5897-7ci7o   1/1       Running   0          18s       app=nginx,pod-template-hash=3123191453
    nginx-deployment-75675f5897-kzszj   1/1       Running   0          18s       app=nginx,pod-template-hash=3123191453
    nginx-deployment-75675f5897-qqcnn   1/1       Running   0          18s       app=nginx,pod-template-hash=3123191453
    

Le ReplicaSet créé garantit qu'il y a trois pods nginx.

Étiquette pod-template-hash

Le label pod-template-hash est ajoutée par le contrôleur de déploiement à chaque ReplicaSet créé ou adopté par un déploiement.

Ce label garantit que les ReplicaSets enfants d'un déploiement ne se chevauchent pas. Il est généré en hachant le PodTemplate du ReplicaSet et en utilisant le hachage résultant comme valeur de label qui est ajoutée au sélecteur ReplicaSet, aux labels de template de pod et dans tous les pods existants que le ReplicaSet peut avoir.

Mise à jour d'un déploiement

Suivez les étapes ci-dessous pour mettre à jour votre déploiement:

  1. Mettons à jour les pods nginx pour utiliser l'image nginx: 1.9.1 au lieu de l'image nginx: 1.7.9.

    kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
    

    ou utilisez la commande suivante:

    kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1 --record
    

    La sortie est similaire à ceci:

    deployment.apps/nginx-deployment image updated
    

    Alternativement, vous pouvez éditer le déploiement et changer .spec.template.spec.containers[0].image de nginx: 1.7.9 à nginx: 1.9.1:

    kubectl edit deployment.v1.apps/nginx-deployment
    

    La sortie est similaire à ceci:

    deployment.apps/nginx-deployment edited
    
  2. Pour voir l'état du déploiement, exécutez:

    kubectl rollout status deployment.v1.apps/nginx-deployment
    

    La sortie est similaire à ceci:

    Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
    

    ou

    deployment "nginx-deployment" successfully rolled out
    

Obtenez plus de détails sur votre déploiement mis à jour:

  • Une fois le déploiement réussi, vous pouvez afficher le déploiement en exécutant kubectl get deployments. La sortie est similaire à ceci:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           36s
    
  • Exécutez kubectl get rs pour voir que le déploiement a mis à jour les pods en créant un nouveau ReplicaSet et en le redimensionnant jusqu'à 3 replicas, ainsi qu'en réduisant l'ancien ReplicaSet à 0 réplicas.

    kubectl get rs
    

    La sortie est similaire à ceci:

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-1564180365   3         3         3       6s
    nginx-deployment-2035384211   0         0         0       36s
    
  • L'exécution de kubectl get pods ne devrait désormais afficher que les nouveaux pods:

    kubectl get pods
    

    La sortie est similaire à ceci:

    NAME                                READY     STATUS    RESTARTS   AGE
    nginx-deployment-1564180365-khku8   1/1       Running   0          14s
    nginx-deployment-1564180365-nacti   1/1       Running   0          14s
    nginx-deployment-1564180365-z9gth   1/1       Running   0          14s
    

    La prochaine fois que vous souhaitez mettre à jour ces pods, il vous suffit de mettre à jour le modèle de pod de déploiement à nouveau.

    Le déploiement garantit que seul un certain nombre de pods sont en panne pendant leur mise à jour. Par défaut, il garantit qu'au moins 75% du nombre souhaité de pods sont en place (25% max indisponible).

    Le déploiement garantit également que seul un certain nombre de pods sont créés au-dessus du nombre souhaité de pods. Par défaut, il garantit qu'au plus 125% du nombre de pods souhaité sont en hausse (surtension maximale de 25%).

    Par exemple, si vous regardez attentivement le déploiement ci-dessus, vous verrez qu'il a d'abord créé un nouveau pod, puis supprimé certains anciens pods et en a créé de nouveaux. Il ne tue pas les anciens Pods tant qu'un nombre suffisant de nouveaux Pods n'est pas apparu, et ne crée pas de nouveaux Pods tant qu'un nombre suffisant de Pods anciens n'a pas été tué. Il s'assure qu'au moins 2 pods sont disponibles et qu'au maximum 4 pods au total sont disponibles.

  • Obtenez les détails de votre déploiement:

    kubectl describe deployments
    

    La sortie est similaire à ceci:

    Name:                   nginx-deployment
    Namespace:              default
    CreationTimestamp:      Thu, 30 Nov 2017 10:56:25 +0000
    Labels:                 app=nginx
    Annotations:            deployment.kubernetes.io/revision=2
    Selector:               app=nginx
    Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
        Labels:  app=nginx
        Containers:
        nginx:
            Image:        nginx:1.9.1
            Port:         80/TCP
            Environment:  <none>
            Mounts:       <none>
        Volumes:        <none>
        Conditions:
        Type           Status  Reason
        ----           ------  ------
        Available      True    MinimumReplicasAvailable
        Progressing    True    NewReplicaSetAvailable
        OldReplicaSets:  <none>
        NewReplicaSet:   nginx-deployment-1564180365 (3/3 replicas created)
        Events:
        Type    Reason             Age   From                   Message
        ----    ------             ----  ----                   -------
        Normal  ScalingReplicaSet  2m    deployment-controller  Scaled up replica set nginx-deployment-2035384211 to 3
        Normal  ScalingReplicaSet  24s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 1
        Normal  ScalingReplicaSet  22s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 2
        Normal  ScalingReplicaSet  22s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 2
        Normal  ScalingReplicaSet  19s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 1
        Normal  ScalingReplicaSet  19s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 3
        Normal  ScalingReplicaSet  14s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 0
    

    Ici, vous voyez que lorsque vous avez créé le déploiement pour la première fois, il a créé un ReplicaSet (nginx-deployment-2035384211) et l'a mis à l'échelle directement jusqu'à 3 réplicas. Lorsque vous avez mis à jour le déploiement, il a créé un nouveau ReplicaSet (nginx-deployment-1564180365) et l'a mis à l'échelle jusqu'à 1, puis a réduit l'ancien ReplicaSet à 2, de sorte qu'au moins 2 pods étaient disponibles et au plus 4 pods ont été créés à chaque fois. Il a ensuite poursuivi la montée en puissance du nouveau et de l'ancien ReplicaSet, avec la même stratégie de mise à jour continue. Enfin, vous aurez 3 réplicas disponibles dans le nouveau ReplicaSet, et l'ancien ReplicaSet est réduit à 0.

Rollover (alias plusieurs mises à jour en vol)

Chaque fois qu'un nouveau déploiement est observé par le contrôleur de déploiement, un ReplicaSet est créé pour afficher les pods souhaités. Si le déploiement est mis à jour, le ReplicaSet existant qui contrôle les pods dont les étiquettes correspondent à .spec.selector mais dont le modèle ne correspond pas à .spec.template est réduit. Finalement, le nouveau ReplicaSet est mis à l'échelle à .spec.replicas et tous les anciens ReplicaSets sont mis à l'échelle à 0.

Si vous mettez à jour un déploiement alors qu'un déploiement existant est en cours, le déploiement crée un nouveau ReplicaSet conformément à la mise à jour et commence à le mettre à l'échelle, et arrête de mettre à jour le ReplicaSet qu'il augmentait précédemment - il l'ajoutera à sa liste de anciens ReplicaSets et commencera à le réduire.

Par exemple, supposons que vous créez un déploiement pour créer 5 répliques de nginx: 1.7.9, puis mettez à jour le déploiement pour créer 5 répliques de nginx: 1.9.1, alors que seulement 3 répliques de nginx:1.7.9 avait été créés. Dans ce cas, le déploiement commence immédiatement à tuer les 3 pods nginx: 1.7.9 qu'il avait créés et commence à créer des pods nginx: 1.9.1. Il n'attend pas que les 5 répliques de nginx: 1.7.9 soient créées avant de changer de cap.

Mises à jour du sélecteur de labels

Il est généralement déconseillé de mettre à jour le sélecteur de labels et il est suggéré de planifier vos sélecteurs à l'avance. Dans tous les cas, si vous devez effectuer une mise à jour du sélecteur de labels, soyez très prudent et assurez-vous d'avoir saisi toutes les implications.

  • Les ajouts de sélecteur nécessitent que les labels de template de pod dans la spécification de déploiement soient également mises à jour avec les nouveaux labels, sinon une erreur de validation est renvoyée. Cette modification ne se chevauche pas, ce qui signifie que le nouveau sélecteur ne sélectionne pas les ReplicaSets et les pods créés avec l'ancien sélecteur, ce qui entraîne la perte de tous les anciens ReplicaSets et la création d'un nouveau ReplicaSet.
  • Les mises à jour du sélecteur modifient la valeur existante dans une clé de sélection - entraînent le même comportement que les ajouts.
  • La suppression de sélecteur supprime une clé existante du sélecteur de déploiement - ne nécessite aucune modification dans les labels du template de pod. Les ReplicaSets existants ne sont pas orphelins et aucun nouveau ReplicaSet n'est créé, mais notez que le label supprimé existe toujours dans tous les Pods et ReplicaSets existants.

Annulation d'un déploiement

Parfois, vous souhaiterez peut-être annuler un déploiement; par exemple, lorsque le déploiement n'est pas stable, comme en cas d'échecs à répétition (CrashLoopBackOff). Par défaut, tout l'historique des déploiements d'un déploiement est conservé dans le système afin que vous puissiez le restaurer à tout moment (vous pouvez le modifier en modifiant la limite de l'historique des révisions).

  • Supposons que vous ayez fait une faute de frappe lors de la mise à jour du déploiement, en mettant le nom de l'image sous la forme nginx:1.91 au lieu de nginx: 1.9.1:

    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.91 --record=true
    

    La sortie est similaire à ceci:

    deployment.apps/nginx-deployment image updated
    
  • Le déploiement est bloqué. Vous pouvez le vérifier en vérifiant l'état du déploiement:

    kubectl rollout status deployment.v1.apps/nginx-deployment
    

    La sortie est similaire à ceci:

    Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
    
  • Appuyez sur Ctrl-C pour arrêter la surveillance d'état de déploiement ci-dessus. Pour plus d'informations sur les déploiements bloqués, en savoir plus ici.

  • Vous voyez que le nombre d'anciens réplicas (nginx-deployment-1564180365 et nginx-deployment-2035384211) est 2, et les nouveaux réplicas (nginx-deployment-3066724191) est 1.

    kubectl get rs
    

    La sortie est similaire à ceci:

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-1564180365   3         3         3       25s
    nginx-deployment-2035384211   0         0         0       36s
    nginx-deployment-3066724191   1         1         0       6s
    
  • En regardant les pods créés, vous voyez que 1 pod créé par le nouveau ReplicaSet est coincé dans une boucle pour récupérer son image:

    kubectl get pods
    

    La sortie est similaire à ceci:

    NAME                                READY     STATUS             RESTARTS   AGE
    nginx-deployment-1564180365-70iae   1/1       Running            0          25s
    nginx-deployment-1564180365-jbqqo   1/1       Running            0          25s
    nginx-deployment-1564180365-hysrc   1/1       Running            0          25s
    nginx-deployment-3066724191-08mng   0/1       ImagePullBackOff   0          6s
    
  • Obtenez la description du déploiement:

    kubectl describe deployment
    

    La sortie est similaire à ceci:

    Name:           nginx-deployment
    Namespace:      default
    CreationTimestamp:  Tue, 15 Mar 2016 14:48:04 -0700
    Labels:         app=nginx
    Selector:       app=nginx
    Replicas:       3 desired | 1 updated | 4 total | 3 available | 1 unavailable
    StrategyType:       RollingUpdate
    MinReadySeconds:    0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
      Labels:  app=nginx
      Containers:
       nginx:
        Image:        nginx:1.91
        Port:         80/TCP
        Host Port:    0/TCP
        Environment:  <none>
        Mounts:       <none>
      Volumes:        <none>
    Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    ReplicaSetUpdated
    OldReplicaSets:     nginx-deployment-1564180365 (3/3 replicas created)
    NewReplicaSet:      nginx-deployment-3066724191 (1/1 replicas created)
    Events:
      FirstSeen LastSeen    Count   From                    SubObjectPath   Type        Reason              Message
      --------- --------    -----   ----                    -------------   --------    ------              -------
      1m        1m          1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-2035384211 to 3
      22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 1
      22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 2
      22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 2
      21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 1
      21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3
      13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 0
      13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 1
    

    Pour résoudre ce problème, vous devez revenir à une version précédente de Deployment qui est stable.

Vérification de l'historique de déploiement d'un déploiement

Suivez les étapes ci-dessous pour vérifier l'historique de déploiement:

  1. Tout d'abord, vérifiez les révisions de ce déploiement:

    kubectl rollout history deployment.v1.apps/nginx-deployment
    

    La sortie est similaire à ceci:

    deployments "nginx-deployment"
    REVISION    CHANGE-CAUSE
    1           kubectl apply --filename=https://k8s.io/examples/controllers/nginx-deployment.yaml --record=true
    2           kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1 --record=true
    3           kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.91 --record=true
    

    CHANGE-CAUSE est copié de l'annotation de déploiement kubernetes.io/change-cause dans ses révisions lors de la création. Vous pouvez spécifier le messageCHANGE-CAUSE en:

    • Annoter le déploiement avec kubectl annotate deployment.v1.apps/nginx-deployment kubernetes.io/change-cause="image mis à jour en 1.9.1"
    • Ajoutez le drapeau --record pour enregistrer la commande kubectl qui apporte des modifications à la ressource.
    • Modification manuelle du manifeste de la ressource.
  2. Pour voir les détails de chaque révision, exécutez:

    kubectl rollout history deployment.v1.apps/nginx-deployment --revision=2
    

    La sortie est similaire à ceci:

    deployments "nginx-deployment" revision 2
      Labels:       app=nginx
              pod-template-hash=1159050644
      Annotations:  kubernetes.io/change-cause=kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1 --record=true
      Containers:
       nginx:
        Image:      nginx:1.9.1
        Port:       80/TCP
         QoS Tier:
            cpu:      BestEffort
            memory:   BestEffort
        Environment Variables:      <none>
      No volumes.
    

Revenir à une révision précédente

Suivez les étapes ci-dessous pour restaurer le déploiement de la version actuelle à la version précédente, qui est la version 2.

  1. Vous avez maintenant décidé d'annuler le déploiement actuel et le retour à la révision précédente:

    kubectl rollout undo deployment.v1.apps/nginx-deployment
    

    La sortie est similaire à ceci:

    deployment.apps/nginx-deployment
    

    Alternativement, vous pouvez revenir à une révision spécifique en la spécifiant avec --to-revision:

    kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
    

    La sortie est similaire à ceci:

    deployment.apps/nginx-deployment
    

    Pour plus de détails sur les commandes liées au déploiement, lisez kubectl rollout.

    Le déploiement est maintenant rétabli à une précédente révision stable. Comme vous pouvez le voir, un événement DeploymentRollback pour revenir à la révision 2 est généré à partir du contrôleur de déploiement.

  2. Vérifiez si la restauration a réussi et que le déploiement s'exécute comme prévu, exécutez:

    kubectl get deployment nginx-deployment
    

    La sortie est similaire à ceci:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           30m
    
  3. Obtenez la description du déploiement:

    kubectl describe deployment nginx-deployment
    

    La sortie est similaire à ceci:

    Name:                   nginx-deployment
    Namespace:              default
    CreationTimestamp:      Sun, 02 Sep 2018 18:17:55 -0500
    Labels:                 app=nginx
    Annotations:            deployment.kubernetes.io/revision=4
                            kubernetes.io/change-cause=kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1 --record=true
    Selector:               app=nginx
    Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
      Labels:  app=nginx
      Containers:
       nginx:
        Image:        nginx:1.9.1
        Port:         80/TCP
        Host Port:    0/TCP
        Environment:  <none>
        Mounts:       <none>
      Volumes:        <none>
    Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    NewReplicaSetAvailable
    OldReplicaSets:  <none>
    NewReplicaSet:   nginx-deployment-c4747d96c (3/3 replicas created)
    Events:
      Type    Reason              Age   From                   Message
      ----    ------              ----  ----                   -------
      Normal  ScalingReplicaSet   12m   deployment-controller  Scaled up replica set nginx-deployment-75675f5897 to 3
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 1
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 2
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 2
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 1
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 3
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 0
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-595696685f to 1
      Normal  DeploymentRollback  15s   deployment-controller  Rolled back deployment "nginx-deployment" to revision 2
      Normal  ScalingReplicaSet   15s   deployment-controller  Scaled down replica set nginx-deployment-595696685f to 0
    

Mise à l'échelle d'un déploiement

Vous pouvez mettre à l'échelle un déploiement à l'aide de la commande suivante:

kubectl scale deployment.v1.apps/nginx-deployment --replicas=10

La sortie est similaire à ceci:

deployment.apps/nginx-deployment scaled

En supposant que l'horizontal Pod autoscaling est activé dans votre cluster, vous pouvez configurer une mise à l'échelle automatique pour votre déploiement et choisir le nombre minimum et maximum de pods que vous souhaitez exécuter en fonction de l'utilisation du processeur de vos pods existants.

kubectl autoscale deployment.v1.apps/nginx-deployment --min=10 --max=15 --cpu-percent=80

La sortie est similaire à ceci:

deployment.apps/nginx-deployment scaled

Mise à l'échelle proportionnelle

Les déploiements RollingUpdate prennent en charge l'exécution simultanée de plusieurs versions d'une application. Lorsque vous ou un autoscaler mettez à l'échelle un déploiement RollingUpdate qui se trouve au milieu d'un déploiement (en cours ou en pause), le contrôleur de déploiement équilibre les réplicas supplémentaires dans les ReplicaSets actifs existants (ReplicaSets avec pods) afin d'atténuer le risque. Ceci est appelé mise à l'échelle proportionnelle.

Par exemple, vous exécutez un déploiement avec 10 réplicas, maxSurge=3, et maxUnavailable=2.

  • Assurez-vous que les 10 réplicas de votre déploiement sont en cours d'exécution.

    kubectl get deploy
    

    La sortie est similaire à ceci:

    NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment     10        10        10           10          50s
    
  • Vous effectuez une mise à jour vers une nouvelle image qui s'avère impossible à résoudre depuis l'intérieur du cluster.

    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:sometag
    

    La sortie est similaire à ceci:

    deployment.apps/nginx-deployment image updated
    
  • La mise à jour de l'image démarre un nouveau déploiement avec ReplicaSet nginx-deployment-1989198191, mais elle est bloquée en raison de l'exigence maxUnavailable que vous avez mentionnée ci-dessus. Découvrez l'état du déploiement:

    kubectl get rs
    

    La sortie est similaire à ceci:

    NAME                          DESIRED   CURRENT   READY     AGE
    nginx-deployment-1989198191   5         5         0         9s
    nginx-deployment-618515232    8         8         8         1m
    
  • Ensuite, une nouvelle demande de mise à l'échelle pour le déploiement arrive. La mise à l'échelle automatique incrémente les réplicas de déploiement à 15. Le contrôleur de déploiement doit décider où ajouter ces 5 nouvelles répliques. Si vous n'utilisiez pas la mise à l'échelle proportionnelle, les 5 seraient ajoutés dans le nouveau ReplicaSet. Avec une mise à l'échelle proportionnelle, vous répartissez les répliques supplémentaires sur tous les ReplicaSets. Des proportions plus importantes vont aux ReplicaSets avec le plus de répliques et des proportions plus faibles vont aux ReplicaSets avec moins de replicas. Tous les restes sont ajoutés au ReplicaSet avec le plus de répliques. Les ReplicaSets avec zéro réplicas ne sont pas mis à l'échelle.

Dans notre exemple ci-dessus, 3 répliques sont ajoutées à l'ancien ReplicaSet et 2 répliques sont ajoutées au nouveau ReplicaSet. Le processus de déploiement devrait éventuellement déplacer toutes les répliques vers le nouveau ReplicaSet, en supposant que les nouvelles répliques deviennent saines. Pour confirmer cela, exécutez:

kubectl get deploy

La sortie est similaire à ceci:

NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment     15        18        7            8           7m

Le statut de déploiement confirme la façon dont les réplicas ont été ajoutés à chaque ReplicaSet.

kubectl get rs

La sortie est similaire à ceci:

NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-1989198191   7         7         0         7m
nginx-deployment-618515232    11        11        11        7m

Pause et reprise d'un déploiement

Vous pouvez suspendre un déploiement avant de déclencher une ou plusieurs mises à jour, puis le reprendre. Cela vous permet d'appliquer plusieurs correctifs entre la pause et la reprise sans déclencher de déploiements inutiles.

  • Par exemple, avec un déploiement qui vient d'être créé: Obtenez les détails du déploiement:

    kubectl get deploy
    

    La sortie est similaire à ceci:

    NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    nginx     3         3         3            3           1m
    

    Obtenez le statut de déploiement:

    kubectl get rs
    

    La sortie est similaire à ceci:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   3         3         3         1m
    
  • Mettez le déploiement en pause en exécutant la commande suivante:

    kubectl rollout pause deployment.v1.apps/nginx-deployment
    

    La sortie est similaire à ceci:

    deployment.apps/nginx-deployment paused
    
  • Mettez ensuite à jour l'image du déploiement:

    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
    

    La sortie est similaire à ceci:

    deployment.apps/nginx-deployment image updated
    
  • Notez qu'aucun nouveau déploiement n'a commencé:

    kubectl rollout history deployment.v1.apps/nginx-deployment
    

    La sortie est similaire à ceci:

    deployments "nginx"
    REVISION  CHANGE-CAUSE
    1   <none>
    
  • Obtenez l'état de déploiement pour vous assurer que le déploiement est correctement mis à jour:

    kubectl get rs
    

    La sortie est similaire à ceci:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   3         3         3         2m
    
  • Vous pouvez effectuer autant de mises à jour que vous le souhaitez, par exemple, mettre à jour les ressources qui seront utilisées:

    kubectl set resources deployment.v1.apps/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
    

    La sortie est similaire à ceci:

    deployment.apps/nginx-deployment resource requirements updated
    

    L'état initial du déploiement avant de le suspendre continuera de fonctionner, mais les nouvelles mises à jour du déploiement n'auront aucun effet tant que le déploiement sera suspendu.

  • Finalement, reprenez le déploiement et observez un nouveau ReplicaSet à venir avec toutes les nouvelles mises à jour:

    kubectl rollout resume deployment.v1.apps/nginx-deployment
    

    La sortie est similaire à ceci:

    deployment.apps/nginx-deployment resumed
    
  • Regardez l'état du déploiement jusqu'à ce qu'il soit terminé.

    kubectl get rs -w
    

    La sortie est similaire à ceci:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   2         2         2         2m
    nginx-3926361531   2         2         0         6s
    nginx-3926361531   2         2         1         18s
    nginx-2142116321   1         2         2         2m
    nginx-2142116321   1         2         2         2m
    nginx-3926361531   3         2         1         18s
    nginx-3926361531   3         2         1         18s
    nginx-2142116321   1         1         1         2m
    nginx-3926361531   3         3         1         18s
    nginx-3926361531   3         3         2         19s
    nginx-2142116321   0         1         1         2m
    nginx-2142116321   0         1         1         2m
    nginx-2142116321   0         0         0         2m
    nginx-3926361531   3         3         3         20s
    
  • Obtenez le statut du dernier déploiement:

    kubectl get rs
    

    La sortie est similaire à ceci:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   0         0         0         2m
    nginx-3926361531   3         3         3         28s
    

Statut de déploiement

Un déploiement entre dans différents états au cours de son cycle de vie. Il peut être progressant lors du déploiement d'un nouveau ReplicaSet, il peut être effectué, ou il peut ne pas progresser.

Progression du déploiement

Kubernetes marque un déploiement comme progressing lorsqu'une des tâches suivantes est effectuée:

  • Le déploiement crée un nouveau ReplicaSet.
  • Le déploiement augmente son nouveau ReplicaSet.
  • Le déploiement réduit ses anciens ReplicaSet.
  • De nouveaux pods deviennent prêts ou disponibles (prêt pour au moins MinReadySeconds).

Vous pouvez surveiller la progression d'un déploiement à l'aide de kubectl rollout status.

Déploiement effectué

Kubernetes marque un déploiement comme effectué lorsqu'il présente les caractéristiques suivantes:

  • Toutes les répliques associées au déploiement ont été mises à jour vers la dernière version que vous avez spécifiée, ce qui signifie que toutes les mises à jour que vous avez demandées ont été effectuées.
  • Toutes les répliques associées au déploiement sont disponibles.
  • Aucune ancienne réplique pour le déploiement n'est en cours d'exécution.

Vous pouvez vérifier si un déploiement est terminé en utilisant kubectl rollout status. Si le déploiement s'est terminé avec succès, kubectl rollout status renvoie un code de sortie de 0.

kubectl rollout status deployment.v1.apps/nginx-deployment

La sortie est similaire à ceci:

Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deployment" successfully rolled out
$ echo $?
0

Déploiement échoué

Votre déploiement peut rester bloqué en essayant de déployer son nouveau ReplicaSet sans jamais terminer. Cela peut se produire en raison de certains des facteurs suivants:

  • Quota insuffisant
  • Échecs de la sonde de préparation
  • Erreurs d'extraction d'image
  • Permissions insuffisantes
  • Plages limites
  • Mauvaise configuration de l'exécution de l'application

Vous pouvez détecter cette condition en spécifiant un paramètre d'échéance dans votre spécification de déploiement: (.spec.progressDeadlineSeconds). .spec.progressDeadlineSeconds indique le nombre de secondes pendant lesquelles le contrôleur de déploiement attend avant d'indiquer (dans l'état de déploiement) que la progression du déploiement est au point mort.

La commande kubectl suivante définit la spécification avec progressDeadlineSeconds pour que le contrôleur signale l'absence de progression pour un déploiement après 10 minutes:

kubectl patch deployment.v1.apps/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'

La sortie est similaire à ceci:

deployment.apps/nginx-deployment patched

Une fois le délai dépassé, le contrôleur de déploiement ajoute un DeploymentCondition avec les attributs suivants aux .status.conditions du déploiement:

  • Type=Progressing
  • Status=False
  • Reason=ProgressDeadlineExceeded

Voir les conventions Kubernetes API pour plus d'informations sur les conditions d'état.

Vous pouvez rencontrer des erreurs transitoires avec vos déploiements, soit en raison d'un délai d'attente bas que vous avez défini, soit en raison de tout autre type d'erreur pouvant être traité comme transitoire. Par exemple, supposons que votre quota soit insuffisant. Si vous décrivez le déploiement, vous remarquerez la section suivante:

kubectl describe deployment nginx-deployment

La sortie est similaire à ceci:

<...>
Conditions:
  Type            Status  Reason
  ----            ------  ------
  Available       True    MinimumReplicasAvailable
  Progressing     True    ReplicaSetUpdated
  ReplicaFailure  True    FailedCreate
<...>

Si vous exécutez kubectl get deployment nginx-deployment -o yaml, l'état de déploiement est similaire à ceci:

status:
  availableReplicas: 2
  conditions:
  - lastTransitionTime: 2016-10-04T12:25:39Z
    lastUpdateTime: 2016-10-04T12:25:39Z
    message: Replica set "nginx-deployment-4262182780" is progressing.
    reason: ReplicaSetUpdated
    status: "True"
    type: Progressing
  - lastTransitionTime: 2016-10-04T12:25:42Z
    lastUpdateTime: 2016-10-04T12:25:42Z
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  - lastTransitionTime: 2016-10-04T12:25:39Z
    lastUpdateTime: 2016-10-04T12:25:39Z
    message: 'Error creating: pods "nginx-deployment-4262182780-" is forbidden: exceeded quota:
      object-counts, requested: pods=1, used: pods=3, limited: pods=2'
    reason: FailedCreate
    status: "True"
    type: ReplicaFailure
  observedGeneration: 3
  replicas: 2
  unavailableReplicas: 2

Finalement, une fois la date limite de progression du déploiement dépassée, Kubernetes met à jour le statut et la raison de la condition de progression:

Conditions:
  Type            Status  Reason
  ----            ------  ------
  Available       True    MinimumReplicasAvailable
  Progressing     False   ProgressDeadlineExceeded
  ReplicaFailure  True    FailedCreate

Vous pouvez résoudre un problème de quota insuffisant en réduisant votre déploiement, en réduisant d'autres contrôleurs que vous exécutez ou en augmentant le quota de votre namespace. Si vous remplissez les conditions de quota et que le contrôleur de déploiement termine ensuite le déploiement de déploiement, vous verrez la mise à jour de l'état du déploiement avec une condition réussie (Status=True et Reason=NewReplicaSetAvailable).

Conditions:
  Type          Status  Reason
  ----          ------  ------
  Available     True    MinimumReplicasAvailable
  Progressing   True    NewReplicaSetAvailable

Type=Available avec Status=True signifie que votre déploiement a une disponibilité minimale. La disponibilité minimale est dictée par les paramètres spécifiés dans la stratégie de déploiement. Type=Progressing avec Status=True signifie que votre déploiement est soit au milieu d'un déploiement et qu'il progresse ou qu'il a terminé avec succès sa progression et que les nouvelles répliques minimales requises sont disponibles (voir la raison de la condition pour les détails - dans notre cas, Reason=NewReplicaSetAvailable signifie que le déploiement est terminé).

Vous pouvez vérifier si un déploiement n'a pas pu progresser en utilisant kubectl rollout status. kubectl rollout status renvoie un code de sortie différent de zéro si le déploiement a dépassé le délai de progression.

kubectl rollout status deployment.v1.apps/nginx-deployment

La sortie est similaire à ceci:

Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline
$ echo $?
1

Agir sur un déploiement échoué

Toutes les actions qui s'appliquent à un déploiement complet s'appliquent également à un déploiement ayant échoué. Vous pouvez le mettre à l'échelle à la hausse/baisse, revenir à une révision précédente ou même la suspendre si vous devez appliquer plusieurs réglages dans le modèle de pod de déploiement.

Politique de nettoyage

Vous pouvez définir le champ .spec.revisionHistoryLimit dans un déploiement pour spécifier le nombre d'anciens ReplicaSets pour ce déploiement que vous souhaitez conserver. Le reste sera effacé en arrière-plan. Par défaut, c'est 10.

Déploiement des Canaries

Si vous souhaitez déployer des versions sur un sous-ensemble d'utilisateurs ou de serveurs à l'aide du déploiement, vous pouvez créer plusieurs déploiements, un pour chaque version, en suivant le modèle canari décrit dans gestion des ressources.

Écriture d'une spécification de déploiement

Comme pour toutes les autres configurations Kubernetes, un déploiement a besoin des champs apiVersion, kind et metadata. Pour des informations générales sur l'utilisation des fichiers de configuration, voir déploiement d'applications, configuration des conteneurs, et Utilisation de kubectl pour gérer les ressources.

Un déploiement nécessite également un .spec section.

Pod Template

Les .spec.template et .spec.selector sont les seuls champs obligatoires du .spec.

Le .spec.template est un Pod template. Il a exactement le même schéma qu'un Pod, sauf qu'il est imbriqué et n'a pas de apiVersion ou de kind.

En plus des champs obligatoires pour un pod, un Pod Template dans un déploiement doit spécifier des labels appropriées et une stratégie de redémarrage appropriée. Pour les labels, assurez-vous de ne pas chevaucher l'action d'autres contrôleurs. Voir sélecteur).

Seulement un .spec.template.spec.restartPolicy égal à Always est autorisé, ce qui est la valeur par défaut s'il n'est pas spécifié.

Répliques

.spec.replicas est un champ facultatif qui spécifie le nombre de pods souhaités. Il vaut par défaut 1.

Sélecteur

.spec.selector est un champ obligatoire qui spécifie un sélecteur de labels pour les pods ciblés par ce déploiement.

.spec.selector doit correspondre .spec.template.metadata.labels, ou il sera rejeté par l'API.

Dans la version d'API apps/v1, .spec.selector et .metadata.labels ne sont pas définis par défaut sur .spec.template.metadata.labels s'ils ne sont pas définis. Ils doivent donc être définis explicitement. Notez également que .spec.selector est immuable après la création du déploiement dans apps/v1.

Un déploiement peut mettre fin aux pods dont les étiquettes correspondent au sélecteur si leur modèle est différent de .spec.template ou si le nombre total de ces pods dépasse .spec.replicas. Il fait apparaître de nouveaux pods avec .spec.template si le nombre de pods est inférieur au nombre souhaité.

Si vous avez plusieurs contrôleurs qui ont des sélecteurs qui se chevauchent, les contrôleurs se battront entre eux et ne se comporteront pas correctement.

Stratégie

.spec.strategy spécifie la stratégie utilisée pour remplacer les anciens pods par de nouveaux. .spec.strategy.type peut être "Recreate" ou "RollingUpdate". "RollingUpdate" est la valeur par défaut.

Déploiment Recreate

Tous les pods existants sont tués avant que de nouveaux ne soient créés lorsque .spec.strategy.type==Recreate.

Déploiement de mise à jour continue

Le déploiement met à jour les pods dans une mise à jour continue quand .spec.strategy.type==RollingUpdate. Vous pouvez spécifier maxUnavailable et maxSurge pour contrôler le processus de mise à jour continue.

Max non disponible

.spec.strategy.rollingUpdate.maxUnavailable est un champ facultatif qui spécifie le nombre maximal de pods qui peuvent être indisponibles pendant le processus de mise à jour. La valeur peut être un nombre absolu (par exemple, 5) ou un pourcentage des pods souhaités (par exemple, 10%). Le nombre absolu est calculé à partir du pourcentage en arrondissant vers le bas. La valeur ne peut pas être 0 si .spec.strategy.rollingUpdate.maxSurge est 0. La valeur par défaut est 25%.

Par exemple, lorsque cette valeur est définie sur 30%, l'ancien ReplicaSet peut être réduit à 70% des pods souhaités immédiatement au démarrage de la mise à jour continue. Une fois que les nouveaux pods sont prêts, l'ancien ReplicaSet peut être réduit davantage, suivi d'une augmentation du nouveau ReplicaSet, garantissant que le nombre total de pods disponibles à tout moment pendant la mise à jour est d'au moins 70% des pods souhaités.

Max Surge

.spec.strategy.rollingUpdate.maxSurge est un champ facultatif qui spécifie le nombre maximal de pods pouvant être créés sur le nombre de pods souhaité. La valeur peut être un nombre absolu (par exemple, 5) ou un pourcentage des pods souhaités (par exemple, 10%). La valeur ne peut pas être 0 si MaxUnavailable est 0. Le nombre absolu est calculé à partir du pourcentage en arrondissant. La valeur par défaut est 25%.

Par exemple, lorsque cette valeur est définie sur 30%, le nouveau ReplicaSet peut être mis à l'échelle immédiatement au démarrage de la mise à jour continue, de sorte que le nombre total d'anciens et de nouveaux pods ne dépasse pas 130% des pods souhaités. Une fois que les anciens pods ont été détruits, le nouveau ReplicaSet peut être augmenté davantage, garantissant que le nombre total de pods en cours d'exécution à tout moment pendant la mise à jour est au maximum de 130% des pods souhaités.

Progress Deadline Seconds

.spec.progressDeadlineSeconds est un champ facultatif qui spécifie le nombre de secondes pendant lesquelles vous souhaitez attendre que votre déploiement progresse avant que le système ne signale que le déploiement a échoué - refait surface comme une condition avec Type=Progressing, Status=False et Reason=ProgressDeadlineExceeded dans l'état de la ressource. Le contrôleur de déploiement continuera de réessayer le déploiement. À l'avenir, une fois la restauration automatique implémentée, le contrôleur de déploiement annulera un déploiement dès qu'il observera une telle condition.

S'il est spécifié, ce champ doit être supérieur à .spec.minReadySeconds.

Min Ready Seconds

.spec.minReadySeconds est un champ facultatif qui spécifie le nombre minimum de secondes pendant lequel un pod nouvellement créé doit être prêt sans qu'aucun de ses conteneurs ne plante, pour qu'il soit considéré comme disponible. Cette valeur par défaut est 0 (le pod sera considéré comme disponible dès qu'il sera prêt). Pour en savoir plus sur le moment où un pod est considéré comme prêt, consultez Sondes de conteneur.

Rollback To

Le champ .spec.rollbackTo est obsolète dans les versions d'API extensions/v1beta1 et apps/v1beta1 et n'est plus pris en charge dans les versions d'API commençant par apps/v1beta2. Utilisez, kubectl rollout undo pour Revenir à une révision précédente.

Limite de l'historique des révisions

L'historique de révision d'un déploiement est stocké dans les ReplicaSets qu'il contrôle.

.spec.revisionHistoryLimit est un champ facultatif qui spécifie le nombre d'anciens ReplicaSets à conserver pour permettre la restauration. Ces anciens ReplicaSets consomment des ressources dans etcd et encombrent la sortie de kubectl get rs. La configuration de chaque révision de déploiement est stockée dans ses ReplicaSets; par conséquent, une fois un ancien ReplicaSet supprimé, vous perdez la possibilité de revenir à cette révision du déploiement. Par défaut, 10 anciens ReplicaSets seront conservés, mais sa valeur idéale dépend de la fréquence et de la stabilité des nouveaux déploiements.

Plus précisément, la définition de ce champ à zéro signifie que tous les anciens ReplicaSets avec 0 réplicas seront nettoyés. Dans ce cas, un nouveau panneau déroulant Déploiement ne peut pas être annulé, car son historique de révision est nettoyé.

Paused

.spec.paused est un champ booléen facultatif pour suspendre et reprendre un déploiement. La seule différence entre un déploiement suspendu et un autre qui n'est pas suspendu, c'est que toute modification apportée au PodTemplateSpec du déploiement suspendu ne déclenchera pas de nouveaux déploiements tant qu'il sera suspendu. Un déploiement n'est pas suspendu par défaut lors de sa création.

Alternative aux déploiements

kubectl rolling-update

kubectl rolling-update met à jour les pods et les ReplicationControllers de la même manière. Mais les déploiements sont recommandés, car ils sont déclaratifs, côté serveur et ont des fonctionnalités supplémentaires, telles que la restauration de toute révision précédente même après la mise à jour progressive..

3 - StatefulSets

StatefulSet est l'objet de l'API de charge de travail utilisé pour gérer des applications avec état (stateful).

Gère le déploiement et la mise à l'échelle d'un ensemble de Pods, et fournit des garanties sur l'ordre et l'unicité de ces Pods.

Comme un Déploiement, un StatefulSet gère des Pods qui sont basés sur une même spécification de conteneur. Contrairement à un Deployment, un StatefulSet maintient une identité pour chacun de ces Pods. Ces Pods sont créés à partir de la même spec, mais ne sont pas interchangeables : chacun a un identifiant persistant qu'il garde à travers tous ses re-scheduling.

Si vous voulez utiliser des volumes de stockage pour fournir de la persistance à votre charge de travail, vous pouvez utiliser un StatefulSet comme partie de la solution. Même si des Pods individuels d'un StatefulSet sont susceptibles d'échouer, les identifiants persistants des Pods rendent plus facile de faire correspondre les volumes existants aux nouveaux Pods remplaçant ceux ayant échoué.

Utiliser des StatefulSets

Les StatefulSets sont utiles pour des applications qui nécessitent une ou plusieurs des choses suivantes :

  • Des identifiants réseau stables et uniques.
  • Un stockage persistant stable.
  • Un déploiement et une mise à l'échelle ordonnés et contrôlés.
  • Des mises à jour continues (rolling update) ordonnées et automatisées.

Ci-dessus, stable est synonyme de persistance suite au (re)scheduling de Pods. Si une application ne nécessite aucun identifiant stable ou de déploiement, suppression ou mise à l'échelle stables, vous devriez déployer votre application en utilisant un objet de charge de travail fournissant un ensemble de réplicas sans état (stateless).

Un Deployment ou ReplicaSet peut être mieux adapté pour vos applications sans état.

Limitations

  • Le stockage pour un Pod donné doit être provisionné soit par un approvisionneur de PersistentVolume basé sur un storage class donné, soit pré-provisionné par un admin.
  • Supprimer et/ou réduire l'échelle d'un StatefulSet à zéro ne supprimera pas les volumes associés avec le StatefulSet. Ceci est fait pour garantir la sécurité des données, ce qui a généralement plus de valeur qu'une purge automatique de toutes les ressources relatives à un StatefulSet.
  • Les StatefulSets nécessitent actuellement un Service Headless qui est responsable de l'identité réseau des Pods. Vous êtes responsable de la création de ce Service.
  • Les StatefulSets ne fournissent aucune garantie de la terminaison des pods lorsqu'un StatefulSet est supprimé. Pour avoir une terminaison ordonnée et maîtrisée des pods du StatefulSet, il est possible de réduire l'échelle du StatefulSet à 0 avant de le supprimer.
  • Lors de l'utilisation de Rolling Updates avec la Politique de gestion des Pods par défaut (OrderedReady), il est possible de tomber dans un état indéfini nécessitant une intervention manuelle pour réparer.

Composants

L'exemple ci-dessous décrit les composants d'un StatefulSet.

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # doit correspondre à .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # est 1 par défaut
  template:
    metadata:
      labels:
        app: nginx # doit correspondre à .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi

Dans l'exemple ci-dessus :

  • Un Service Headless, appelé nginx, est utilisé pour contrôler le domaine réseau.
  • Le StatefulSet, appelé web, a une Spec indiquant que 3 réplicas du container nginx seront démarrés dans des Pods.
  • Le volumeClaimTemplates fournira un stockage stable utilisant des PersistentVolumes provisionnés par un approvisionneur de PersistentVolume.

Le nom d'un objet StatefulSet doit être un nom de sous-domaine DNS valide.

Sélecteur de Pod

Vous devez renseigner le champ .spec.selector d'un StatefulSet pour qu'il corresponde aux labels de son .spec.template.metadata.labels. Avant Kubernetes 1.8, le champ .spec.selector était mis par défaut s'il était omis. Pour les versions 1.8 et ultérieures, ne pas spécifier de sélecteur de Pod résulte en une erreur de validation lors de la création du StatefulSet.

Identité du Pod

Les Pods d'un StatefulSet ont une identité unique comprenant un ordinal, une identité réseau stable et un stockage stable. L'identité est accrochée au Pod, indépendamment du noeud sur lequel il est (re)programmé.

Index Ordinal

Pour un StatefulSet avec N réplicas, chaque Pod du StatefulSet se verra assigné un ordinal entier, de 0 à N-1, unique sur l'ensemble des pods.

ID réseau stable

Chaque Pod dans un StatefulSet dérive son nom d'hôte du nom du StatefulSet et de l'ordinal du Pod. Le modèle pour le nom d'hôte généré est $(nom statefulset)-$(ordinal). L'exemple ci-dessus créera trois Pods nommés web-0,web-1,web-2. Un StatefulSet peut utiliser un Service Headless pour contrôler le domaine de ses Pods. Le domaine pris en charge par ce Service prend la forme : $(nom service).$(namespace).svc.cluster.local, où "cluster.local" est le domaine du cluster. Chaque fois qu'un Pod est créé, il obtient un sous-domaine DNS correspondant, prenant la forme : $(nom pod).$(domaine du service gouvernant), où le service gouvernant est défini par le champ serviceName du StatefulSet.

En fonction de la façon dont est configuré le DNS dans votre cluster, vous ne pourrez peut-être pas rechercher immédiatement le nom DNS d'un pod nouvellement exécuté. Ce problème peut se produire lorsque d'autres clients dans le cluster ont déjà envoyé des requêtes pour le nom d'hôte du Pod avant sa création. La mise en cache négative (normale pour le DNS) signifie que les résultats des recherches précédentes ayant échoué sont mémorisés et réutilisés, même après que le Pod ait démarré, pendant au moins quelques secondes.

Si vous avez besoin de découvrir les Pods rapidement après leur création, vous avez plusieurs options :

  • Interrogez directement l'API Kubernetes (par exemple, à l'aide d'un watch) plutôt que de vous fier aux recherches DNS.
  • Réduisez le temps de mise en cache dans votre fournisseur de DNS Kubernetes (cela signifie généralement modifier le ConfigMap de CoreDNS, qui met actuellement en cache pendant 30 secondes).

Comme mentionné dans la section limitations, vous êtes responsable de créer le Service Headless responsable de l'identité réseau des Pods.

Voici quelques exemples de choix pour le domaine du cluster, le nom du service, le nom du StatefulSet et comment cela affecte les noms DNS des pods du StatefulSet.

Domaine ClusterService (ns/nom)StatefulSet (ns/nom)Domaine StatefulSetDNS PodNom d'hôte
cluster.localdefault/nginxdefault/webnginx.default.svc.cluster.localweb-{0..N-1}.nginx.default.svc.cluster.localweb-{0..N-1}
cluster.localfoo/nginxfoo/webnginx.foo.svc.cluster.localweb-{0..N-1}.nginx.foo.svc.cluster.localweb-{0..N-1}
kube.localfoo/nginxfoo/webnginx.foo.svc.kube.localweb-{0..N-1}.nginx.foo.svc.kube.localweb-{0..N-1}

Stockage stable

Kubernetes crée un PersistentVolume pour chaque VolumeClaimTemplate. Dans l'exemple nginx ci-dessus, chaque Pod se verra affecter un unique PersistentVolume avec un StorageClass de my-storage-class et 1 Gib de stockage provisionné. Si aucun StorageClass n'est spécifié, alors le StorageClass par défaut sera utilisé. Lorsqu'un Pod est (re)schedulé sur un noeud, ses volumeMounts montent les PersistentVolumes associés aux
PersistentVolumeClaims. Notez que les PersistentVolumes associés avec les PersistentVolumeClaims des Pods ne sont pas supprimés lorsque les Pods, ou le StatefulSet, sont supprimés. Ceci doit être fait manuellement.

Étiquette du nom de Pod

Lorsque le StatefulSet Contrôleur crée un Pod, il ajoute une étiquette, statefulset.kubernetes.io/pod-name, renseignée avec le nom du Pod. Cette étiquette vous permet d'attacher un Service à un Pod spécifique du StatefulSet.

Garanties de déploiement et de mise à l'échelle

  • Pour un StatefulSet avec N réplicas, lorsque les Pods sont déployés, ils sont créés de manière séquentielle, dans l'ordre {0..N-1}.
  • Lorsque les Pods sont supprimés, ils sont terminés dans l'ordre inverse, {N-1..0}.
  • Avant qu'une opération de mise à l'échelle soit appliquée à un Pod, tous ses prédécesseurs doivent être Running et Ready.
  • Avant qu'un Pod soit terminé, tous ses successeurs doivent être complètement arrêtés.

Le StatefulSet ne devrait pas spécifier un pod.Spec.TerminationGracePeriodSeconds à 0. Cette pratique est dangereuse et fortement déconseillée. Pour plus d'explications, veuillez vous référer à forcer la suppression de Pods de StatefulSet.

Lorsque l'exemple nginx ci-dessus est créé, trois Pods seront déployés dans l'ordre web-0, web-1, web-2. web-1 ne sera pas déployé avant que web-0 soit Running et Ready, et web-2 ne sera pas déployé avant que web-1 soit Running et Ready. Si web-0 venait à échouer, après que web-1 soit Running et Ready, mais avant que web-2 soit lancé, web-2 ne serait pas lancé avant que web-0 soit correctement relancé et redevienne Running et Ready.

Si un utilisateur venait à mettre à l'échelle l'exemple déployé en patchant le StatefulSet pour que replicas=1, web-2 serait terminé en premier. web-1 ne serait pas terminé avant que web-2 ne soit complètement arrêté et supprimé. Si web-0 venait à échouer après que web-2 soit terminé et complètement arrêté, mais avant que web-1 soit terminé, web-1 ne serait pas terminé avant que web-0 soit Running et Ready.

Politiques de gestion d'un Pod

Dans Kubernetes 1.7 et ultérieurs, le StatefulSet vous permet d'assouplir ses garanties d'ordre, tout en préservant ses garanties d'unicité et d'identité via son champ .spec.podManagementPolicy.

Gestion de Pod OrderedReady

La gestion de Pod OrderedReady est la valeur par défaut pour les StatefulSets. Il implémente le comportement décrit ci-dessus.

Gestion de Pod Parallel

La gestion de Pod Parallel indique au contrôleur de StatefulSet de lancer ou terminer tous les Pods en parallèle, et de ne pas attendre que les Pods deviennent Running et Ready ou complètement terminés avant de lancer ou terminer un autre Pod. Cette option affecte seulement le comportement pour les opérations de mise à l'échelle. Les mises à jour ne sont pas affectées.

Stratégies de mise à jour

Dans Kubernetes 1.7 et ultérieurs, le champ .spec.updateStrategy d'un StatefulSet vous permet de configurer et désactiver les rolling updates automatisés pour les conteneurs, étiquettes, requête/limites de ressources, et annotations pour les Pods d'un StatefulSet.

On Delete

La stratégie de mise à jour OnDelete implémente l'ancien comportement (1.6 et précédents). Lorsque .spec.updateStrategy.type d'un StatefulSet est mis à OnDelete, le contrôleur de StatefulSet ne mettra pas à jour automatiquement les Pods dans un StatefulSet. Les utilisateurs doivent supprimer manuellement les Pods pour forcer le contrôleur à créer de nouveaux Pods qui réflètent les modifications faites à un .spec.template d'un StatefulSet.

Rolling Updates

La stratégie de mise à jour RollingUpdate implémente le rolling update automatisé pour les Pods d'un StatefulSet. C'est la stratégie par défaut lorsque .spec.updateStrategy n'est pas spécifié. Lorsqu'un .spec.updateStrategy.type d'un StatefulSet est mis à RollingUpdate, le contrôleur de StatefulSet va supprimer et recréer chaque Pod d'un StatefulSet. Il va procéder dans le même ordre que pour la terminaison d'un Pod (de l'ordinal le plus grand au plus petit), mettant à jour chaque Pod, un seul à la fois. Il va attendre qu'un Pod mis à jour soit Running et Ready avant de mettre à jour son prédécesseur.

Partitions

La stratégie de mise à jour RollingUpdate peut être partitionnée, en spécifiant une .spec.updateStrategy.rollingUpdate.partition. Si une partition est spécifiée, tous les Pods ayant un ordinal plus grand ou égal à la partition seront mis à jour lorsque le .spec.template du StatefulSet sera mis à jour. Tous les Pods ayant un ordinal inférieur à la partition ne sera pas mis à jour, et, même s'ils sont supprimés, ils seront recréés avec l'ancienne version. Si une .spec.updateStrategy.rollingUpdate.partition d'un StatefulSet est plus grand que son .spec.replicas, les mises à jour de son .spec.template ne seront pas propagés à ses Pods. Dans la plupart des cas vous n'aurez pas à utiliser de partition, mais elles sont utiles si vous désirez organiser une mise à jour, déployer une version canari, ou effectuer un déploiement par étapes.

Rollback forcé

En utilisant des Rolling Updates avec la politique de gestion d'un Pod par défaut (OrderedReady), il est possible de se retrouver dans un état inconsistant nécessitant une intervention manuelle pour réparation.

Si vous mettez à jour le template de Pod dans une configuration qui ne devient jamais Running et Ready (par exemple, du fait d'un mauvais binaire ou d'une erreur de configuration au niveau de l'application), le StatefulSet va arrêter le rollout et attendre.

Dans cet état, il n'est pas suffisant de revenir à une bonne configuration du template de Pod. En raison d'une erreur connue, le StatefulSet va continuer à attendre que le Pod en échec Pod devienne Ready (ce qui n'arrive jamais) avant qu'il tente de revenir à la bonne configuration.

Après être revenu au bon template, vous devez aussi supprimer tous les Pods que le StatefulSet avait déjà essayé de démarrer avec la mauvaise configuration. Le StatefulSet va alors commencer à recréer les Pods en utilisant le bon template.

A suivre