Implementando GitOps con ArgoCD

0
3067

El término GitOps es relativamente reciente, se empezó hablar de él en el año 2017 en un artículo de Alexis Richarsdson (Co-fundador y CEO de Weaveworks). Con el tiempo se ha ido popularizando y han aparecido múltiples herramientas que implementan este nuevo proceso de despliegue. Aunque el término es relativamente joven, el concepto que esta detrás de él no tanto. En proyectos donde he colaborado ya se estaba aplicando la misma filosofía antes de la aparición de este término en la comunidad.

GitOps rompe con el tradicional proceso de CI/CD que data del año 2006 (Continuos Integration) y 2013 (Continuos Delivery) y que hasta a la fecha la mayoría de las empresas utilizan. GitOps intenta actualizarlo a las tecnologías que han ido apareciendo en estos años (microservicios, contenedores, orquestador de contenedores, Cloud, etc.). Quiero destacar que, GitOps, no es ninguna herramienta sino es un concepto que define un pipeline diferente al tradicional. Por tanto, las empresas pueden tener diferentes formas de implementar GitOps pero respetando los principios que define.

El nombre de GitOps ya nos da una pista y es que Git es la pieza central de este nuevo pipeline. Tiene cuatro principios:

  1. Entorno definido mediante lenguaje declarativo : En la actualidad, prácticamente la mayoría del software usa lenguajes declarativos para definir la configuración en vez de utilizar un conjunto de instrucciones. Al usar configuración declarativa, cualquier persona puede saber que recursos utiliza cada aplicación y cuál es su configuración en cada entorno. Almacenando esta configuración en un repositorio de Git se podrá desplegar o restaurar las aplicaciones más fácilmente ya que cualquier cambio está registrado en él. Además ante algún desastre se puede reconstruir rápidamente ya que sólo se tiene que volver a aplicar la configuración.
  2. Git como fuente de la verdad: con la configuración declarativa almacenada en Git se tiene un único lugar de configuración de las aplicaciones. Cualquier cambio de configuración debe ser subido al repositorio, de esta forma se tiene lo que se ha definido como única fuente de la verdad (single source of truth). Esto simplifica los procesos de rollbacks de las aplicaciones ya que sólo será necesario restaurar un commit previo para que la aplicación vuelva a tener el estado deseado.
  3. Despliegues automático bajo aprobación : una vez que la configuración de la aplicación se encuentre almacenada en Git, se puede utilizar el sistema de aprobación para actualizar el estado de las aplicaciones. Cualquier cambio que se quiera realizar se hará mediante el sistema de aprobación de Git. Una vez aprobado el cambio se aplica automáticamente en el sistema. Con GitOps, no será necesario tener credenciales para aplicar los cambios ya que es el propio cluster el que aplica el cambio cuando el repositorio es actualizado. Únicamente el sistema tiene que tener acceso al repositorio de configuración e imágenes de contenedores.
  4. Uso de agentes para asegurar el correcto despliegue : con el despliegue automático se debe tener agentes que aseguren que el estado solicitado se ha aplicado correctamente y sino alertarnos de ello.

Para ver realmente la diferencia entre los dos pipeline, vamos a verlo mejor con estos dos diagramas. Un pipeline CI/CD tradicional tiene el siguiente:

 

Cuando un desarrollador sube al repositorio de la aplicación el código, se lanza el proceso de construcción que habitualmente se compone de: ejecución de pruebas unitarias, de integración, comprobación de la calidad, generación de la imagen con la aplicación y subida al repositorio de imágenes. Posteriormente se despliega en el cluster de kubernetes, todo ello desde el propio pipeline.

En cambio, el pipeline de GitOps es ligeramente diferente, separando el proceso de construcción del proceso de despliegue.

Como se puede ver en el diagrama, el proceso de construcción es idéntico al anterior, el verdadero cambio se centra en el despliegue. Aparecen dos nuevos elementos: el repositorio de configuración, donde se almacena todos los ficheros de despliegue de nuestra aplicación y un operador desplegado en el cluster de kubernetes que se encarga de monitorizar el repositorio de configuración y cuando exista un cambio desplegarlo en el cluster. Por tanto, cuando se quiera subir una nueva versión de la aplicación, se deberá realizar un Pull Request en el repositorio de configuración, y cuando éste se haya aprobado por las personas encargadas para este propósito se despliega automáticamente en el entorno correspondiente en el que se haya solicitado el despliegue.

