Nota de traducción.: Tras una reciente publicación sobre los métodos pull y push en GitOps, hemos observado un interés en este modelo en general; sin embargo, ha habido muy pocas publicaciones en ruso sobre este tema (prácticamente no hay en Habr). Por lo tanto, estamos contentos de ofrecerles la traducción de otro artículo, ¡aunque ya tenga casi un año! — de la empresa Weaveworks, cuyo fundador acuñó el término «GitOps». En el texto se explica la esencia del enfoque y las diferencias clave con respecto a lo que ya existe.
Hace un año publicamos . En ese momento, contamos cómo el equipo de Weaveworks lanzó un SaaS completamente basado en Kubernetes y desarrolló un conjunto de mejores prácticas prescriptivas para implementar, administrar y monitorear en un entorno cloud native.
El artículo resultó ser popular. Otras personas comenzaron a hablar sobre GitOps y a publicar nuevas herramientas para , , , , etc. En nuestro sitio web aparecieron publicaciones y casos de uso de GitOps. Pero algunas personas todavía tenían preguntas. ¿En qué se diferencia el modelo del tradicional y la entrega continua ()? ¿Es necesario usar Kubernetes?
Pronto nos dimos cuenta de que necesitábamos una nueva descripción que ofreciera:
- Una gran cantidad de ejemplos e historias;
- Una definición concreta de GitOps;
- Una comparación con la entrega continua tradicional.
En este artículo intentamos abordar todos estos temas. Encontrarás una introducción actualizada a GitOps y una perspectiva desde los desarrolladores y CI/CD. Principalmente nos centramos en Kubernetes, aunque el modelo se puede generalizar.
Conozcan: GitOps
Imagina a Alicia. Ella dirige una empresa llamada Family Insurance, que ofrece pólizas de seguro de salud, automóviles, bienes raíces y seguros de viaje a personas que están demasiado ocupadas como para entender los matices de los contratos por sí solas. Su negocio comenzó como un proyecto paralelo, mientras Alicia trabajaba en un banco como científica de datos. Un día se dio cuenta de que podía utilizar algoritmos computacionales avanzados para analizar datos de manera más eficiente y crear paquetes de seguros. Los inversores financieron el proyecto, y ahora su empresa genera más de 20 millones de dólares al año y está creciendo rápidamente. En este momento, cuenta con 180 empleados en diferentes posiciones. Entre ellos está el equipo tecnológico, que se encarga del desarrollo, mantenimiento del sitio web, la base de datos y el análisis de la base de clientes. Este equipo de 60 personas está liderado por Bob, el director técnico de la empresa.
El equipo de Bob despliega sistemas de producción en la nube. Sus principales aplicaciones funcionan en GKE, aprovechando las ventajas de Kubernetes en Google Cloud. Además, utilizan diversas herramientas para el manejo de datos y análisis.
Family Insurance no tenía la intención de usar contenedores, pero se contagió del entusiasmo por Docker. Pronto, los especialistas de la empresa descubrieron que GKE permite desplegar clústeres para probar nuevas funcionalidades de manera fácil y sin complicaciones. Se añadieron Jenkins para CI y Quay para organizar el registro de contenedores, y se escribieron scripts para Jenkins que enviaban nuevos contenedores y configuraciones a GKE.
Ha pasado un tiempo. Alice y Bob se sintieron decepcionados con el rendimiento del enfoque elegido y su impacto en el negocio. La implementación de contenedores no mejoró el rendimiento tanto como esperaba el equipo. A veces, los despliegues fallaban, y no estaba claro si esto se debía a cambios en el código. También resultó difícil rastrear los cambios en las configuraciones. A menudo tenían que crear un nuevo clúster y mover las aplicaciones a él, ya que era la forma más sencilla de deshacerse del caos en el que se había convertido el sistema. Alice temía que la situación empeorara a medida que evolucionara la aplicación (además, un nuevo proyecto basado en machine learning estaba en desarrollo). Bob había automatizado gran parte del trabajo y no entendía por qué el pipeline seguía siendo inestable, tenía una mala escalabilidad y requería intervención manual de vez en cuando.
Entonces conocieron GitOps. Esta solución resultó ser justo lo que necesitaban para avanzar con confianza.
Alice y Bob habían estado escuchando sobre flujos de trabajo basados en Git, DevOps e infraestructura como código durante varios años. La singularidad de GitOps es que aporta una serie de mejores prácticas —específicas y normativas— para implementar estas ideas en el contexto de Kubernetes. Este tema , incluso en el .
Family Insurance decide implementar GitOps. Ahora la empresa tiene un modelo de operación automatizado, compatible con Kubernetes y que combina rapidez para con estabilidad, ya que ellos:
- descubrieron que la productividad del equipo se había duplicado y nadie se estaba volviendo loco;
- dejaron de mantener scripts. En cambio, ahora pueden concentrarse en nuevas funciones y mejorar los métodos de ingeniería, por ejemplo, implementar despliegues canarios y mejorar las pruebas;
- mejoraron el proceso de despliegue: ahora rara vez falla;
- tienen la capacidad de restaurar los despliegues después de fallos parciales sin intervención manual;
- adquirieron unamayor audiencia.mayor confianza en los sistemas de entrega. Alice y Bob descubrieron que podían dividir al equipo en grupos que se enfocan en microservicios y trabajan en paralelo;
- pueden hacer entre 30 y 50 cambios en el proyecto cada día gracias al esfuerzo de cada grupo y probar nuevas técnicas.
- facilitan la atracción de nuevos desarrolladores al proyecto, quienes tienen la posibilidad de implementar actualizaciones en producción a través de pull requests en unas pocas horas;
- facilitan la auditoría en el marco de SOC2 (sobre la conformidad de los proveedores de servicios con los requisitos de gestión segura de datos; para más detalles, lea, por ejemplo, — nota del traductor).
¿Qué sucedió?
GitOps son dos cosas:
- Un modelo operativo para Kubernetes y cloud native. Proporciona un conjunto de mejores prácticas para la implementación, gestión y supervisión de clústeres y aplicaciones empaquetadas en contenedores. Una elegante definición en forma desde :
- El camino hacia la creación de un entorno orientado a desarrolladores para la gestión de aplicaciones. Aplicamos un flujo de trabajo de Git tanto a la operación como al desarrollo. Tenga en cuenta que no se trata solo de un Git push, sino de la organización de todo el conjunto de herramientas CI/CD y UI/UX.
Unas palabras sobre Git
Si no está familiarizado con los sistemas de control de versiones y el flujo de trabajo basado en Git, le recomendamos encarecidamente que los estudie. Al principio, trabajar con ramas y pull requests puede parecer magia negra, pero los beneficios valen el esfuerzo. Aquí para empezar.
Cómo funciona Kubernetes
En nuestra historia, Alice y Bob se acercaron a GitOps después de haber trabajado un tiempo con Kubernetes. De hecho, GitOps está estrechamente relacionado con Kubernetes: es un modelo operativo para infraestructuras y aplicaciones basadas en Kubernetes.
¿Qué ofrece Kubernetes a los usuarios?
Aquí hay algunas características clave:
- En el modelo de Kubernetes, todo se puede describir en forma declarativa.
- El servidor API de Kubernetes acepta esa declaración como entrada y luego intenta constantemente llevar el clúster al estado descrito en la declaración.
- Las declaraciones son suficientes para describir y gestionar una amplia variedad de cargas de trabajo — 'aplicaciones'.
- Como resultado, los cambios en la aplicación y el clúster ocurren debido a:
- cambios en las imágenes de los contenedores;
- cambios en la especificación declarativa;
- errores en el entorno — por ejemplo, caídas de contenedores.
Las maravillosas capacidades de convergencia de Kubernetes
Cuando un administrador realiza cambios en la configuración, el orquestador de Kubernetes aplicará esos cambios al clúster hasta que su estado se acerque a la nueva configuración. Este modelo funciona para cualquier recurso de Kubernetes y se expande a través de Custom Resource Definitions (CRDs). Por lo tanto, los despliegues de Kubernetes tienen las siguientes propiedades maravillosas:
- Automatización: las actualizaciones de Kubernetes proporcionan un mecanismo para automatizar el proceso de aplicar cambios de manera correcta y oportuna.
- Convergencia: Kubernetes seguirá intentando actualizaciones hasta lograr el éxito.
- Idempotencia: las reaplicaciones de convergencia conducen al mismo resultado.
- Determinismo: dada la suficiencia de recursos, el estado del clúster actualizado depende únicamente del estado deseado.
Cómo funciona GitOps
Hemos aprendido lo suficiente sobre Kubernetes como para explicar los principios de funcionamiento de GitOps.
Volvamos a los equipos de Family Insurance relacionados con microservicios. ¿Con qué suelen lidiar? Mire la lista a continuación (si algunos puntos le parecen extraños o desconocidos, por favor, absténgase de criticar y quédese con nosotros). Son solo ejemplos de flujos de trabajo basados en Jenkins. También existen muchos otros procesos al trabajar con otras herramientas.
Lo principal es que vemos que cada actualización termina con cambios en los archivos de configuración y los repositorios de Git. Estos cambios en Git hacen que el 'operador GitOps' actualice el clúster:
1. Flujo de trabajo: 'Construcción de Jenkins — rama master».
Lista de tareas:
- Jenkins envía imágenes etiquetadas a Quay;
- Jenkins envía la configuración y los Helm charts al bucket del almacenamiento master;
- Una función en la nube copia la configuración y los charts del bucket del almacenamiento master al repositorio Git master;
- El operador GitOps actualiza el clúster.
2. Construcción de Jenkins — rama release o hotfix:
- Jenkins envía imágenes no etiquetadas a Quay;
- Jenkins envía la configuración y los Helm charts al bucket del almacenamiento staging;
- Una función en la nube copia la configuración y los charts del bucket del almacenamiento staging al repositorio Git staging;
- El operador GitOps actualiza el clúster.
3. Construcción de Jenkins — rama develop o feature:
- Jenkins envía imágenes no etiquetadas a Quay;
- Jenkins envía la configuración y los Helm charts al bucket del almacenamiento develop;
- Una función en la nube copia la configuración y los charts del bucket del almacenamiento develop al repositorio Git develop;
- El operador GitOps actualiza el clúster.
4. Agregar un nuevo cliente:
- El gerente o administrador (LCM/ops) llama a Gradle para el despliegue inicial y la configuración de los balanceadores de carga de red (NLB);
- LCM/ops hace commit de una nueva configuración para preparar el despliegue para actualizaciones;
- El operador GitOps actualiza el clúster.
Descripción breve de GitOps
- Describa el estado deseado de todo el sistema utilizando especificaciones declarativas para cada entorno (en nuestra historia, el equipo de Bob define toda la configuración del sistema en Git).
- El repositorio de Git es la única fuente de verdad respecto al estado deseado de todo el sistema.
- Todos los cambios en el estado deseado se realizan mediante commits en Git.
- Todos los parámetros deseados del clúster también son observables en el propio clúster. Así podemos determinar si coinciden (convergen, converge) o difieren (divergen, diverge) el estado deseado y el observado.
- Si el estado deseado y el observado difieren, entonces:
- existe un mecanismo de convergencia que, tarde o temprano, sincronizará automáticamente el estado objetivo y el observado. Dentro del clúster, esto lo maneja Kubernetes.
- El proceso se inicia inmediatamente con una notificación de "cambio cometido".
- Después de un intervalo de tiempo configurable, se puede enviar una notificación de "diferencia" si los estados difieren.
- Así, todos los commits en Git provocan actualizaciones verificables e idempotentes en el clúster.
- Un rollback es una convergencia hacia un estado deseado anterior.
- La convergencia es definitiva. Su ocurrencia se indica por:
- La ausencia de notificaciones de "diferencia" durante un intervalo de tiempo determinado.
- Una notificación de "convergido" (por ejemplo, webhook, evento de escritura de Git).
¿Qué es la divergencia?
Repitamos una vez más: todas las propiedades deseadas del clúster deben ser observables en el propio clúster..
Algunos ejemplos de divergencia:
- Cambio en el archivo de configuración debido a la fusión de ramas en Git.
- Cambio en el archivo de configuración debido a un commit en Git realizado por un cliente GUI.
- Múltiples cambios en el estado deseado debido a un PR en Git, seguido de la creación de una imagen de contenedor y cambios en la configuración.
- Cambio en el estado del clúster debido a un error, conflicto de recursos que lleva a un "mal comportamiento", o simplemente un desvío accidental del estado original.
¿Qué representa el mecanismo de convergencia?
Algunos ejemplos:
- Para contenedores y clústeres, el mecanismo de convergencia es proporcionado por Kubernetes.
- El mismo mecanismo se puede utilizar para gestionar aplicaciones y construcciones basadas en Kubernetes (por ejemplo, Istio y Kubeflow).
- El mecanismo para gestionar la interacción laboral entre Kubernetes, los repositorios de imágenes y Git proporciona , que forma parte de .
- Para las máquinas básicas, el mecanismo de convergencia debe ser declarativo y autónomo. Desde nuestra experiencia, podemos decir que se acerca más a esta definición, sin embargo, todavía requiere supervisión humana. En este sentido, GitOps amplía las tradiciones de Infrastructure as Code.
GitOps une Git con un magnífico mecanismo de convergencia de Kubernetes, ofreciendo un modelo para la operación.
GitOps nos permite afirmar: solo aquellos sistemas que pueden ser descritos y observados son susceptibles de automatización y control.
GitOps está destinado a toda la pila cloud native (por ejemplo, Terraform, etc.)
GitOps no es solo Kubernetes. Queremos que todo el sistema se gestione de forma declarativa y utilice la convergencia. Por todo el sistema nos referimos al conjunto de entornos que trabajan con Kubernetes, como 'dev cluster 1', 'producción', etc. Cada entorno incluye máquinas, clústeres, aplicaciones y también interfaces para servicios externos que proporcionan datos, monitoreo, etc.
Observe lo crucial que es Terraform para el problema del bootstrap. Kubernetes debe estar desplegado en algún lugar, y el uso de Terraform significa que podemos aplicar los mismos flujos de trabajo de GitOps para crear una capa de gestión que subyace a Kubernetes y las aplicaciones. Es una buena práctica.
Se presta gran atención a la aplicación de los conceptos de GitOps a las capas por encima de Kubernetes. Actualmente, existen soluciones de tipo GitOps para Istio, Helm, Ksonnet, OpenFaaS y Kubeflow, así como, por ejemplo, para Pulumi, que crean una capa para el desarrollo de aplicaciones cloud native.
Kubernetes CI/CD: comparación de GitOps con otros enfoques
Como se mencionó, GitOps son dos cosas:
- Un modelo operativo para Kubernetes y cloud native, como se describió anteriormente.
- El camino hacia la organización de un entorno orientado a desarrolladores para la gestión de aplicaciones.
Para muchos, GitOps es ante todo un flujo de trabajo basado en Git pushes. A nosotros también nos gusta. Pero no es todo: ahora veamos los pipelines de CI/CD.
GitOps proporciona despliegue continuo (CD) para Kubernetes
GitOps ofrece un mecanismo de despliegue continuo que elimina la necesidad de 'sistemas de gestión de despliegues' separados. Todo el trabajo lo realiza Kubernetes por usted.
- La actualización de la aplicación requiere una actualización en Git. Esta es una actualización transaccional al estado deseado. El "despliegue" se realiza luego dentro del clúster por Kubernetes basado en la descripción actualizada.
- Debido a la naturaleza del funcionamiento de Kubernetes, estas actualizaciones son convergentes. Esto proporciona un mecanismo para el despliegue continuo, donde todas las actualizaciones son atómicas.
- Nota: ofrece un operador GitOps que integra Git y Kubernetes, permitiendo realizar CD al alinear el estado deseado con el estado actual del clúster.
Sin kubectl y scripts
Se debe evitar el uso de kubectl para actualizar el clúster, especialmente los scripts para agrupar comandos de kubectl. En su lugar, mediante un pipeline GitOps, el usuario puede actualizar su clúster de Kubernetes a través de Git.
Las ventajas incluyen:
- Precisión. Un grupo de actualizaciones puede aplicarse, converger y finalmente validarse, acercándonos al objetivo de un despliegue atómico. En contraste, el uso de scripts no garantiza ninguna convergencia (más sobre esto a continuación).
- Seguridad. Kelsey Hightower: "Limite el acceso al clúster de Kubernetes a herramientas de automatización y administradores cuya responsabilidad sea depurarlo o mantenerlo en funcionamiento". Ver también sobre seguridad y cumplimiento de especificaciones, así como a través del robo de credenciales de un script de Jenkins descuidado.
- Experiencia del usuario. Kubectl expone la mecánica del modelo de objetos de Kubernetes, que es bastante compleja. En ideal, los usuarios deben interactuar con el sistema en un nivel de mayor abstracto. Aquí nuevamente cito a Kelsey y recomiendo ver .
La diferencia entre CI y CD
GitOps mejora los modelos existentes de CI/CD.
Un servidor CI moderno es una herramienta de orquestación. En particular, es una herramienta para orquestar pipelines de CI. Estos incluyen compilación, prueba, fusión a trunk, etc. Los servidores CI automatizan la gestión de complejos pipelines de múltiples pasos. La tentación general es crear un script para un conjunto de actualizaciones de Kubernetes y ejecutarlo como parte de un pipeline para enviar cambios al clúster. De hecho, muchos especialistas hacen esto. Sin embargo, no es óptimo, y aquí está el por qué.
CI debe utilizarse para realizar actualizaciones en trunk, y el clúster de Kubernetes debe ajustarse en función de estas actualizaciones para gestionar CD "internamente". Lo llamamos , a diferencia del modelo push de CI. CD es parte de orquestación en tiempo de ejecución.
Por qué los servidores CI no deberían realizar CD mediante actualizaciones directas en Kubernetes
No utilices el servidor CI para orquestar actualizaciones directas en Kubernetes como un conjunto de tareas de CI. Este es un anti-patrón, del cual hablamos en nuestro blog.
Volvamos a Alicia y Bob.
¿Qué problemas enfrentaron? El servidor CI de Bob aplica cambios al clúster, pero si falla en el proceso, Bob no sabrá en qué estado está (o debería estar) el clúster y cómo corregirlo. Lo mismo se aplica en caso de éxito.
Supongamos que el equipo de Bob construyó una nueva imagen y luego parcheó sus despliegues para implementar la imagen (todo esto desde la tubería CI).
Si la imagen se construye correctamente, pero la tubería falla, el equipo tendrá que averiguar:
- ¿Se implementó la actualización?
- ¿Estamos ejecutando una nueva construcción? ¿Esto conducirá a efectos secundarios no deseados, con la posibilidad de obtener dos construcciones de la misma imagen inalterada?
- ¿Deberíamos esperar a la próxima actualización antes de ejecutar la construcción?
- ¿Qué salió mal exactamente? ¿Qué pasos hay que repetir (y cuáles de ellos se pueden repetir de manera segura)?
Organizar un flujo de trabajo basado en Git no garantiza que el equipo de Bob no enfrente estos problemas. Aún pueden cometer un error con el push del commit, con una etiqueta o con cualquier otro parámetro; sin embargo, este enfoque sigue estando mucho más cerca de un todo o nada explícito.
En resumen, aquí están las razones por las que los servidores CI no deben encargarse de CD:
- Los scripts de actualización no siempre son deterministas; es fácil cometer errores en ellos.
- Los servidores CI no convergen hacia un modelo declarativo del clúster.
- Es difícil garantizar la idempotencia. Los usuarios deben comprender la semántica profunda del sistema.
- Es más difícil realizar una recuperación después de una falla parcial.
Nota sobre Helm: si deseas usar Helm, recomendamos combinarlo con un operador de GitOps, como . Esto ayudará a garantizar la convergencia. Helm por sí solo no es determinista ni atómico.
GitOps como la mejor manera de realizar Entrega Continua para Kubernetes
El equipo de Alice y Bob implementa GitOps y descubre que es mucho más fácil trabajar con productos de software, mantener un alto rendimiento y estabilidad. Terminemos este artículo con ilustraciones que muestren cómo se ve su nuevo enfoque. Tenga en cuenta que principalmente hablamos de aplicaciones y servicios, sin embargo, GitOps se puede utilizar para gestionar toda la plataforma.
Modelo de operación para Kubernetes
Mire el siguiente diagrama. Representa a Git y el repositorio de imágenes de contenedores como recursos compartidos para dos ciclos de vida orquestados:
- El pipeline de integración continua, que lee y escribe archivos en Git y puede actualizar el repositorio de imágenes de contenedores.
- El pipeline de Runtime GitOps, que combina despliegue con gestión y observabilidad. Lee y escribe archivos en Git y puede cargar imágenes de contenedores.
¿Cuáles son las principales conclusiones?
- División de problemas: Tenga en cuenta que ambos pipelines pueden intercambiar datos solo actualizando Git o el repositorio de imágenes. En otras palabras, existe un cortafuegos entre la CI y el entorno de ejecución. Lo llamamos "cortafuegos de inmutabilidad" (immutability firewall), ya que todas las actualizaciones de los repositorios crean nuevas versiones. Para información adicional sobre este tema, consulte las diapositivas 72-87. .
- Se puede utilizar cualquier servidor CI y Git: GitOps funciona con cualquier componente. Puede seguir utilizando sus servidores CI y Git favoritos, repositorios de imágenes y conjuntos de pruebas. Casi todas las demás herramientas de Continuous Delivery en el mercado requieren su propio servidor CI/Git o repositorio de imágenes. Esto puede convertirse en un factor limitante en el desarrollo de cloud native. En el caso de GitOps, puede usar las herramientas con las que ya está familiarizado.
- Eventos como herramienta de integración: Tan pronto como los datos en Git se actualizan, Weave Flux (o el operador Weave Cloud) notifica al runtime. Cada vez que Kubernetes acepta un conjunto de cambios, Git se actualiza. Esto proporciona un modelo de integración sencillo para organizar flujos de trabajo para GitOps, como se muestra a continuación.
Conclusión
GitOps proporciona garantías significativas de actualización necesarias para cualquier herramienta moderna de CI/CD:
- automatización;
- convergencia;
- idempotencia;
- determinismo.
Esto es importante, ya que ofrece un modelo de operación para desarrolladores en el ámbito cloud native.
- Las herramientas tradicionales para la gestión y supervisión de sistemas están asociadas a los equipos de operaciones que funcionan dentro de un runbook. (conjunto de procedimientos y operaciones rutinarias — nota del traductor), vinculado a un deployment específico.
- En la gestión de sistemas cloud native, las herramientas de observación son la mejor manera de evaluar los resultados de los despliegues, para que el equipo de desarrolladores pueda reaccionar rápidamente a ellos.
Imagina múltiples clústeres dispersos en diferentes nubes y numerosos servicios con sus propios equipos y planes de despliegue. GitOps ofrece un modelo invariante a gran escala para gestionar toda esta abundancia.
P.D. del traductor
También puedes leer en nuestro blog:
- «»;
- «»;
- «».
Solo los usuarios registrados pueden participar en la encuesta. , por favor.
¿Sabías sobre GitOps antes de la aparición de estas dos traducciones en Habr?
Sí, lo sabía.
Solo de manera superficial.
No
35 usuarios votaron. 10 usuarios se abstuvieron.
Fuente: habr.com
