Usaremos Gitlab CI y GitOps manual para implementar y utilizar el despliegue Canary en Kubernetes

Artículos de este ciclo:
- (este artículo)
- Despliegue Canary mediante Istio
- Despliegue Canary mediante Jenkins-X Istio Flagger
Realizaremos el despliegue Canary manualmente a través de GitOps y la creación/modificación de recursos básicos de Kubernetes. Este artículo está destinado principalmente a familiarizarse con el funcionamiento del despliegue Canary en Kubernetes, ya que hay maneras más efectivas de automatización que examinaremos en los siguientes artículos.

Despliegue Canary
Con la estrategia Canary de actualización, primero se aplica solo para una parte de los usuarios. A través de monitoreo, datos de registros, pruebas manuales u otros canales de retroalimentación, se prueba el lanzamiento antes de aplicarlo a todos los usuarios.
Despliegue de Kubernetes (actualización progresiva)
La estrategia predeterminada para el despliegue de Kubernetes es la actualización progresiva, donde se ejecuta una cantidad determinada de pods con nuevas versiones de imágenes. Si se crean sin problemas, los pods con versiones antiguas de las imágenes se eliminan y se crean nuevos pods en paralelo.
GitOps
Utilizamos GitOps en este ejemplo, ya que:
- usamos Git como única fuente de verdad
- utilizamos operaciones de Git para construir y desplegar (no se necesitan comandos, excepto git tag/merge)
Ejemplo
Tomemos una buena práctica: tener un repositorio para el código de las aplicaciones y otro para la infraestructura.
Repositorio para aplicaciones
Es una API muy simple en Python+Flask que devuelve una respuesta en formato JSON. Construiremos el paquete a través de GitlabCI y subiremos el resultado al Registro de Gitlab. En el registro tenemos dos versiones diferentes de lanzamientos:
wuestkamp/k8s-deployment-example-app:v1wuestkamp/k8s-deployment-example-app:v2
La única diferencia entre ellas es el cambio en el archivo JSON devuelto. Usamos esta aplicación para visualizar de manera simple con qué versión estamos interactuando.
Repositorio de infraestructura
En este repositorio desplegaremos a través de GitlabCI en Kubernetes, .gitlab-ci.yml se ve de la siguiente manera:
image: traherom/kustomize-docker
before_script:
- printenv
- kubectl version
stages:
- deploy
deploy test:
stage: deploy
before_script:
- echo $KUBECONFIG
script:
- kubectl get all
- kubectl apply -f i/k8s
only:
- master
Para ejecutarlo por su cuenta necesitará un clúster, puede usar Gcloud:
gcloud container clusters create canary --num-nodes 3 --zone europe-west3-b
gcloud compute firewall-rules create incoming-80 --allow tcp:80Necesita hacer un fork y crear una variable KUBECONFIG en GitlabCI, que contendrá la configuración para acceder kubectl a su clúster.
Sobre cómo obtener las credenciales para el clúster (Gcloud) puede leer .
Yaml de infraestructura
En el repositorio de infraestructura tenemos un service:
apiVersion: v1
kind: Service
metadata:
labels:
id: app
name: app
spec:
ports:
- port: 80
protocol: TCP
targetPort: 5000
selector:
id: app
type: LoadBalancerY el deployment en deploy.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 10
selector:
matchLabels:
id: app
type: main
template:
metadata:
labels:
id: app
type: main
spec:
containers:
- image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v1
name: app
resources:
limits:
cpu: 100m
memory: 100MiY otro deployment en deploy-canary.yaml:
kind: Deployment
metadata:
name: app-canary
spec:
replicas: 0
selector:
matchLabels:
id: app
type: canary
template:
metadata:
labels:
id: app
type: canary
spec:
containers:
- image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v2
name: app
resources:
limits:
cpu: 100m
memory: 100MiTenga en cuenta que app-deploy aún no tiene réplicas definidas.
Ejecución del despliegue inicial
Para iniciar el despliegue inicial, puede ejecutar el pipeline de GitlabCI manualmente en la rama maestra. Después de esto, kubectl debería mostrar lo siguiente:

Vemos app un deployment con 10 réplicas y app-canary con 0. También hay un LoadBalancer desde el cual podemos acceder a través de curl por IP externa:
while true; do curl -s 35.198.149.232 | grep label; sleep 0.1; done

Vemos que nuestra aplicación de prueba devuelve solo “v1”.
Ejecución del despliegue Canary
Paso 1: lanzar una nueva versión para parte de los usuarios
Hemos establecido el número de réplicas en 1 en el archivo deploy-canary.yaml y la imagen de nueva versión:
kind: Deployment
metadata:
name: app-canary
spec:
replicas: 1
selector:
matchLabels:
id: app
type: canary
template:
metadata:
labels:
id: app
type: canary
spec:
containers:
- image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v2
name: app
resources:
limits:
cpu: 100m
memory: 100MiEn el archivo deploy.yaml hemos cambiado el número de réplicas a 9:
kind: Deployment
metadata:
name: app
spec:
replicas: 9
selector:
matchLabels:
id: app
...Estamos subiendo estos cambios al repositorio desde el cual se iniciará el despliegue (a través de GitlabCI) y vemos al final:

Nuestro Service apuntará a ambos deployments, ya que ambos tienen el selector app. Debido a la distribución aleatoria por defecto en Kubernetes, deberíamos ver diferentes respuestas en aproximadamente el 10% de las solicitudes:

El estado actual de nuestra aplicación (GitOps, tomado de Git como fuente única de verdad) es tener dos deployments con réplicas activas, uno para cada versión.
~10% de los usuarios se familiarizan con una nueva versión y la prueban inadvertidamente. Ahora es el momento de revisar los registros y los datos de monitoreo para detectar problemas.
Paso 2: lanzar una nueva versión para todos los usuarios
Decidimos que todo ha ido bien y ahora necesitamos desplegar la nueva versión para todos los usuarios. Para ello, simplemente actualizamos deploy.yaml instalando la nueva versión de la imagen y estableciendo el número de réplicas en 10. En deploy-canary.yaml estamos configurando el número de réplicas de nuevo en 0. Después del despliegue, el resultado será el siguiente:

Resumiendo
Para mí, realizar un despliegue manual de esta manera ayuda a entender lo fácil que se puede configurar con k8s. Dado que Kubernetes permite actualizar todo a través de API, estos pasos se pueden automatizar mediante scripts.
Otra cosa a implementar es un punto de entrada para el tester (LoadBalancer o a través de Ingress), a través del cual se puede acceder únicamente a la nueva versión. Esto puede ser utilizado para visualizarlo manualmente.
En los próximos artículos, revisaremos otras soluciones automatizadas que implementan la mayoría de lo que hemos hecho.
También lee otros artículos en nuestro blog:
Fuente: habr.com