GitOps añade un beneficio considerable desde el punto de vista de seguridad. El propio cluster es el que se encarga de desplegar las aplicaciones a diferencia de los pipelines tradicionales que necesitan tener las credenciales con privilegios de administrador para poder desplegar las aplicaciones. Además, con GitOps, cualquier cambio de estado del cluster esta registrado: se sabe quién realizo el cambio, quién lo aprobó y cuando se desplegó.

Otro aspecto importante es cuando se necesita restaurar el cluster por algún desastre. En el caso de GitOps solo se debe sincronizar los repositorios de configuración, mientras que en el pipeline tradicional se debe re-ejecutar los jobs de todas las aplicaciones.

En la actualidad, existen un gran número de aplicaciones con las que podemos implementar este nuevo pipeline, aunque dos de ellas prevalecen sobre las demás. FluxCD y ArgoCD son hoy día las herramientas Open Source con una mayor aceptación por parte de la comunidad. Ambos proyectos forman parte de la CNCF (Cloud Native Computing Foundation) y en los últimos años son los que más actividad en sus repositorios han tenido. De hecho, al final de año pasado se comunicó que FluxCD y ArgoCD iban fusionar ambos proyectos para generar una herramienta que aglutinase lo mejor de cada producto. Este nuevo proyecto se llama GitOps-Engine y en los próximos meses habrá que estar atentos.

De las dos, creo que ArgoCD es la más completa ya que a pesar de ser un producto Open Source tiene funcionalidades de producto de pago. De hecho, entre los clientes de Argo se encuentran empresas como Google, RedHat, Alibaba, Adobe, Sap, IBM, etc, lo que indica que no es un mal producto. ArgoCD forma parte de ArgoProject que tiene más proyecto interesantes como: Argo-Workflow o Argo-Rollouts que os recomiendo que le echéis un vistazo.

ArgoCD

ArgoCD es un operador de kubernetes, que define un conjunto de CRDs (Custom Resource Definitions) usados para su configuración. A diferencia de otros productos similares, sólo implementa la monitorización de los repositorios realizando Pulling, es decir, cada cierto tiempo lee los repositorios configurados y aplica los cambios cuando haya alguna modificación. Hay otro productos, como FluxCD, que además monitorizan cambios en el repositorio de contenedores y actualiza las aplicaciones cuando nuevas imágenes son subidas.

Es compatible con muchos de las herramientas para generar manifiestos de despliegue como: kustomize, helm, ksonnet, jsonnet y ficheros tradicionales de despliegue de kubernetes. Además es posible ampliar con otras herramientas mediante plugins.

ArgoCD puede desplegar aplicaciones en multiples Cluster y así centralizar todo el despliegue de nuestra infraestructura con esta herramienta. Además permite leer la configuración de despliegue de las aplicaciones de diversos repositorios lo que nos permite elegir diferentes estrategias. Este aspecto creo que es un punto fuerte a diferencia de FluxCD que sólo puede tener un sólo repositorio de configuración para todas las aplicaciones.

La seguridad es uno de los puntos fuertes, de hecho lo comentan en su página, que el desarrollo del producto ha sido creado teniendo muy en cuenta este aspecto. Es capaz de integrarse con un gran número de SSO como: OIDC, OAuth2, LDAP, SAML 2.0, GitHub, GitLab, Microsoft oLinkedIn y tiene una política de seguridad basada en roles pudiendo ser mapeados con roles de nuestro SSO.

Como veremos, ArgoCD, tiene un interfaz muy simple pero también podemos comunicarnos por terminal sin necesidad de acceder a su portal de administración. Tiene integración mediante Webhook con las aplicaciones CI más usadas como: GitHub, BitBucket o GitLab.

Una vez comentado algunas de los aspectos que ofrece ArgoCD, vamos a ver como implementar GitOps usando ArgoCD, para ello usaremos:

  • minikube para disponer de un entorno con kubernetes en nuestra máquina,
  • se instalará Gitlab como gestor de repositorios y herramienta de integración continua. En él se configurará dos repositorios: el repositorio que simulará nuestra aplicación y el repositorio de configuración.
  • y por último se instalará y configurará ArgoCD en kubernetes para el despliegue automático.

El entorno utilizado para escribir este tutorial:

  • Hardware: Mac Book Pro (2,6 GHz Intel Core i7, 32 GB RAM, 1 TB SSD)
  • Sistema Operativo: Catalina 10.15.4
  • Minikube: 1.9.2
  • Helm: 3.1.2
  • Gitlab: 12.9.2
  • ArgoCd: 1.5.0

Minikube

