Objetivos

Al finalizar el tutorial el estudiante estará en capacidad de:

Pasos previos

En particular se utilizarán los siguientes recursos:

  1. gcloud SDK para acceder a los servicios del proveedor Google Cloud Platform a partir de la consola. En caso de no tenerla instalada puede consultar el siguiente manual de instalación:https://cloud.google.com/sdk/docs/install
  2. Herramienta de control de Kubernetes, kubectl. En caso de no tenerla instalada puede consultar el siguiente manual de instalación:https://kubernetes.io/docs/tasks/tools/
  3. Haber habilitado el API de Kubernetes Engine y creado un Cluster en GCP, en caso de no haberlo hecho anteriormente puede consultar el tutorial Hello Kubernetes

ArgoCD es una herramienta de despliegue continuo basada en GitOps para aplicaciones de Kubernetes que permite a los equipos automatizar el despliegue y la gestión de sus aplicaciones utilizando Git como una única fuente de verdad. ArgoCD vigila los cambios en los repositorios de Git y sincroniza automáticamente esos cambios con el estado deseado en el clúster de Kubernetes objetivo, asegurándose de que la aplicación e infraestructura siempre estén actualizadas con la última versión.

Los principales beneficios de usar ArgoCD son:

  1. Automatización: Automatiza el proceso de despliegue, reduciendo el riesgo de errores manuales y asegurando que la aplicación se despliegue de manera consistente y confiable.
  2. Visibilidad: Proporciona una UI web en la cual se tiene visibilidad en tiempo real del estado de la aplicación e infraestructura, incluido el estado de los deployments y cualquier error que pueda surgir
  3. Seguridad: Proporciona un mecanismo seguro para la gestión de cambios de aplicaciones e infraestructura, con controles estrictos sobre quién puede realizar cambios y cuándo se pueden desplegar esos cambios
  4. Flexibilidad: Proporciona mecanismos para realizar acciones que previamente con Kubernetes nativo no eran posibles tal como despliegues canarios con rollback automatico, blue/green deployments, A/B testing desplegando versiones especiales a cierto tipo de usuarios y que tienen un tiempo de vencimiento, entre otras características.

Para mas información acceder a la documentación oficial https://argo-cd.readthedocs.io/en/stable/

Para este tutorial usaremos el cluster creado en tutoriales pasados, haremos un fork del repositorio argocd-tutorial que es posible consultar en el siguiente enlace y lo clonaremos, es importante que se asegure que este fork sea público ya que es necesario para las herramientas que usaremos.

El repositorio consta de los siguientes archivos de configuración de Kubernetes:

  1. deployment.yml: Deployment utilizado para configurar la contenedora que ejecutará la imagen de docker proporcionada.
  2. svc.yml: Service utilizado para disponibilizar a la red el servidor que es ejecutado en el docker.

Trabajaremos sobre la rama main de su fork y usaremos una serie de imágenes de docker almacenadas en Github packages en el siguiente enlace.

La imagen consta de un servidor de flask que proporciona el endpoint GET https://localhost:8080/version cuya respuesta es un JSON conteniendo la versión de la imagen de docker que se está ejecutando. Por ejemplo, para la versión de la imagen ghcr.io/misw-4301-desarrollo-apps-en-la-nube/argocd-tutorial:1.0 la respuesta es la siguiente

{"version":1.0}

Para los siguientes pasos se recomienda trabajar con un ambiente sin contenedoras en ejecución. Para ello puede destruir los despliegues y los servicios haciendo uso del comando delete:

kubectl delete all --all -n default

Recordemos que anteriormente clonamos el fork que hicimos y que contiene una carpeta k8s con archivos para la configuración de los recursos de Kubernetes. Ahora aplicaremos estos archivos sobre el cluster con los siguientes comandos.

user@192 ~ % kubectl apply -f deployment.yml
user@192 ~ % kubectl apply -f svc.yml

Para verificar el estado de un despliegue emplee las instrucciones kubectl get pods, kubectl get services y kubectl get deployments.

  1. kubectl get pods:
user@192 ~ % kubectl get pods
W1112 16:21:42.982225    9346 gcp.go:120] WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead.
To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke
NAME                                   READY   STATUS    RESTARTS   AGE
tutorial-server-7749f598b6-d2s75   1/1     Running   0          24s
  1. kubectl get services
