Comment forcer Kubernetes à extraire à nouveau une image?

161

J'ai le contrôleur de réplication suivant dans Kubernetes sur GKE:

apiVersion: v1
kind: ReplicationController
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  replicas: 2
  selector:
    app: myapp
    deployment: initial
  template:
    metadata:
      labels:
        app: myapp
        deployment: initial
    spec:
      containers:
      - name: myapp
        image: myregistry.com/myapp:5c3dda6b
        ports:
        - containerPort: 80
      imagePullPolicy: Always
      imagePullSecrets:
        - name: myregistry.com-registry-key

Maintenant, si je dis

kubectl rolling-update myapp --image=us.gcr.io/project-107012/myapp:5c3dda6b

la mise à jour progressive est effectuée, mais pas de nouvelle extraction. Pourquoi?

Torsten Bronger
la source
12
J'ai donné une image différente, juste avec le même tag. S'il est nécessaire de donner une balise différente, eh bien, je ne vois aucun intérêt dans le imagePullPolicydomaine.
Torsten Bronger
4
Je souhaite utiliser une balise spécifique, mais sa dernière version.
Torsten Bronger
3
@TorstenBronger Je pense que c'est un changement radical dans la théorie de Kubernetes / Docker. L'idée que vous pourriez extraire image: tag (autre que la dernière) à deux moments différents et obtenir deux images différentes serait problématique. Une balise s'apparente à un numéro de version. Il serait préférable de toujours changer l'étiquette lorsque l'image change.
duct_tape_coder
2
Ça dépend. Il existe des logiciels avec une API très stable mais des mises à jour de sécurité. Ensuite, je veux la dernière version sans avoir à le dire explicitement.
Torsten Bronger
1
@TorstenBronger En ce qui concerne l'utilisation latest, ne le faites pas. La dernière tirera l'image, enfin, la plus récente avec la dernière balise. Ce que vous voulez, c'est une gamme SemVer. ~ 1.2.3 par exemple. cela tirera les images avec des balises comprises entre> = 1.2.3 et <1.3.0. Tant que le fournisseur d'images suit SemVer votre connaissance (et c'est la partie importante), aucun changement de rupture en arrière n'a été ajouté (exprès) et qu'aucune nouvelle fonctionnalité n'a été ajoutée (problème de sécurité possible). Veuillez ne jamais utiliser latestdans les systèmes de production.
David J Eddy

Réponses:

141

Kubernetes tirera sur la création du pod si l'un ou l'autre (voir le document de mise à jour d'images ):

  • Utilisation d'images marquées :latest
  • imagePullPolicy: Always est spécifié

C'est génial si vous voulez toujours tirer. Mais que se passe-t-il si vous souhaitez le faire à la demande : par exemple, si vous souhaitez utiliser some-public-image:latestmais que vous souhaitez uniquement extraire une version plus récente manuellement lorsque vous le demandez. Vous pouvez actuellement:

  • Définir imagePullPolicysur IfNotPresentou Neveret pré-extraire : tirez manuellement les images sur chaque nœud du cluster afin que le dernier soit mis en cache, puis faites un kubectl rolling-updateou similaire pour redémarrer les pods (hack facile à casser!)
  • Changer temporairementimagePullPolicy , faire un kubectl apply, redémarrer le pod (par exemple kubectl rolling-update), revenir en arrière imagePullPolicy, refaire un kubectl apply(moche!)
  • Tirez et poussez some-public-image:latest vers votre référentiel privé et faites un kubectl rolling-update(lourd!)

Aucune bonne solution pour l'extraction à la demande. Si cela change, veuillez commenter; Je vais mettre à jour cette réponse.

Wernight
la source
Vous dites que kubernetes tirera parti de la création de pod lors de l'utilisation :latest- qu'en patchest-il? tire-t-il également toujours la dernière / dernière image? Semble ne pas fonctionner pour moi :(
pkyeck
Cela dépend si votre patch force ou non la recréation d'un pod. Très probablement pas, alors il ne tirera plus. Vous pouvez tuer le pod manuellement ou marquer avec quelque chose d'unique et corriger avec cette balise mise à jour.
Wernight
Ceci est une réponse à une question différente. J'ai demandé de forcer une nouvelle traction.
Torsten Bronger
Cela m'a permis de forcer un nouveau pull de GCR. J'avais une :latestbalise qui pointait vers une nouvelle image, et le kubectl rolling-updatetravail pour mettre à jour les pods.
Randy L
Merci. Je suis allé pour l'approche Pull & Push. Automatisé autant que possible avec des scripts bash mais d'accord, c'est lourd :)
arcseldon
77

Il faut regrouper imagePullPolicyles données du conteneur au lieu des données de spécification. Cependant, j'ai déposé un problème à ce sujet parce que je trouve cela étrange. De plus, il n'y a pas de message d'erreur.

Donc, cet extrait de spécification fonctionne:

spec:
  containers:
  - name: myapp
    image: myregistry.com/myapp:5c3dda6b
    ports:
    - containerPort: 80
    imagePullPolicy: Always
  imagePullSecrets:
    - name: myregistry.com-registry-key
Torsten Bronger
la source
3
imagePullPolicy(ou taguer :latest) est bon si vous voulez toujours tirer, mais ne résout pas la question du tirage à la demande.
Wernight
1
Oui, je veux toujours tirer, comme indiqué dans la question.
Torsten Bronger
1
L'utilisation de l' imagePullPolicy: Alwaysintérieur de la définition du conteneur aura pour effet de kubernetesrécupérer des images étiquetées :latestchaque fois qu'une version plus récente d'entre elles est poussée vers le registre?
pkaramol
1
@pkaramol No. imagePullPolicy: Alwaysdit simplement à Kubernetes de toujours extraire l'image du registre. Quelle image il sera est configuré par imageattribut. Si vous le configurez sur image: your-image:latest, il tirera toujours l' your-imageimage avec la latestbalise.
Gajus
26

Mon hack pendant le développement est de changer mon manifeste de déploiement pour ajouter la dernière balise et toujours tirer comme ça

image: etoews/my-image:latest
imagePullPolicy: Always

Ensuite, je supprime le pod manuellement

kubectl delete pod my-app-3498980157-2zxhd

Comme il s'agit d'un déploiement, Kubernetes recrée automatiquement le pod et extrait la dernière image.

Everett Toews
la source
J'aime profiter des prémisses "état souhaité" de l'objet "déploiement" ... merci pour la suggestion!
Marcello de Sales
2
Il convient de noter que cette stratégie n'est viable que si les pannes du service et les temps d'arrêt sont tolérables. Pour le développement, cela semble raisonnable, mais je ne reprendrais jamais cette stratégie pour un déploiement en production.
digitaldreamer
Modifier le déploiement, changer l'imagePullPolicy en toujours et supprimer le pod me suffisait, comme Everett l'a suggéré. Il s'agit cependant d'un environnement de développement. kubernetes.io/docs/concepts/containers/images
Jos Roberto Almaraz
17

Une solution de contournement courante consiste à corriger le déploiement avec une annotation factice (ou une étiquette):

kubectl patch deployment <name> -p \
  "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}"

En supposant que votre déploiement réponde à ces exigences , les K8 tireront toute nouvelle image et se redéployeront.

Tamlyn
la source
2
Oui, j'utilise une annotation pour cela.
Torsten Bronger
quelle annotation?
Jeryl Cook
1
Une autre solution sophistiquée serait une combinaison des deux ie. ajouter une annotation et définir ImagePullPolicycomme Toujours . des annotations comme deployment.kubernetes.io/revision: "v-someversion"et kubernetes.io/change-cause: the reasonpeuvent être très utiles et se dirigent vers des déploiements immuables.
chandan
16

Il y aura une nouvelle commande pour faire cela directement:

Créez une nouvelle kubectl rollout restartcommande qui effectue un redémarrage progressif d'un déploiement.

La demande d'extraction a été fusionnée. Il fera partie de la version 1.15( changelog )

S.Spieker
la source
Oui, partie du numéro: github.com/kubernetes/kubernetes/issues/13488
Tilo
Oui, c'est le meilleur moyen de déclencher la mise à jour dans la nouvelle version Kubernetes de 1.15.
Dolphin le
7

Apparemment maintenant, lorsque vous exécutez une mise à jour progressive avec l' --imageargument identique à l'image de conteneur existante, vous devez également spécifier un fichier --image-pull-policy. La commande suivante doit forcer une extraction de l'image lorsqu'elle est identique à l'image du conteneur:

kubectl rolling-update myapp --image=us.gcr.io/project-107012/myapp:5c3dda6b --image-pull-policy Always

sjking
la source
6
# Linux

kubectl patch deployment <name> -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}"

# windows

kubectl patch deployment <name> -p (-join("{\""spec\"":{\""template\"":{\""metadata\"":{\""annotations\"":{\""date\"":\""" , $(Get-Date -Format o).replace(':','-').replace('+','_') , "\""}}}}}"))
Bar Nuri
la source
3

Désormais, la commande kubectl rollout restart deploy YOUR-DEPLOYMENTcombinée à une imagePullPolicy: Alwayspolitique vous permettra de redémarrer tous vos pods avec une dernière version de votre image.

Orabîg
la source
3

La commande de mise à jour progressive, lorsqu'elle est donnée un argument d'image, suppose que l'image est différente de ce qui existe actuellement dans le contrôleur de réplication.

Robert Bailey
la source
Cela signifie-t-il que la balise d'image (alias nom) doit être différente?
Torsten Bronger
Oui, le nom de l'image doit être différent si vous passez le --imagedrapeau.
Robert Bailey
1
Comme le dit ma propre réponse, cela fonctionne aussi si le nom de l'image est le même. C'était simplement que l'imagePullPolicy était au mauvais endroit. Pour ma défense, la documentation du k8s 1.0 est erronée à cet égard.
Torsten Bronger
Je dois adorer quand les documents ne sont pas synchronisés avec le comportement. : /
Robert Bailey
1
Cette URL est également obsolète.
Dan Tenenbaum le
2

Vous pouvez définir imagePullPolicy: Alwaysdans votre fichier de déploiement.

Sachin Arote
la source
0

La politique d'extraction d'image aidera toujours à extraire l'image chaque fois qu'un nouveau pod est créé (cela peut être dans tous les cas comme la mise à l'échelle des répliques, ou le pod meurt et un nouveau pod est créé)

Mais si vous souhaitez mettre à jour l'image du pod en cours d'exécution, le déploiement est le meilleur moyen. Cela vous laisse une mise à jour sans faille sans aucun problème (principalement lorsque vous avez un volume persistant attaché au pod) :)

Harish Desetti
la source