Lo primero es instalar minikube en nuestra máquina con los addons: dashboard, metrics-server, ingress y registry. Además se necesitará aumentar la memoria y CPU que usa por defecto minikube para poder correr Gitlab en kubernetes.

Gitlab

Arrancado minikube lo siguiente es instalar Gitlab. Usaremos los Charts de Helm que el propio Gitlab ofrece para instalar su producto en kubernetes.

Crearemos el namespace donde se instalará Gitlab.

Antes de instalar Gitlab, tendremos que modificar la configuración de CoreDNS para que todos los elementos que instalemos en el cluster puedan resolver el nombre de dominio de Gitlab. De lo contrario, ArgoCD o GitlabRunner darán problemas cuando tengan que comunicarse con él.

Lo primero es conocer la ip de nuestro cluster:

Creamos el fichero coredns.yaml con el siguiente contenido:

Como se puede ver se ha mapeado el nombre «gitlab.192.168.64.10.nip.io» con «unicorn.192.168.64.10.nip.io» ya que el frontend de Gitlab en el cluster esta bajo el dominio «unicorn.192.168.64.10.nip.io«. De esta forma cuando ArgoCD o GitlabRunner acceda al cluster usando «gitlab.192.168.64.10.nip.io» todo funcionará correctamente.

Ahora ya se puede instalar Gitlab:

Para que todo funcione correctamente, tendremos que cambiar la configuración que viene de base en el Chart de GitlabRunner. La configuración que vamos aplicar es para que GitlabRunner confíe en el certificado autofirmado que tiene Gitlab sino nunca conseguirá registrarse en él.

A continuación editamos nuestro fichero de «/etc/hosts» para resolver el dominio de gitlab. En mi caso es «gitlab.192.168.184.10.nip.io» en vuestro caso podría ser otro en función de vuestra configuración de red.

Finalmente, tenemos que asegurarnos que todo ha desplegado correctamente. Para ello, accedemos al dashboard de kubernetes ejecutando:

Esto nos abrirá una navegador con la aplicación «dashboard». Seleccionamos el namespace «gitlab» y vamos a la opción «Workloads» y esperamos a que todo se ponga en verde.

Ahora solo nos queda acceder a Gitlab desde un navegador accediendo, en mi caso, a https://gitlab.192.168.184.10/.

 

El usuario para acceder a Gitlab es «root» y la contraseña se puede recuperar ejecutando el siguiente comando:

Una vez que hemos accedido, lo primero es cambiar la password del usuario administrador. Vamos al area de usuario y pulsamos en editar sobre el usuario «Administrador».

 

Y cambiamos la password:

 

Para ver el flujo habitual de construcción y despliegue con GitOps se necesitan cuatro usuarios que representan los cuatro roles que intervienen.

  • reviewer: es la persona responsable de aprobar los Pull Request que se realizan en el repositorio de la aplicación por los desarrolladores y solicitar los cambios de configuración en el repositorio de configuración.
  • developer: es la persona que desarrolla la aplicación y tiene permisos de lectura/escritura sobre el repositorio de la aplicación, aunque no tendrá permisos sobre ramas protegidas como en nuestro caso «master».
  • operator: es la persona que aprueba los Pull Request en el repositorio de configuración antes de ser desplegado.
  • argocd: es el usuario que ArgoCD usa para monitorizar los cambios en los repositorios de configuración. En en el caso de ArgoCD sólo necesita permisos de lectura.

Como el proceso es el mismo para los cuatro usuarios, sólo mostraremos para uno de ellos. Accedemos al área de usuarios, pulsamos sobre «New User», rellenamos el formulario como se ve en la imagen inferior y pulsamos en «Create User».

 

Luego pulsamos «Edit» sobre el usuario creado y le establecemos una password:

 

Creado los cuatro usuarios, ahora nos queda crear los dos repositorios:

  • helloworld: repositorio con el código fuente de la aplicación.
  • helloworld-ops: repositorio con los ficheros de despliegue en kubernetes para la aplicación helloworld.

Con el usuario administrador, pulsamos sobre el símbolo «+» de la barra superior y seleccionamos la opción «New project».

 

Y damos de alta el repositorio «helloworld».

Ahora sólo nos queda asociar a los usuarios con el repositorio. Accedemos al proyecto y pulsamos sobre la opción «Settings» del menú izquierdo y a continuación la subopción «Members». Ahí daremos de alta al usuario developer con el role Developer y al usuario «reviewer» con el role «Maintainer».

 

