Para los que no quieren leer todo (aunque lo recomiendo) podríamos dividir el post en 3 grandes títulos que voy a marcarlos en mayúscula, azul y subrayado así TITULO
Los títulos son:
CREAR NAMESPACE
CREAR DEPLOYMENT
ROLLBACK DE UN DEPLOYMENT
Antes de avanzar con el post de rollback de un deployment en si vamos a ver que tengo corriendo actualmente en mi cluster de Kubernetes:
Para ver un listado de lo que tenemos corriendo en el cluster:
kubectl get all
Fijense que diferencia los PODs, de los servicios, de los deployments y las replicas.
Ver detalle de todos los PODs en el namespaces actual:
kubectl get pods -o wide
Ver detalle de todos los PODs en todos los namespaces:
kubectl get pods --all-namespaces
En este caso vemos los mismos ya que tengo solo un namespace (los otros que aparecen son del sistema).
Ver cantidad de replicas:
kubectl get rs
Ver historial de cambios de un deployment:
kubectl rollout history deployment/nombredeldeploy
CREAR NAMESPACE
Bueno, como yo no quiero eliminar nada de esto para hacer el ejercicio lo que voy a hacer es crear un nuevo namespace donde voy a correr todo el despliegue que viene a continuación.
Primero vemos que namespaces tenemos:
kubectl get namespaces
Kubernetes arranca con tres espacios de nombres inicialmente:
default El espacio de nombres por defecto para aquellos objetos que no especifican ningún espacio de nombres
kube-system El espacio de nombres para aquellos objetos creados por el sistema de Kubernetes
kube-public Este espacio de nombres se crea de forma automática y es legible por todos los usuarios (incluyendo aquellos no autenticados). Este espacio de nombres se reserva principalmente para uso interno del clúster, en caso de que algunos recursos necesiten ser visibles y legibles de forma pública para todo el clúster. La naturaleza pública de este espacio de nombres es simplemente por convención, no es un requisito.
Para crear un nuevo espacio de nombres ejecutamos:
kubectl create namespace nombredelnamespace
En mi caso lo llamé mirollback
Verificamos que se haya creado:
kubectl get namespaces
Vemos creado mirollback |
kubectl config set-context --current --namespace=mirollback
Verificamos:
kubectl config view | grep mirollback
IMPORTANTE: No todos los objetos están en un espacio de nombres.
La mayoría de los recursos de Kubernetes (pods, services, replication controllers y otros) están en algunos espacios de nombres.
Para comprobar qué recursos de Kubernetes están y no están en un espacio de nombres ejecutamos:
Recursos que SI estan en un espacio de nombres:
kubectl api-resources --namespaced=true
Recursos que NO estan en un espacio de nombres:
kubectl api-resources --namespaced=false
Vemos por ejemplo que los PODs si están, pero los NODOS no.
Para mas info podes entrar aca.
Verificamos si tenemos nodos y pods en nuestro nuevo namespace default (llamado rollback):
Vemos que no hay ningún POD. Pero si miramos el namespace default (que ya no es mas el default, es solo el nombre, el default ahora es mirollback).
kubectl -n default get pods (con -n default le decimos que chequee ese namespace)
Vemos que en el default siguen corriendo los PODs que tenia al principio.
CREAR DEPLOYMENT
Ya creado nuestro nuevo namespace y puesto por default procedemos con la creación de un deployment.
Creamos un deployment con 3 PODs con nginx 1.14.2:
nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment #Nombre del despliegue
labels:
app: nginx
spec:
replicas: 3 #Cantidad de replicas
selector:
matchLabels:
app: nginx #Etiqueta con la que se encuentra al POD
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2 #Version de la imagen de Docker Hub de nginx que ejecuta
ports:
- containerPort: 80
Crear despliegue:
kubectl apply -f nginx-deployment.yaml
Ver despliegues creados:
kubectl get deployments
El nuestro es el que dice nginx-deployment, que es el nombre del despliegue que definimos en el archivo yaml.
La columna READY nos muestra cuantas replicas están disponibles (listas/deseadas).
UP-TO-DATE nos muestra el número de réplicas que se han actualizado para lograr el estado deseado.
AVAILABLE nos muestra cuántas réplicas de la aplicación están disponibles.
AGE nos muestra la cantidad de tiempo que hace que se ejecuta la aplicación.
Para ver el estado de implementación del despliegue, ejecutar:
kubectl rollout status deployment.v1.apps/nginx-deployment
En este caso vemos que dice que "successfully rolled out".
Para ver la cantidad de replicas de cada POD (ReplicaSet):
kubectl get rs
NAME enumera los nombres de los ReplicaSets en el espacio de nombres (namespace mirollback).
DESIRED nos muestra el número deseado de réplicas de la aplicación, que definimos cuando creamos la implementación.
CURRENT nos muestra cuántas réplicas se están ejecutando actualmente.
READY nos muestra cuántas réplicas están disponibles para los usuarios.
AGE nos muestra la cantidad de tiempo que la aplicación lleva ejecutándose.
El nombre del ReplicaSet siempre tiene el formato [DEPLOYMENT-NAME]-[RANDOM-STRING]. La cadena se genera aleatoriamente. En nuestro caso:
nginx-deployment-6b474476c4
Para ver las etiquetas generadas para cada Pod, ejecutamos:
kubectl get pods --show-labels
La etiqueta es:
app=nginx,pod-template-hash=6b474476c4
Debe especificarse un selector apropiado y etiquetas de template Pod en una implementación (en este caso, app:nginx). No superpongan etiquetas o selectores con otros controladores, Kubernetes no lo evita, y si varios controladores tienen selectores superpuestos, pueden entrar en conflicto y comportarse inesperadamente.
Etiqueta pod-template-hash:
Ésta etiqueta no se debe cambiar. El pod-template-hash agrega la etiqueta a cada ReplicaSet de una implementacion. Esta etiqueta garantiza que los ReplicaSets secundarios de una implementación no se superpongan. Se genera mediante el hash PodTemplate del ReplicaSet.
Ahora vamos a actualizar nuestra implementación:
Vamos a hacer que los PODs usen la imagen nginx 1.16.1 en lugar de la 1.14.2:
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record
o use el siguiente comando:
kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
Vemos que aparece actualizado.
Para ver el estado de implementación ejecutamos:
kubectl rollout status deployment.v1.apps/nginx-deployment
Vemos que se aplico correctamente:
deployment "nginx-deployment" successfully rolled out
Ejecutamos kubectl get rs para ver que la implementación actualizó los Pods creando un nuevo ReplicaSet y escalandolos a 3 réplicas, y reduciendo el antiguo ReplicaSet 0 réplicas.
kubectl get rs
Vemos que las 3 replicas anteriores estan en cero y las nuevas en 3.
Ahora verificamos los nuevos PODs con la nueva version:
kubectl get pods
Durante el deployment solo una cierta cantidad de Pods están inactivos mientras se actualizan. De forma predeterminada, al menos el 75% del número deseado de Pods esta activo (25% máximo no disponible).
También se puede crear un cierto número de Pods por encima del número deseado. De forma predeterminada, garantiza que como máximo el 125% del número deseado de Pods esté activo (aumento máximo del 25%).
En nuestro ejemplo, Kubernetes no mata los PODs antiguos hasta que haya surgido un número suficiente de PODs nuevos, y no crea nuevos hasta que se haya matado una cantidad suficiente de PODs viejos. Se asegura que al menos 2 PODs estén disponibles, y que como máximo haya 4.
Para ver los detalles del despliegue:
kubectl describe deployments
Aquí puede ver que cuando creó el despliegue, creó un ReplicaSet (nginx-deployment-6b474476c4) y lo amplió a 3 réplicas directamente. Cuando actualizó la implementación, creó un nuevo ReplicaSet (nginx-deployment-7b45d69949) y lo amplió a 1 y luego redujo el antiguo ReplicaSet a 2, de modo que al menos 2 Pods estaban disponibles y como máximo 4. Luego continuó ampliando y reduciendo el ReplicaSet nuevo y el antiguo, con la misma estrategia de actualización continua. Finalmente, quedaron 3 réplicas disponibles en el nuevo ReplicaSet, y el antiguo ReplicaSet quedo en cero.
Rollover (actualizaciones al vuelo), ¿que es?
Si actualizamos un despliegue mientras otro está en progreso, el despliegue nuevo crea un nuevo ReplicaSet según la actualización y comienza a escalar eso, y reinicia el ReplicaSet que estaba escalando anteriormente; lo agrega a su lista de antiguos ReplicaSets y comienza a reducirlo.
Por ejemplo, supongamos que crea una nueva implementación para crear 5 réplicas de nginx:1.14.2, pero luego mientras se implementan la actualiza para crear 5 réplicas nginx:1.16.1. Solo se habian creado 3 replicas de nginx:1.14.2. En ese caso, el despliegue comienza inmediatamente a matar los 3 PODs nginx:1.14.2, y comienza a crear los de la version nginx:1.16.1.
Es decir, no espera a que se creen las 5 replicas con nginx:1.14.2 sino que sobre la marcha mata los viejos que creó y va creando los nuevos con la nueva versión.
ROLLBACK DE UN DEPLOYMENT:
El rollout se activa si y solo si se modifica el template del Pod de implementación (.spec.template), por ejemplo, si actualiza las etiquetas o las imágenes del contenedor de la plantilla. Otras actualizaciones, como el escalado de la implementación, no crean una revisión de implementación. Esto significa que cuando retrocede a una revisión anterior, solo se revierte la parte del template del Pod de implementación.
Supongamos cometimos un error tipográfico al actualizar la implementación, pusimos el nombre de la imagen como en nginx:1.161 en lugar de nginx:1.16.1:
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.161 --record=true
Nos va a aparecer que se actualizó el despliegue, aunque luego se va a colgar.
Para verificar el estado de la implementación ejecutamos:
kubectl rollout status deployment.v1.apps/nginx-deployment
Podemos ver que el estado queda detenido en:
Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Presionamos Ctrl-C para detener.
Ahora vemos que el número de réplicas antiguas (nginx-deployment-7b45d69949 y nginx-deployment-6b474476c4) es 2 y el de réplicas nuevas (nginx-deployment-777654c9c) es 1.
kubectl get rs
Ahora vamos a ver los Pods que tenemos funcionando, veremos que uno de esos Pods (el creado por el nuevo ReplicaSet) está colgado (ImagePullBackOff).
kubectl get pods
El controlador de implementación detiene el despliegue incorrecto automáticamente y deja de escalar el nuevo ReplicaSet. Esto depende de los parámetros que haya especificado, Kubernetes por defecto establece el valor en 25%.
Vamos a ver el detalle de la implementación:
kubectl describe deployment
Fijense las ultimas 2 lineas:
Normal ScalingReplicaSet 57m deployment-controller Scaled down replica set nginx-deployment-6b474476c4 to 0
Normal ScalingReplicaSet 22m deployment-controller Scaled up replica set nginx-deployment-777654c9c to 1
Ahi se ve con claridad cuando baja una de las replicas viejas para levantar la nueva con la versión que no existe y que finalmente quedó colgada.
Primero verificamos el historial de la implementación:
kubectl rollout history deployment.v1.apps/nginx-deployment
Aquí vemos los 2 cambios que hicimos:
En la revisión 2 cambiamos la version de nginx a nginx=nginx:1.16.1
Y en la revisión 3 la cambiamos a nginx=nginx:1.161
Si hubiese muchas revisiones que ver podriamos ver directamente la que deseamos con este comando:
kubectl rollout history deployment.v1.apps/nginx-deployment --revision=2
Aca se puede ver el detalle de la revisión 2 y la revisión 3 |
En nuestro caso vamos a hacer el rollback a la version anterior que era la que se encontraba funcionando.
Para revertir la versión actual y hacer el rollback a la versión anterior ejecutamos:
kubectl rollout undo deployment.v1.apps/nginx-deployment
Si quisiéramos ir a una versión especifica podríamos ejecutar:
kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
Chequeamos el detalle de la implementación:
kubectl describe deployment nginx-deployment
Vemos corriendo la imagen de nginx 1.16.1 |
kubectl scale deployment.v1.apps/nginx-deployment --replicas=10
Antes y despues del escalado |
Primero con 3 replicas listas y luego con las 10 |
kubectl autoscale deployment.v1.apps/nginx-deployment --min=10 --max=15 --cpu-percent=80
Para pausar implementacion:
kubectl rollout pause deployment.v1.apps/nginx-deployment
Para actualizar la imagen de la implementación:
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.17.0
Ver historial del despliegue:
kubectl rollout history deployment.v1.apps/nginx-deployment
La nueva implementacion no tendrá ningún efecto mientras esté en pausa.
Para reanudar la implementación:
kubectl rollout resume deployment.v1.apps/nginx-deployment
Despliegue completo, ¿que es?
Kubernetes marca una implementación como completa cuando tiene las siguientes características:
Todas las réplicas asociadas con la implementación se han actualizado a la última versión que ha especificado, lo que significa que se han completado las actualizaciones que ha solicitado.
Todas las réplicas asociadas con la implementación están disponibles.
No se están ejecutando réplicas antiguas para la implementación.
Por último, para verificar si se ha completado una implementación ejecutamos:
kubectl rollout status deployment.v1.apps/nginx-deployment
Nos indica que se implementó con éxito.
Para mas info y detalle podes ingresar acá.
Como accedo al servicio del POD
Una cosita mas, si quisieramos acceder al nginx para ver que carajo esta mostrando ¬¬ seguimos estos pasos:
Primero, vemos la IP de nuestro Minikube para luego usar en la URL del servicio:
minikube ip
kubectl get services
Ahora exponemos el puerto de nuestro nginx:
kubectl expose deployment nginx-deployment --type=NodePort --port=80
Verificamos los servicios de nuevo:
kubectl get services
Y ahora si, vamos a ver el de nginx-deployment corriendo con un puerto externo asociado al 80, en mi caso el 32737.
Entonces para acceder pongo la IP del Minikube y ese puerto y puedo acceder con curl así:
curl http://192.168.99.100:32737
Aca dejo una imagen con todos los pasos:
Por interfaz grafica lo vemos asi:
Antes de terminar una mas, quiero convertirlos en una fuente inagotable de conocimiento (?).
Se acuerdan que al principio del post creamos un nuevo namespace para separar lo que íbamos a hacer de lo que ya estaba hecho, ¿no? (Si no se acuerdan vuelvan al principio ¬¬)
Ver PODs de los diferentes namespace
Bueno, acá lo podemos ver con mas claridad, para ver los PODs del namespace default:
kubectl get pods -n default
Vemos los PODs de nombre hello, hello-http, mi-app y nginx-deployment.
Luego no le especificamos el namespace y nos muestra el predeterminado (que ahora es mirollback porque lo habíamos configurado al principio):
kubectl get pods
Vemos que tenemos 10 PODs con el nombre nginx-deployment pero que a diferencia de los otros que llevan 2 días, estos llevan apenas 129 minutos.
Para verlo con total claridad vamos a mostrar todos los PODs de todos los namespace:
kubectl get pods -A
Ahora si, no me pidas mas ¬¬
Ahora te pido yo:
COMPARTI, ¿que te cuesta? Son 2 clicks, no lo puedo entender.
Arrobame, que te quiero agradecer, como le agradecí a Ramón.
Y si no te agradezco no te aflijas, porque a cambio, te enseño a convertirte en el mejor técnico de la historia, en 100 días, y sin perder la memoria (?).
Mas no puedo hacer. Te estoy dando el negocio de tu vida en un posteo.
Chau, cuidate (?).
No hay comentarios:
Publicar un comentario