user@192 ~ % kubectl get services
W1112 16:22:40.238125    9366 gcp.go:120] WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead.
To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke
NAME                       TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE
kubernetes        ClusterIP      192.168.72.1    <none>          443/TCP        20h
tutorial-server   LoadBalancer   192.168.76.14   35.202.234.71   80:32263/TCP   4m35s
  1. kubectl get deployments.
user@192 ~ % kubectl get deployments
W1112 16:23:57.990528    9399 gcp.go:120] WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead.
To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
tutorial-server   1/1     1            1           56s

Note que al ejecutar el comando kubectl get services, se obtuvo una IP externa, esta corresponde al balanceador de carga que es el punto de entrada a los pods contenidos dentro del cluster. En el caso del ejemplo corresponde a 35.202.234.71, corriendo en el puerto 80. Para probar que el despliegue está funcionando, identifique su IP externa y reemplazarla en el siguiente curl:

user@192 ~ % curl --location --request GET 'http://<IP-BALANCEADOR>:<PUERTO>/version' --header 'Content-Type: application/json'

Para el caso del ejemplo corresponde a:

user@192 ~ % curl --location --request GET 'http://35.202.234.71:80/version' --header 'Content-Type: application/json'

Obteniendo el resultado:

{"version":1.0}

En el contenido de esta semana describimos las diferentes formas que hay para desplegar cambios a un cluster de Kubernetes, en este caso haremos un primer acercamiento manual, para ello cambiaremos la imagen de docker para que ya no sea la versión 1.0 si no la versión 2.0

El primer cambio que debemos hacer es en nuestro archivo deployment.yml modificando el valor de la llave image por ghcr.io/misw-4301-desarrollo-apps-en-la-nube/argocd-tutorial:2.0

Luego de esto desplegamos los cambios al cluster ejecutando el comando apply para el archivo que cambió.

user@192 ~ % kubectl apply -f deployment.yml

Ahora si ejecutamos el comando kubectl get pods y veremos que se inició un nuevo pod y el anterior ha sido removido, si esperamos a que finalice este proceso y ejecutamos el curl recibiremos ahora la versión 2.0.

{"version":2.0}

Finalmente haga git add, git commit y git push a su repositorio remoto para que esté actualizado con la última versión desplegada.

user@192 ~ % git add .
user@192 ~ % git commit -m "[Deployment] Version 2.0"
user@192 ~ % git origin main

Este proceso fue fácil y rápido sin embargo considere como sería este proceso si varios archivos cambiaran y tuviéramos que hacer apply de cada uno por separado, se volvería un proceso bastante tedioso y propenso a errores sin considerar el caso en el que hubiera más desarrolladores trabajando en el mismo proyecto.

Para particionar recursos dentro de un cluster de forma separada y aislada Kubernetes ofrece el concepto de namespaces. Cada namespace tiene su propio conjunto de recursos tales como pods, services, deployments, secrets entre otros que están aislados de los recursos de otros namespaces, lo anterior, permite que varios equipos o proyectos mantengan un nivel de separación alto. Por defecto cuando se crea un cluster de Kubernetes y creamos recursos estos son almacenados en un namespace por defecto llamado default. Cada vez que ejecutamos un comando como kubectl get pods, kubectl get deployments, kubectl get services entre otros, estamos solicitando los recursos del namespace default.

Para listar los namespaces disponibles podemos ejecutar el comando.

user@192 ~ % kubectl get namespaces

Así mismo si queremos obtener los recursos de un namespace podemos hacerlo agregando al comando el nombre de este namespace como se ve a continuación.

user@192 ~ % kubectl get <RECURSO> -n <NOMBRE_NAMESPACE>

Por ejemplo para obtener los pods de un namespace llamado tutoriales lo haríamos de la siguiente forma.

user@192 ~ % kubectl get pods -n tutoriales

Y para aplicar un recurso de Kubernetes lo haríamos de la siguiente forma

user@192 ~ % kubectl apply -f svc.yml -n tutoriales

Finalmente para crear un nuevo namespace usaremos el comando

user@192 ~ % kubectl create namespace <NOMBRE_NUEVO_NAMESPACE>

Con el propósito de automatizar el proceso de despliegue y seguir las prácticas de entrega continua que propone GitOps usaremos ArgoCD como herramienta principal de despliegue a Kubernetes.

Lo primero que haremos será crear un nuevo namespace donde estarán los recursos de ArgoCD y así no mezclar estos recursos con los nuestros.