Sobre el proyecto «helloworld-ops» hacemos lo mismo. Vamos a «Settings» -> «Members» y damos de alta al usuario «reviewer» con role de «Developer», al usuario «operator» con role de «Maintainer» y al usuario «argocd» con el role «Reporter».

Desplegando el proyecto helloworld

Para este tutorial vamos a simular un pipeline sencillo. El usuario «developer» sube el código fuente de la aplicación a una rama «feature» y solicita un Pull Request a la rama master. Luego, el «reviewer» aprueba el cambio, se mergea a master y se ejecuta el pipeline de construcción. A continuación, el «reviewer» obtiene la imagen de docker construida y hace un Pull Request en el repositorio de configuración con los ficheros de despliegue. Y finalmente el usuario «operator» aprueba el cambio para que ArgoCD lo despliegue en el cluster.

En el proceso de construcción vamos a simular una aplicación super sencilla. Consiste en un html que muestra el mensaje «Hello World!!!». Este recurso será empaquetado en una imagen de docker de un nginx con la configuración necesaria para servir el html. Para evitar alargar mucho este tutorial y centrarnos en lo importante que es como ArgoCD despliega la aplicación. He subido a mi cuenta de Github los recursos necesarios para el repositorio de la aplicación y el repositorio de configuración.

Lo primero vamos a iniciar el repositorio. Simulando que somos el usuario «reviewer». Creamos la rama «master» añadiendo el fichero «.gitlab-ci.yml» vacío.

Ahora nos ponemos el gorro del usuario «developer», creamos una rama feature, añadimos los ficheros necesarios para nuestra aplicación y finalmente subimos los cambios al repositorio:

Nos saldrá algo como:

Ahora creamos el Pull Request para que el usuario «reviewer» acepte el cambio. Así que copiamos el enlace que salió cuando ejecutamos el comando push. En nuestro caso https://gitlab.192.168.64.10.nip.io/root/helloworld2/-/merge_requests/new?merge_request[source_branch]=feature/HW-001 y nos saldrá una pantalla como esta.

Asignamos el Pull Request al usuario «reviewer» y pulsamos «Submit merge request». Si ahora accedemos con la cuenta de «reviewer» vemos en la parte superior derecha que hay una notificación de que tenemos un Pull Request asignado. Pulsamos sobre ella y nos muestra el listado de Pull Request que tenemos asignadas.

 

Accedemos a la Pull Request y vemos una pantalla como esta. Después de que el usuario «reviewer» haya validado los cambios, el usuario pulsa el botón «Merge».

 

El pipeline que se ha definido en el fichero .gitlab-ci.yml empieza ejecutarse. Para ver el detalle del pipeline pulsamos sobre en el enlace la sección de pipeline.

Vemos una pantalla con el pipeline de ejecución, donde se ha ejecutado un stage llamado «generate-image».

Si pulsamos sobre él vemos el resultado de la ejecución. Si vamos al final de las trazas se puede observar que se ha subido la imagen de docker al repositorio. En nuestro caso la tag que se le ha asignado a nuestra imagen en esta construcción es «helloworld:ci-34». Esta tag es muy importante porque es la información que el usuario «reviewer» va a necesitar para que esta nueva versión de la aplicación sea desplegada por ArgoCD en nuestro cluster de kubernetes.

 

Ya sólo nos queda la parte del repositorio de configuración. Lo primero al igual que se hizo con el otro repositorio tenemos que inicializarlo usando el usuario «operator».

A continuación, el usuario «reviewer» tendrá que ir al repositorio de configuración asociado con la aplicación de helloworld, en nuestro caso, «helloworld-ops» y hacemos un Pull Request.

Antes de hacer el Pull Request tenemos que editar el fichero «deployment.yml» cambiando la imagen de docker que vamos a desplegar nuestra aplicación. Así que editamos el fichero y modificamos la imagen con el valor «helloworld:ci-34» que hemos visto anteriormente.

También editamos el fichero «ingress.yml» para cambiar el host «helloworld.192.168.64.10.nip.io» por la ip de tu minikube.

Y finalmente hacemos push:

Como hicimos con el Pull Request anterior, copiamos el enlace que nos genera git en el terminal. En nuestro caso https://gitlab.192.168.64.10.nip.io/root/helloworld-ops/-/merge_requests/new?merge_request[source_branch]=feature/HW-001. Creamos el Pull Request y nos conectamos al Gitlab con el usuario «operator» y lo aceptamos.

Ya tenemos todo preparado en Gitlab, ahora vamos con ArgoCD.

