Al finalizar el tutorial el estudiante estará en capacidad de:
En particular se utilizarán los siguientes recursos:
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:
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:
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.
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
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
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.
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.
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.
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/