user@192 ~ % kubectl create namespace argocd

Seguido a esto aplicaremos el archivo yml que contiene la configuración de ArgoCD y que se encuentra publicado en github de forma pública. El siguiente comando creará en el namespace de argocd todos los recursos necesarios para que se pueda ejecutar correctamente.

user@192 ~ % kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

A continuación si listamos los pods del namespace argocd podremos ver que se están creando sus pods al igual que todos sus demás recursos.

user@192 ~ % kubectl get pods -n argocd
W0203 15:30:19.229410   56516 gcp.go:119] WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.26+; use gcloud instead.
To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke
NAME                                                READY   STATUS    RESTARTS      AGE
argocd-application-controller-0                     1/1     Running   0             18h
argocd-applicationset-controller-6cfdfc75cf-rs47d   1/1     Running   0             18h
argocd-dex-server-6785dd9444-54f78                  1/1     Running   2 (18h ago)   18h
argocd-notifications-controller-7c9c954b78-r4gmd    1/1     Running   1 (18h ago)   18h
argocd-redis-7f997b4c4b-mqwg7                       1/1     Running   0             18h
argocd-repo-server-6bb8bf4f4b-nq565                 1/1     Running   0             18h
argocd-server-6d447dccf5-fjf4v                      1/1     Running   0             18h

Cuando todos los pods se encuentren en estado Running sabremos que habremos finalizado con su configuración inicial de forma correcta.

Accediendo a ArgoCD

ArgoCD por defecto viene con una interfaz interactiva que nos ayuda con las diferentes tareas que debemos realizar para la configuración de un proyecto al igual que para la visualización de todos los recursos de Kubernetes desplegados en este. Esta interfaz no está expuesta a la red de forma pública por defecto por lo cual tendremos que hacer port-forwarding para poder acceder a ella con el siguiente comando

user@192 ~ % kubectl port-forward svc/argocd-server -n argocd 8080:443

Este comando habilitará en nuestro localhost:8080 la interfaz de ArgoCD.

Como podemos ver nos solicita un usuario y contraseña, el usuario por defecto es admin y para obtener la contraseña debemos ejecutar el comando.

user@192 ~ % kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo

Una vez ingresados los datos de acceso podremos visualizar la pantalla principal.

Conectando nuestro repositorio

El siguiente paso que haremos será ir a la parte de settings, repositories y luego seleccionaremos la opción Connect Repo, con esta opción vamos a registrar el repositorio en donde tenemos los archivos de configuración de Kubernetes y el cual ArgoCD va a estar monitoreando con el propósito de detectar cambios. Para nuestro caso el repositorio que usaremos será el fork que realizamos al inicio del tutorial.

En esta ocasión usaremos HTTPS como medio de conexión y completamos los campos Type, Project y Repository URL, en este último campo ingresamos el URL HTTPS que usamos para clonar nuestro repositorio. Como nuestro repositorio es público no es necesario proporcionar más información o credenciales. Finalmente seleccionaremos el botón de Connect.

Con el repositorio creado deberíamos ver que se hizo la conexión satisfactoriamente.

El último paso que debemos realizar es crear una aplicación de ArgoCD que se sincronice con el repositorio que acabamos de crear, para eso iremos a la sección de aplicaciones y seleccionaremos la opción New App.

Para la primera sección, le daremos un nombre a nuestra aplicación, seleccionaremos el nombre del proyecto al que pertenece y seleccionaremos como sync policy Automatic, esto significa que ArgoCD al detectar cambios no esperará aprobación si no que actualizará de forma automática los recursos. Por último, seleccionamos la opción Prune Resources, lo cual le indica a ArgoCD que si se elimina algún archivo yml se debe eliminar también el recurso que estaba declarado en el.

En la sección source escogeremos el repositorio que agregamos previamente y en path ingresamos k8s que es la ruta en la cual se encuentran nuestros archivos de Kubernetes. Finalmente en destination seleccionaremos el cluster en el cual queremos aplicar los cambios, en este caso será el primero que nos aparece indicando que hacemos referencia al mismo cluster en el cual ArgoCD está ejecutándose.

Una vez realizada la configuración anterior seleccionaremos el botón de create con lo cual ArgoCD iniciará su primera sincronización con el repositorio. Cuando este proceso haya finalizado veremos una tarjeta nueva con el nombre de nuestra aplicación que debe estar en estado Healthy y Synced indicando que el proceso ya fue finalizado correctamente.

