Kubernetes cómo hacer la implementación para actualizar la imagen

131

Tengo despliegue con un solo pod, con mi imagen de acoplador personalizada como:

containers:
  - name: mycontainer
    image: myimage:latest

Durante el desarrollo, deseo impulsar la nueva versión más reciente y actualizar Deployment. No puedo encontrar cómo hacerlo, sin definir explícitamente la etiqueta / versión e incrementarlo para cada compilación, y hacer

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

Respuestas:

151

Puede configurar su pod con un período de gracia (por ejemplo, 30 segundos o más, dependiendo del tiempo de inicio del contenedor y el tamaño de la imagen) y configurar "imagePullPolicy: "Always". Y uso kubectl delete pod pod_name. Se creará un nuevo contenedor y se descargará automáticamente la última imagen, luego se cancelará el contenedor anterior.

Ejemplo:

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

Actualmente estoy usando Jenkins para compilaciones automatizadas y etiquetado de imágenes y se parece a esto:

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

Otro truco es ejecutar inicialmente:

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

y entonces:

kubectl set image deployment/my-deployment mycontainer=myimage

En realidad, activará la actualización continua, pero asegúrese de que también haya imagePullPolicy: "Always"configurado.

Actualizar:

Otro truco que encontré, donde no tienes que cambiar el nombre de la imagen, es cambiar el valor de un campo que desencadenará una actualización continua, como terminationGracePeriodSeconds. Para ello, puede utilizar kubectl edit deployment your_deploymento kubectl apply -f your_deployment.yamlo el uso de un parche de la siguiente manera:

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

Solo asegúrese de cambiar siempre el valor del número.

Camil
fuente
1
En realidad, su truco no es malo, teniendo en cuenta myimage: lastet y myimage son básicamente lo mismo, ¡gracias!
abovesun
1
Este truco parece más un error, no estoy seguro de por qué necesitamos especificarlo dos veces.
Speedplane
2
Si desea que una implementación de kubernetes inicie un nuevo pod utilizando la misma imagen (y este truco solo funciona con la etiqueta "más reciente"), debe especificarlo sin una etiqueta. La próxima vez agregue la etiqueta "más reciente" y activará la actualización. El orden podría revertirse, no importa. Nunca utiliza la etiqueta "más reciente" en producción, pero a veces para fines de desarrollo puede beneficiarse de ella.
Camil
2
Solo funciona para lo último. De forma predeterminada, al menos en Docker Hub, al no etiquetar una imagen, asumirá la etiqueta "más reciente". Pero también funcionará sin él. Este ejemplo no es algo que desee en un entorno de producción, y no hay muchos casos de uso en los que pueda beneficiarse también en el desarrollo. Existen mejores métodos para actualizar una imagen automáticamente, utilizando una herramienta CI / CD.
Camil
11
Cada vez que cambie la etiqueta y ejecute el kubectl set imagecomando, kubernetes realizará una actualización continua. Por ejemplo, supongamos que implementó "repo / myimage: latest". Mientras tanto, su imagen fue cambiada y empujada al repositorio con la etiqueta "v0.2". Puede realizar una actualización ejecutando kubectl set image deployment/my-deployment mycontainer=myimage:v0.2Esta imagen también tendrá la etiqueta "más reciente".
Camil
73

ACTUALIZACIÓN 2019-06-24

Según el comentario de @Jodiug, si tiene una 1.15versión, puede usar el comando:

kubectl rollout restart deployment/demo

Lea más sobre el tema:

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


Bueno, hay una discusión interesante sobre este tema en el proyecto Kubernetes GitHub. Vea el problema: https://github.com/kubernetes/kubernetes/issues/33664

De las soluciones descritas allí, sugeriría una de dos.

primero

1.Preparar el despliegue

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 desplegar

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

Segundo (un trazador de líneas):

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

Por supuesto, imagePullPolicy: Alwaysse requiere en ambos casos.

Przemek Nowak
fuente
Encontré otro truco relacionado. Si solo realiza el "despliegue de reinicio del despliegue de kubectl" sin especificar ningún nombre de despliegue específico, hará "todos".
Lennart Rolland el
20
kubectl rollout restart deployment myapp

Esta es la forma actual de activar una actualización continua y dejar los viejos conjuntos de réplicas en su lugar para otras operaciones proporcionadas por kubectl rolloutretrocesos similares.

Martin Peter
fuente
@Prathameshdhanawade la operación de parche no tiene undocomando o equivalente.
Martin Peter
7

Uso Gitlab-CI para construir la imagen y luego implementarla directamente en GCK. Si usa un pequeño truco para lograr una actualización continua sin cambiar ninguna configuración real del contenedor, que está cambiando una etiqueta al commit-short-sha actual.

Mi comando se ve así:

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

Donde puede usar cualquier nombre y cualquier valor para la etiqueta siempre que cambie con cada compilación.

¡Que te diviertas!

David Faber
fuente
6

Parece que k8s espera que proporcionemos una etiqueta de imagen diferente para cada implementación. Mi estrategia por defecto sería hacer que el sistema de generación de EC y empujar las imágenes estibador, etiquetado con el número de compilación: xpmatteo/foobar:456.

Para el desarrollo local, puede ser conveniente usar un script o un archivo MAKE, como este:

# 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

El sedcomando reemplaza un marcador de posición en el documento de implementación con la etiqueta de imagen generada real.

xpmatteo
fuente
kubernetes no requiere que actualice la implementación con una nueva etiqueta para obtener la versión más reciente de cualquier imagen, siendo la "más reciente" el ejemplo más común.
Dave White
1

Estoy usando Azure DevOps para implementar las aplicaciones de contenedor, me las arreglo para superar este problema fácilmente usando el ID de compilación

Cada vez que compila y genera la nueva ID de compilación, utilizo esta ID de compilación como etiqueta para la imagen de acoplador. Aquí hay un ejemplo.

nombre de imagen: buildID

una vez que su imagen se compila (CI) con éxito, en la canalización de CD en el archivo yml de implementación, le doy el nombre de la imagen como

nombre de imagen: env: buildID

aquí evn: buildid es la variable de desarrollo azul que tiene el valor de ID de compilación.

así que ahora cada vez que tengo nuevos cambios para compilar (CI) e implementar (CD).

comente si necesita una definición de compilación para CI / CD.

Noman Sadiq
fuente
El manifiesto es parte del repositorio. No entiendo cuáles son las mejores prácticas para esto. Si construyo la imagen en la tubería, ¿debo presionar para dominar el manifiesto actualizado? ¿O debería producir un manifiesto actualizado para los artefactos (y, por lo tanto, el manifiesto en el repositorio sería solo una plantilla sin la imagen etiquetada real)?
Pablete