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?


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.


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

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.


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.


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


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


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('+','_') , "\""}}}}}"))

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.


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.


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.


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) :)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.