Desplegando nuevos cambios

Para probar que la sincronización automatica funciona correctamente modificaremos el deployment.yml de nuestro repositorio con la imagen https://ghcr.io/misw-4301-desarrollo-apps-en-la-nube/argocd-tutorial:3.0, para hacer aún mas evidente la sincronización cambiaremos tambien el numero de replicas a 2 lo cual deberia causar que se creen 2 pods, finalmente haremos push de los cambios.

ArgoCD cada 3 minutos se actualizará automáticamente para detectar cambios, en caso de no querer esperar a que pase este tiempo podemos seleccionar el botón Sync Apps obligando que lo haga inmediatamente.

De igual forma, en caso de no querer esperar los 3 minutos y no querer utilizar el botón de Sync Apps, es posible configurar un Webhook del lado de Github para que le avise a ArgoCD cada vez que hay un push en un repositorio haciendo trigger de la sincronización, esta última forma se sale del scope del tutorial sin embargo para profundizar más en el tema puede ingresar al siguiente enlace.

Cuando inicie el proceso de sincronización veremos que el estado pasará a ser Progressing y una vez finalizado podemos verificar que se hizo correctamente la actualización haciendo curl al servicio version y verificando que esté la versión 3 en ejecución.

user@192 ~ % curl --location --request GET 'http://35.202.234.71:80/version' --header 'Content-Type: application/json'
{"version":3.0}

De igual forma si hacemos kubectl get pods deberíamos ver 2 pods.

user@192 ~ % kubectl get pods
W0203 23:59:45.808850    6575 gcp.go:119] WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.26+; use gcloud instead.
To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke
NAME                               READY   STATUS    RESTARTS   AGE
tutorial-server-67f9696488-2wd95   1/1     Running   0          2m12s
tutorial-server-67f9696488-4pfgx   1/1     Running   0          118s

Pruebe hacer diferentes cambios y ver cómo se aplican los cambios en el cluster.

Como se pudo observar anteriormente ArgoCD provee una interfaz web interactiva con la cual podemos ver el estado de nuestros servicios de Kubernetes al igual que hacer configuraciones rápidas que nos ayuden en el proceso de despliegue continuo. Así mismo, nos provee una visión global de los recursos que fueron creados en cada aplicación, podemos ver un ejemplo de esto al seleccionar la aplicación que creamos anteriormente.

En esta vista ArgoCD nos presenta todos los recursos que fueron creados y que están siendo ejecutados tal como tutorial-server service y tutorial-server deployment, los replica set que se están ejecutando y los pods asociados a cada uno.

Si seleccionamos un pod, vamos a ver su yml de definición, los eventos que han sucedido y los logs del servidor. También es posible realizar acciones tales como sincronizar el pod o eliminarlo desde la interfaz.

Por último podemos observar que en la parte inferior donde se encuentra el yml (live manifest) hay un botón de Edit que nos permite editar la configuración del recurso en tiempo real para su sincronización, lo cual es bastante útil al momento de necesitar escalar o realizar un rollback desde la interfaz web. Con el propósito de observar este comportamiento modificaremos el deployment desde la interfaz cambiando el número de réplicas a 5.

Una vez guardado el cambio es posible ver que se crean 3 pods más para un total de 5.

Es recomendable no abusar de estas modificaciones desde la interfaz y utilizarlo solo en caso de emergencias ya que al modificar el yml desde ArgoCD no se modifica el archivo que se encuentra en el repositorio remoto, haciendo que mantengamos una aplicación no sincronizada lo cual nos indica ArgoCD con un estado OutOfSync.

Lo invitamos a seguir explorando las diferentes opciones que permite ArgoCD.

¡Éxitos en el desarrollo del tutorial y nos vemos en una próxima oportunidad!

Para evitar cobros en su medio de pago por parte de Google Cloud recomendamos eliminar los recursos de ArgoCD una vez haya finalizado el tutorial con los siguientes comandos.

user@192 ~ % kubectl delete all --all -n argocd
user@192 ~ % kubectl delete namespace argocd

[1] «Qué es Kubernetes», [Online]. Disponible en:https://kubernetes.io/es/docs/concepts/overview/what-is-kubernetes/ .

[2] «Descripción general de Autopilot | Documentación de Kubernetes Engine | Google Cloud». [Online]. Disponible en:https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview

[3] «ArgoCD docs». [Online]. Disponible en:https://argo-cd.readthedocs.io/