Kubernetes come eseguire la distribuzione per aggiornare l'immagine


131

Ho una distribuzione con un singolo pod, con la mia immagine docker personalizzata come:

containers:
  - name: mycontainer
    image: myimage:latest

Durante lo sviluppo desidero eseguire il push della nuova versione più recente e aggiornare la distribuzione. Non riesco a trovare come farlo, senza definire esplicitamente tag / versione e incrementarlo per ogni build, e fallo

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

Risposte:


151

Puoi configurare il tuo pod con un periodo di grazia (ad esempio 30 secondi o più, a seconda del tempo di avvio del contenitore e delle dimensioni dell'immagine) e impostare "imagePullPolicy: "Always". E usa kubectl delete pod pod_name. Verrà creato un nuovo contenitore e verrà scaricata automaticamente l'ultima immagine, quindi il vecchio contenitore verrà chiuso.

Esempio:

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

Attualmente sto utilizzando Jenkins per build automatizzate e tag di immagini e assomiglia a questo:

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

Un altro trucco è eseguire inizialmente:

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

e poi:

kubectl set image deployment/my-deployment mycontainer=myimage

In realtà attiverà l'aggiornamento continuo, ma assicurati di aver imagePullPolicy: "Always"impostato anche .

Aggiornare:

un altro trucco che ho trovato, in cui non devi cambiare il nome dell'immagine, è cambiare il valore di un campo che attiverà un aggiornamento continuo, come terminationGracePeriodSeconds. È possibile farlo utilizzando kubectl edit deployment your_deploymento kubectl apply -f your_deployment.yamloppure utilizzando una patch in questo modo:

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

Assicurati solo di cambiare sempre il valore del numero.


1
In realtà è il tuo trucco non è male, considerando myimage: lastet e myimage praticamente la stessa cosa, grazie!
domenica

1
Questo trucco sembra più un bug, non so perché dobbiamo specificarlo due volte.
speedplane

2
Se vuoi che una distribuzione di kubernetes avvii un nuovo pod utilizzando la stessa immagine (e questo trucco funziona solo con il tag "latest") devi specificarlo senza tag. La prossima volta aggiungi il tag "latest" e attiverà l'aggiornamento. L'ordine potrebbe essere invertito, non importa. Non usi mai il tag "latest" in produzione, ma a volte per scopi di sviluppo puoi trarne vantaggio.
Camil

2
Funziona solo per gli ultimi. Per impostazione predefinita, almeno nel docker hub, non taggando un'immagine assumerà il tag "latest". Ma funzionerà anche senza. Questo esempio non è qualcosa che vorresti in un ambiente di produzione e non ci sono molti casi d'uso in cui puoi trarne vantaggio anche durante lo sviluppo. Esistono metodi migliori per aggiornare automaticamente un'immagine, utilizzando uno strumento CI / CD.
Camil

11
Ogni volta che modifichi il tag ed esegui il kubectl set imagecomando, kubernetes eseguirà un aggiornamento in sequenza. Ad esempio, supponiamo che tu abbia distribuito "repo / myimage: latest". Nel frattempo la tua immagine è stata modificata e inviata al repo con il tag "v0.2". Puoi eseguire un aggiornamento eseguendo kubectl set image deployment/my-deployment mycontainer=myimage:v0.2Questa immagine avrà anche il tag "latest".
Camil

73

AGGIORNAMENTO 2019-06-24

In base al commento @Jodiug se hai una 1.15versione puoi usare il comando:

kubectl rollout restart deployment/demo

Per saperne di più sulla questione:

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


Ebbene, c'è un'interessante discussione su questo argomento nel progetto Kubernetes GitHub. Consulta il problema: https://github.com/kubernetes/kubernetes/issues/33664

Dalle soluzioni qui descritte, suggerirei una delle due.

Primo

1.Preparare la distribuzione

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.Deploy

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

Secondo (una linea):

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

Ovviamente imagePullPolicy: Alwaysè richiesto in entrambi i casi.


Trovato un altro trucco correlato. Se si esegue semplicemente "kubectl rollout restart deployment" senza specificare alcun nome di distribuzione specifico, la città farà "tutti" questi.
Lennart Rolland

21
kubectl rollout restart deployment myapp

Questo è il modo corrente per attivare un aggiornamento in sequenza e lasciare i vecchi set di repliche in posizione per altre operazioni fornite da kubectl rolloutrollback simili.


@Prathameshdhanawade l'operazione patch non ha alcun undocomando o equivalente.
Martin Peter

7

Uso Gitlab-CI per creare l'immagine e quindi distribuirla direttamente su GCK. Se usi un piccolo trucco per ottenere un aggiornamento continuo senza modificare le impostazioni reali del contenitore, che sta cambiando un'etichetta nell'attuale commit-short-sha.

Il mio comando è simile a questo:

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

Dove puoi usare qualsiasi nome e qualsiasi valore per l'etichetta fintanto che cambia con ogni build.

Divertiti!


6

Sembra che k8s si aspetti che forniamo un tag immagine diverso per ogni distribuzione. La mia strategia di default potrebbe essere quella di rendere il sistema CI generare e spingere le immagini della finestra mobile, li codifica con il numero di build: xpmatteo/foobar:456.

Per lo sviluppo locale può essere conveniente usare uno script o un makefile, come questo:

# 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

Il sedcomando sostituisce un segnaposto nel documento di distribuzione con il tag immagine effettivamente generato.


kubernetes non richiede di aggiornare la distribuzione con un nuovo tag per estrarre la versione più recente di qualsiasi immagine, "latest" è l'esempio più comune.
Dave White,

1

Sto usando Azure DevOps per distribuire le applicazioni containerizzate, riesco facilmente a superare questo problema usando l'ID build

Ogni volta che viene compilato e generato il nuovo ID build, utilizzo questo ID build come tag per l'immagine docker qui è un esempio

nomeimmagine: BUILDID

una volta che l'immagine è stata compilata (CI) con successo, nella pipeline del CD nel file yml di distribuzione ho dato il nome dell'immagine come

nomeimmagine: env: BUILDID

qui evn: buildid è la variabile devops azzurra che ha il valore di build ID.

così ora ogni volta che ho nuove modifiche da compilare (CI) e distribuire (CD).

si prega di commentare se è necessaria la definizione di build per CI / CD.


Il file manifest fa parte del repo. Non capisco quali siano le migliori pratiche per questo. Se creo l'immagine nella pipeline, devo eseguire il push per padroneggiare il manifest aggiornato? o dovrei produrre un manifest aggiornato per gli artefatti (e quindi il manifest nel repository sarebbe solo un modello senza l'effettiva immagine taggata)?
pablete il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.