Configurando ArgoCD

Para instalar ArgoCD, creamos una nuevo namespace en kubernetes llamado «argocd» y desplegamos el manifiesto que Argo proporciona en su repositorio. A continuación y para tener acceso cambiamos el tipo de servicio a LoadBalancer ya que viene por defecto como ClusterIP.

ArgoCD por defecto crea un usuario administrador cuya password se obtiene ejecutando el siguiente comando:

Y para acceder a la ampliación de ArgoCD lo haremos ejecutando:

Y veremos una página como:

Ahora nos logamos con el usuario «admin» y configuraremos ArgoCD para que monitorice nuestro repositorio de configuración. En el menú de la izquierda, accedemos a la opción «Manage your repositories, projects, settings».

Desde esta opción, se podrá gestionar:

  • todos los repositorios de configuración que se estén monitorizando para el despliegue continuo,
  • gestión de certificados de confianza para conectarnos a los repositorios Git. ArgoCD viene por defecto con varios certificados para conectarse a las plataformas más usadas hoy día.
  • gestión de los clusters de kubernetes donde van a instalarse las aplicaciones,
  • gestión de nuestros proyectos de despliegue,
  • y las cuentas dadas de alta en ArgoCD.

En nuestro caso configuraremos nuestro repositorio de configuración «helloworld-ops» y un proyecto. Así que vamos a la opción «Repositories» y pulsamos sobre la opción «Connect Repo using https» y introducimos la url del repositorio de helloworld-ops e introducimos el usuario «argocd» y la password que hayamos usado en el alta de este usuario y por último activamos «Skip server verification» ya que nuestro Gitlab usa un certificado autofirmado. Otra posibilidad para evitar activar esta opción sería acceder a la opción de «Certificados» y dar de alta nuestro certificado autofirmado.

Ahora accedemos a la opción «Projects», pulsamos sobre «New project» y rellenamos los datos:

  • Project Name: helloworld
  • Source: https://gitlab.192.168.64.10.nip.io/root/helloworld-ops.git
  • Cluster Name: https://kubernetes.default.svc
  • Namespace: default

 

En nuestro caso, seleccionamos el repositorio que hemos dado de alta, el cluster por defecto y usaremos el namespace default para desplegar las aplicaciones que cuelguen de este proyecto. ArgoCD da mucha más opciones de configuración pero para este tutorial no vamos a usarlas.

Ya sólo nos queda dar de alta la aplicación, vamos al menú izquierdo y pulsamos sobre «Manage your applications, and diagnose health problems».

 

Seleccionamos «New App» y damos de alta nuestra aplicación «helloworld».

  • Application Name: helloworld
  • Project: helloworld
  • Sync policy: Automatic
  • Sync options: activada
  • Repository URL: https://gitlab.192.168.64.10.nip.io/root/helloworld-ops.git
  • Revision: HEAD
  • Path: .
  • Cluster Name: https://kubernetes.default.svc
  • Namespace: default

 

Si pulsamos sobre la aplicación «helloworld», veremos que nuestra aplicación se ha desplegado automáticamente. Con ArgoCD se puede observar el status de cada uno de los recursos que nuestra aplicación haya desplegado.

Si no vemos algo como la imagen de arriba es porque todavía ArgoCD no ha sincronizado la aplicación. Podemos forzarlo pulsando el botón «Sync» o dejar que ArgoCD lo haga automáticamente.

Ya sólo nos queda acceder a nuestra aplicación. Añadimos al nuestro fichero /etc/hosts la nueva aplicación.

Abrimos un navegador y tecleamos en nuestro caso http://helloworld.192.168.184.10/ y debemos ver algo como esto.

 

Imaginaros que necesitamos que en vez de una replica para nuestra aplicación necesitamos 2 replicas para poder dar servicio a más peticiones. El usuario «reviewer» deberá editar el fichero «deployment.yml» y cambiar el número de réplicas y realizar un Pull Request para que el usuario «operator» acepte el cambio. Después de todo este proceso, en ArgoCD debemos ver algo como esto:

Conclusión

Como habéis podido observar, GitOps, es un nuevo planteamiento del proceso de despliegue continuo en una infraestructura con kubernetes. Con productos como ArgoCD o similares este proceso se simplifica bastante y mejora considerablemente la seguridad de nuestro pipeline al no tener que estar gestionando las credenciales necesarias para el despliegue de las aplicaciones en el cluster de kubernetes.

Dejar respuesta

Please enter your comment!
Please enter your name here