Kubernetes comment effectuer un déploiement pour mettre à jour l'image

131

J'ai un déploiement avec un seul pod, avec mon image de menu fixe personnalisée comme:

containers:
  - name: mycontainer
    image: myimage:latest

Pendant le développement, je veux pousser la nouvelle version la plus récente et mettre à jour le déploiement. Impossible de trouver comment faire cela, sans définir explicitement la balise / version et l'incrémenter pour chaque build, et faire

kubectl set image deployment/my-deployment mycontainer=myimage:1.9.1
au-dessus du soleil
la source

Réponses:

151

Vous pouvez configurer votre pod avec une période de grâce (par exemple 30 secondes ou plus, selon l'heure de démarrage du conteneur et la taille de l'image) et définir "imagePullPolicy: "Always". Et utilisez kubectl delete pod pod_name. Un nouveau conteneur sera créé et la dernière image téléchargée automatiquement, puis l'ancien conteneur se terminera.

Exemple:

spec:
  terminationGracePeriodSeconds: 30
  containers:
  - name: my_container
    image: my_image:latest
    imagePullPolicy: "Always"

J'utilise actuellement Jenkins pour les builds automatisés et le marquage d'image et cela ressemble à ceci:

kubectl --user="kube-user" --server="https://kubemaster.example.com"  --token=$ACCESS_TOKEN set image deployment/my-deployment mycontainer=myimage:"$BUILD_NUMBER-$SHORT_GIT_COMMIT"

Une autre astuce consiste à exécuter initialement:

kubectl set image deployment/my-deployment mycontainer=myimage:latest

puis:

kubectl set image deployment/my-deployment mycontainer=myimage

Cela déclenchera en fait la mise à jour continue, mais assurez-vous que vous avez également imagePullPolicy: "Always"défini.

Mettre à jour:

une autre astuce que j'ai trouvée, où vous n'avez pas à changer le nom de l'image, est de changer la valeur d'un champ qui déclenchera une mise à jour progressive, comme terminationGracePeriodSeconds. Vous pouvez le faire en utilisant kubectl edit deployment your_deploymentou kubectl apply -f your_deployment.yamlou en utilisant un patch comme celui-ci:

kubectl patch deployment your_deployment -p \
  '{"spec":{"template":{"spec":{"terminationGracePeriodSeconds":31}}}}'

Assurez-vous simplement de toujours modifier la valeur numérique.

Camil
la source
1
En fait c'est votre truc n'est pas mal, vu myimage: lastet et myimage fondamentalement la même chose, merci!
dessus du
1
Cette astuce ressemble plus à un bug, je ne sais pas pourquoi nous devons le spécifier deux fois.
speedplane
2
Si vous voulez qu'un déploiement kubernetes démarre un nouveau pod en utilisant la même image (et cette astuce ne fonctionne qu'avec la balise "latest"), vous devez le spécifier sans balise. La prochaine fois, ajoutez la balise "dernière" et cela déclenchera la mise à jour. L'ordre pourrait être inversé, peu importe. Vous n'utilisez jamais la balise "la plus récente" en production, mais à des fins de développement, vous pouvez parfois en bénéficier.
Camil
2
Cela ne fonctionne que pour le dernier. Par défaut, au moins dans docker hub, en ne balisant pas une image, il assumera la balise "dernière". Mais fonctionnera aussi sans cela. Cet exemple n'est pas quelque chose que vous voudrez dans un environnement de production, et il n'y a pas beaucoup de cas d'utilisation où vous pouvez également en bénéficier en développement. Il existe de meilleures méthodes pour mettre à jour une image automatiquement, à l'aide d'un outil CI / CD.
Camil
11
Chaque fois que vous modifiez la balise et exécutez la kubectl set imagecommande, kubernetes effectuera une mise à jour progressive. Par exemple, disons que vous avez déployé "repo / myimage: latest". Pendant ce temps, votre image a été modifiée et transférée vers le dépôt avec la balise "v0.2". Vous pouvez effectuer une mise à jour en exécutant kubectl set image deployment/my-deployment mycontainer=myimage:v0.2Cette image aura également la balise "dernière".
Camil
73

MISE À JOUR 2019-06-24

Sur la base du commentaire @Jodiug, si vous avez une 1.15version, vous pouvez utiliser la commande:

kubectl rollout restart deployment/demo

En savoir plus sur le problème:

https://github.com/kubernetes/kubernetes/issues/13488


Eh bien, il y a une discussion intéressante à ce sujet sur le projet Kubernetes GitHub. Voir le problème: https://github.com/kubernetes/kubernetes/issues/33664

À partir des solutions décrites ici, je suggérerais l'une des deux.

Première

1. préparer le déploiement

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: demo
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: demo
        image: registry.example.com/apps/demo:master
        imagePullPolicy: Always
        env:
        - name: FOR_GODS_SAKE_PLEASE_REDEPLOY
          value: 'THIS_STRING_IS_REPLACED_DURING_BUILD'

2. déployer

sed -ie "s/THIS_STRING_IS_REPLACED_DURING_BUILD/$(date)/g" deployment.yml
kubectl apply -f deployment.yml

Deuxième (une doublure):

kubectl patch deployment web -p \
  "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}"

Bien sûr, le imagePullPolicy: Alwaysest requis dans les deux cas.

Przemek Nowak
la source
J'ai trouvé une autre astuce connexe. Si vous faites simplement "kubectl rollout restart deployment" sans spécifier de nom de déploiement spécifique, "tous" les feront.
Lennart Rolland
21
kubectl rollout restart deployment myapp

C'est la manière actuelle de déclencher une mise à jour progressive et de laisser les anciens jeux de répliques en place pour d'autres opérations fournies par des kubectl rolloutrestaurations similaires.

Martin Peter
la source
@Prathameshdhanawade l'opération de patch n'a pas de undocommande ou équivalent.
Martin Peter
7

J'utilise Gitlab-CI pour créer l'image, puis la déployer directement sur GCK. Si vous utilisez une petite astuce pour réaliser une mise à jour progressive sans changer les paramètres réels du conteneur, ce qui change une étiquette en commit-short-sha actuel.

Ma commande ressemble à ceci:

kubectl patch deployment my-deployment -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"build\":\"$CI_COMMIT_SHORT_SHA\"}}}}}}"

Où vous pouvez utiliser n'importe quel nom et n'importe quelle valeur pour l'étiquette tant qu'elle change à chaque build.

S'amuser!

David Faber
la source
6

Il semble que k8s s'attend à ce que nous fournissions une balise d'image différente pour chaque déploiement. Ma stratégie par défaut serait de faire en sorte que le système CI génère et pousse les images du docker, en les étiquetant avec le numéro de build:xpmatteo/foobar:456 .

Pour le développement local, il peut être pratique d'utiliser un script ou un makefile, comme ceci:

# create a unique tag    
VERSION:=$(shell date +%Y%m%d%H%M%S)
TAG=xpmatteo/foobar:$(VERSION)

deploy:
    npm run-script build
    docker build -t $(TAG) . 
    docker push $(TAG)
    sed s%IMAGE_TAG_PLACEHOLDER%$(TAG)% foobar-deployment.yaml | kubectl apply -f - --record

La sedcommande remplace un espace réservé dans le document de déploiement par la balise d'image réellement générée.

xpmatteo
la source
kubernetes ne vous oblige pas à mettre à jour le déploiement avec une nouvelle balise afin d'extraire la version la plus récente de n'importe quelle image, «la plus récente» étant l'exemple le plus courant.
Dave White
1

J'utilise Azure DevOps pour déployer les applications de conteneurisation, je parviens facilement à surmonter ce problème en utilisant l'ID de build

Chaque fois que ses builds et génèrent le nouvel ID de build, j'utilise cet ID de build comme balise pour l'image docker, voici un exemple

imageename: buildID

une fois que votre image est construite (CI) avec succès, dans le pipeline de CD dans le fichier yml de déploiement, j'ai donné le nom de l'image comme

imagename: env: buildID

ici evn: buildid est la variable azure devops qui a la valeur de build ID.

donc maintenant, chaque fois que j'ai de nouveaux changements à construire (CI) et à déployer (CD).

veuillez commenter si vous avez besoin d'une définition de construction pour CI / CD.

Noman Sadiq
la source
Le manifeste fait partie du repo. Je ne comprends pas quelles sont les meilleures pratiques pour cela. Si je construis l'image dans le pipeline, dois-je pousser pour maîtriser le manifeste mis à jour? ou devrais-je produire un manifeste mis à jour pour les artefacts (et donc le manifeste dans le dépôt ne serait qu'un modèle sans l'image étiquetée réelle)?
pablete le