Despliegues seguros con Config Sync

En este documento se explica a los operadores de clústeres y a los administradores de plataformas cómo implementar cambios de forma segura en varios entornos mediante Config Sync. Este enfoque puede ayudarte a evitar errores que afecten a todos tus entornos simultáneamente.

Config Sync te permite gestionar clústeres únicos, clústeres multiinquilino y configuraciones de Kubernetes multiclúster mediante archivos almacenados en un repositorio de Git.

Las configuraciones pueden representar varios elementos, entre los que se incluyen los siguientes:

Config Sync es especialmente adecuado para desplegar configuraciones, políticas y cargas de trabajo necesarias para ejecutar la plataforma que creas sobre Google Kubernetes Engine, como agentes de seguridad, agentes de monitorización y gestores de certificados.

Aunque puedes implementar aplicaciones orientadas a los usuarios con Config Sync, no te recomendamos que vincules su ciclo de vida de lanzamiento al ciclo de vida de lanzamiento de las cargas de trabajo administrativas mencionadas anteriormente. En su lugar, te recomendamos que utilices una herramienta específica para la implementación de aplicaciones, como una herramienta de implementación continua, para que los equipos de aplicaciones puedan encargarse de su calendario de lanzamientos.

Config Sync es un producto potente que puede gestionar muchos elementos, por lo que necesitas medidas de protección para evitar errores que tengan un impacto importante. En este documento se describen varios métodos para crear medidas de protección. La primera sección trata las implementaciones graduales y la segunda se centra en las pruebas y validaciones. En la tercera sección se explica cómo monitorizar las implementaciones.

Implementar lanzamientos progresivos con Config Sync

En un entorno de varios clústeres, no recomendamos aplicar un cambio de configuración en todos los clústeres al mismo tiempo. Un lanzamiento gradual, clúster por clúster, es mucho más seguro porque reduce el impacto potencial de cualquier error.

Hay varias formas de implementar lanzamientos graduales con Config Sync:

  • Usa confirmaciones o etiquetas de Git para aplicar manualmente los cambios que quieras a los clústeres.
  • Usa ramas de Git para aplicar los cambios automáticamente cuando se combinen. Puedes usar diferentes ramas para distintos grupos de clústeres.
  • Usa los objetos ClusterSelector y NamespaceSelector para aplicar cambios de forma selectiva a subgrupos de clústeres o espacios de nombres.

Todos los métodos de lanzamiento progresivo tienen ventajas e inconvenientes. En la siguiente tabla se muestra cuáles de estos métodos puedes usar al mismo tiempo:

Compatibilidad Commits o etiquetas de Git Ramas de Git Selectores de clústeres Selectores de espacios de nombres
Commits o etiquetas de Git No es compatible Compatible Compatible
Ramas de Git No es compatible Compatible Compatible
Selectores de clústeres Compatible Compatible Compatible
Selectores de espacios de nombres Compatible Compatible Compatible

El siguiente diagrama de flujo de toma de decisiones puede ayudarte a decidir cuándo usar uno de los métodos de lanzamiento progresivo.

Árbol de decisiones para los métodos de lanzamiento.

Usar confirmaciones o etiquetas de Git

En comparación con los otros métodos de lanzamiento gradual, el uso de confirmaciones o etiquetas de Git es el más seguro y el que ofrece más control. Puedes usar la página Config Sync de la Google Cloud consola para actualizar varios clústeres al mismo tiempo. Usa este método si quieres aplicar cambios a tus clústeres uno a uno y controlar exactamente cuándo se producen.

En este método, "fijas" cada clúster a una versión específica (una confirmación o una etiqueta) de tu repositorio. Este método es similar a usar la confirmación de Git como etiqueta de imagen de contenedor. Para implementar este método, especifica la confirmación, la etiqueta o el hash en el campo spec.git.revision del RootSync o del RepoSync recurso personalizado.

Si gestionas tus recursos personalizados de RootSync o RepoSync con una herramienta como Kustomize, puedes reducir la cantidad de trabajo manual necesario para las implementaciones. Con esta herramienta, solo tienes que cambiar el parámetro revision en un lugar y, a continuación, aplicar de forma selectiva el nuevo recurso personalizado RootSync o RepoSync a tus clústeres en el orden y al ritmo que elijas.

Además, puedes usar la consola para actualizar el parámetro Google Cloud revision de varios clústeres que pertenezcan a la misma flota al mismo tiempo. Sin embargo, si tienes un sistema automatizado para actualizar tus configuraciones, no te recomendamos que uses la consola de Google Cloud para hacer cambios en la configuración. Google Cloud

Por ejemplo, la siguiente definición de RootSync configura Config Sync para usar la etiqueta 1.2.3:

apiVersion: configsync.gke.io/v1
kind: RootSync
metadata:
  name: root-sync
  namespace: config-sync-system
spec:
  sourceType: git
  sourceFormat: unstructured
  git:
    repo: git@example.com:gke/config-sync.git
    revision: 1.2.3
    auth: ssh

Si aplicas esta configuración a tu clúster, Config Sync usará la etiqueta 1.2.3 del repositorio example.com:gke/config-sync.git.

Para actualizar un clúster, cambia el campo spec.git.revision por el nuevo valor del clúster. De esta forma, puedes definir qué clústeres se actualizan y cuándo. Si necesitas deshacer un cambio, vuelve a cambiar el campo spec.git.revision a su valor anterior.

En el siguiente diagrama se ilustra el proceso de lanzamiento de este método. Primero, confirma los cambios en el repositorio de Config Sync y, después, actualiza las definiciones de RootSync en todos los clústeres:

Proceso de lanzamiento de confirmaciones y etiquetas de Git.

Te recomendamos que hagas lo siguiente:

  • Usa IDs de confirmación de Git en lugar de etiquetas. Debido a la forma en que funciona Git, tienes la garantía de que nunca cambiarán. Por ejemplo, un git push --force no puede cambiar el commit que usa Config Sync. Este método es útil para realizar auditorías y para hacer un seguimiento de la confirmación que estás usando en los registros. Además, a diferencia de las etiquetas, no es necesario realizar ningún paso adicional para confirmar los IDs.
  • Si prefieres usar etiquetas de Git en lugar de IDs de confirmación de Git, puedes proteger tus etiquetas si usas una solución de Git que admita la protección.
  • Si quieres actualizar varios clústeres a la vez, puedes hacerlo en la consola Google Cloud . Para actualizar varios clústeres a la vez, deben formar parte de la misma flota (y estar en el mismo proyecto).

Usar ramas de Git

Si quieres que los cambios se apliquen a los clústeres en cuanto se combinen en tu repositorio de Git, configura Config Sync para que use ramas de Git en lugar de confirmaciones o etiquetas. Con este método, se crean varias ramas de larga duración en el repositorio de Git y se configura Config Sync en diferentes clústeres para que lea su configuración de diferentes ramas.

Por ejemplo, un patrón sencillo tiene dos ramas:

  • Una rama staging para clústeres que no sean de producción.
  • Una rama main para los clústeres de producción.

En el caso de los clústeres que no son de producción, crea el objeto RootSync o RepoSync con el campo spec.git.branch definido como staging. En los clústeres de producción, crea el objeto RootSync o RepoSync con el parámetro spec.git.branch definido como main.

Por ejemplo, la siguiente definición de RootSync configura Config Sync para que use la rama main:

apiVersion: configsync.gke.io/v1
kind: RootSync
metadata:
  name: root-sync
  namespace: config-sync-system
spec:
  git:
    repo: git@example.com:gke/config-sync.git
    branch: main
    auth: ssh

En el siguiente diagrama se ilustra el proceso de lanzamiento de este método:

Proceso de lanzamiento de ramas de Git.

Puedes adaptar este patrón a necesidades específicas, usando más de dos ramas o ramas que se asignen a algo distinto de los entornos. Si necesitas deshacer un cambio, usa el comando git revert para crear una nueva confirmación en la misma rama que revierta los cambios de la confirmación anterior.

Te recomendamos que hagas lo siguiente:

  • Cuando trabajes con varios clústeres, usa al menos dos ramas de Git para distinguir entre los clústeres de producción y los que no lo son.
  • La mayoría de las soluciones de Git te permiten usar la función de ramas protegidas para evitar que se eliminen o se hagan cambios sin revisar en esas ramas. Para obtener más información, consulta la documentación de GitHub, GitLab y Bitbucket.

Usar objetos ClusterSelector y NamespaceSelector

Las ramas de Git son una buena forma de implementar cambios de forma gradual en varios clústeres que, al final, tendrán las mismas políticas. Sin embargo, si quieres implementar un cambio solo en un subconjunto de clústeres o de espacios de nombres, usa los objetos ClusterSelector y NamespaceSelector. Estos objetos tienen un objetivo similar: te permiten aplicar objetos solo a clústeres o espacios de nombres que tengan etiquetas específicas.

Por ejemplo:

  • Con los objetos ClusterSelector, puedes aplicar diferentes políticas a los clústeres en función del país en el que se encuentren para cumplir varios regímenes.
  • Si usas objetos NamespaceSelector, puedes aplicar diferentes políticas a los espacios de nombres que utilicen un equipo interno y un proveedor externo.

Los objetos ClusterSelector y NamespaceSelector también te permiten implementar metodologías de prueba y lanzamiento avanzadas, como las siguientes:

  • Lanzamientos canary de políticas, en los que se implementa una nueva política en un pequeño subconjunto de clústeres y espacios de nombres durante un periodo prolongado para estudiar el impacto de la política.
  • Pruebas A/B, en las que se implementan diferentes versiones de la misma política en distintos clústeres para estudiar el impacto de las versiones de la política y, a continuación, elegir la mejor para implementarla en todas partes.

Por ejemplo, imagina una organización con varios clústeres de producción. El equipo de la plataforma ya ha creado dos categorías de clústeres de producción, llamadas canary-prod y prod, mediante objetos Cluster y ClusterSelector (consulta Usar ClusterSelectors).

El equipo de la plataforma quiere implementar una política con Policy Controller para exigir que los espacios de nombres tengan una etiqueta de equipo. De esta forma, se podrá identificar a qué equipo pertenece cada espacio de nombres. Ya han implementado una versión de esta política en modo de prueba y ahora quieren aplicarla en un pequeño número de clústeres. Con los objetos ClusterSelector, crean dos K8sRequiredLabels recursos diferentes que se aplican a distintos clústeres.

  • El recurso K8sRequiredLabels se aplica a clústeres de tipo prod, con el parámetro enforcementAction definido como dryrun:

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sRequiredLabels
    metadata:
      name: ns-must-have-team
      annotations:
        configmanagement.gke.io/cluster-selector: prod
    Spec:
      enforcementAction: dryrun
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Namespace"]
      parameters:
        labels:
          - key: "team"
    
  • El recurso K8sRequiredLabels se aplica a clústeres de tipo canary-prod, sin el parámetro enforcementAction, lo que significa que la política se aplica realmente:

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sRequiredLabels
    metadata:
      name: ns-must-have-team
      annotations:
        configmanagement.gke.io/cluster-selector: canary-prod
    spec:
      match:
        kinds:
          - apiGroups: [""]
        kinds: ["Namespace"]
      parameters:
        labels:
          - key: "team"
    

La anotación configmanagement.gke.io/cluster-selector permite al equipo aplicar la política solo en clústeres de tipo canary-prod, lo que evita que se produzcan efectos secundarios no deseados en toda la flota de producción. Para obtener más información sobre la función de prueba de Policy Controller, consulta el artículo sobre creación de restricciones.

Te recomendamos que hagas lo siguiente:

  • Usa los objetos ClusterSelector y NamespaceSelector si necesitas aplicar un cambio de configuración solo a un subconjunto de clústeres o espacios de nombres de forma indefinida o durante un periodo prolongado.
  • Si implementas un cambio mediante selectores, ten mucho cuidado. Si usas confirmaciones de Git, cualquier error afectará solo a un clúster a la vez, ya que despliegas los clústeres uno a uno. Sin embargo, si usas ramas de Git, cualquier error puede afectar a todos los clústeres que usen esa rama. Si usas selectores, los errores pueden afectar a todos los clústeres a la vez.

Implementar revisiones, pruebas y validaciones

Una de las ventajas de Config Sync es que gestiona todo de forma declarativa: recursos de Kubernetes, recursos de la nube y políticas. Esto significa que los archivos de un sistema de gestión de control de versiones representan los recursos (archivos de Git en el caso de Config Sync). Esta característica te permite implementar flujos de trabajo de desarrollo que ya utilizas para el código fuente de una aplicación: revisiones y pruebas automatizadas.

Implementar reseñas

Como Config Sync se basa en Git, puedes usar la solución de Git que prefieras para alojar el repositorio de Config Sync. Es probable que tu solución de Git tenga una función de revisión de código que puedas usar para revisar los cambios realizados en el repositorio de Config Sync.

Las prácticas recomendadas para revisar los cambios en tu repositorio son las mismas que las de una revisión de código normal, tal como se indica a continuación:

Debido a la sensibilidad de la base de código de Config Sync, también te recomendamos que, si es posible con tu solución de Git, hagas las siguientes configuraciones:

Al usar estas funciones, puedes obligar a que se aprueben todas las solicitudes de cambio en tu base de código. Por ejemplo, puedes asegurarte de que cada cambio lo apruebe al menos un miembro del equipo de la plataforma (que gestiona la flota de clústeres) y un miembro del equipo de seguridad (que se encarga de definir e implementar las políticas de seguridad).

Te recomendamos que hagas lo siguiente:

  • Aplica revisiones entre pares en tu repositorio y protege las ramas de Git que usan tus clústeres.

Implementar pruebas automatizadas

Una práctica recomendada habitual al trabajar en una base de código es implementar la integración continua. Esto significa que configuras pruebas automatizadas para que se ejecuten cuando se cree o se actualice una solicitud de cambio. Las pruebas automatizadas pueden detectar muchos errores antes de que una persona revise la solicitud de cambio. De esta forma, el desarrollador recibe comentarios más rápido. Puedes implementar la misma idea con las mismas herramientas en el repositorio de Config Sync.

Por ejemplo, un buen punto de partida es ejecutar el comando nomos vet automáticamente cuando se produzcan cambios. Este comando valida que la sintaxis del repositorio de Config Sync sea válida. Puedes implementar esta prueba con Cloud Build siguiendo el tutorial sobre validación de configuraciones. Puedes integrar Cloud Build con las siguientes opciones:

  • Bitbucket, mediante activadores de compilación.
  • GitHub, mediante la aplicación de GitHub para Google Cloud Build. Los activadores de compilación también están disponibles para GitHub, pero la aplicación de GitHub es el método de integración preferido.

Como puedes ver en el tutorial sobre validación de configuraciones, la prueba se realiza mediante una imagen de contenedor. Por lo tanto, puedes implementar la prueba en cualquier solución de integración continua que ejecute contenedores, no solo en Cloud Build.

Para acortar aún más el bucle de comentarios, puedes pedir a los usuarios que ejecuten el comando nomos vet como un hook pre-commit de Git. Una de las desventajas es que es posible que algunos usuarios no tengan acceso a los clústeres de Kubernetes gestionados por Config Sync y que no puedan ejecutar la validación completa desde su estación de trabajo. Ejecuta el comando nomos vet --clusters "" para limitar la validación a comprobaciones semánticas y sintácticas.

Te recomendamos que hagas lo siguiente:

  • Implementa pruebas en un flujo de procesamiento de integración continua.
  • Ejecuta al menos el comando nomos vet en todos los cambios sugeridos.

Monitorizar lanzamientos

Aunque implementes todas las medidas de protección que se describen en este documento, pueden seguir produciéndose errores. A continuación, se indican dos tipos de errores habituales:

  • Errores que no suponen ningún problema para Config Sync, pero que impiden que tus cargas de trabajo funcionen correctamente. Por ejemplo, una política de red demasiado restrictiva que impide que los componentes de tu carga de trabajo se comuniquen.
  • Errores que impiden que Config Sync aplique cambios a un clúster, como un manifiesto de Kubernetes no válido o un objeto rechazado por un controlador de admisión. Con los métodos explicados anteriormente, se deberían detectar la mayoría de estos errores.

Detectar los errores descritos en el primer punto anterior es casi imposible a nivel de Config Sync, ya que requiere conocer el estado de cada una de tus cargas de trabajo. Por este motivo, la mejor forma de detectar estos errores es mediante el sistema de monitorización que ya tengas, que te avisa cuando una aplicación no funciona correctamente.

Para detectar los errores descritos en el segundo punto anterior (que deberían ser poco frecuentes si has implementado todas las medidas de protección), se necesita una configuración específica. De forma predeterminada, Config Sync escribe los errores en sus registros (que se encuentran en Cloud Logging). Los errores también se muestran en la página de la consola de Config Sync Google Cloud . Por lo general, ni los registros ni la consola son suficientes para detectar errores, ya que probablemente no los monitorices en todo momento. La forma más sencilla de automatizar la detección de errores es ejecutar el nomos status comando, que te indica si hay algún error en un clúster.

También puedes configurar una solución más avanzada con alertas automáticas de errores. Config Sync expone métricas en formato Prometheus. Para obtener más información, consulta el artículo sobre monitorizar Config Sync.

Una vez que tenga las métricas de Config Sync en su sistema de monitorización, cree una alerta para que le avise cuando la métrica gkeconfig_monitor_errors sea superior a 0. Para obtener más información, consulta cómo gestionar políticas de alertas en Cloud Monitoring o las reglas de alertas de Prometheus.

Resumen de los mecanismos para realizar despliegues seguros con Config Sync

En la siguiente tabla se resumen los distintos mecanismos que se han descrito anteriormente en este documento. Ninguno de estos mecanismos es exclusivo. Puedes usar algunos de ellos o todos con diferentes fines.

Mecanismo ¿Para qué sirve? Para qué no es adecuado Caso práctico de ejemplo
IDs de confirmación y etiquetas de Git Usa IDs o etiquetas de confirmación de Git específicos para controlar con precisión en qué clúster se aplican los cambios. No uses IDs ni etiquetas de confirmación de Git para diferencias duraderas entre clústeres. Usa selectores de clústeres. Todos tus clústeres están configurados para aplicar el 12345 Git commit. Haces un cambio con una nueva confirmación, abcdef, que quieres probar. Cambias la configuración de un solo clúster para usar esta nueva confirmación y validar el cambio.
Ramas de Git Usa varias ramas de Git cuando quieras implementar el mismo cambio en varios entornos, uno después de otro. No utilices varias ramas de Git para diferencias duraderas entre clústeres. Las ramas divergirán significativamente y será difícil volver a fusionarlas. Primero, combina el cambio en la rama de staging, donde lo recogerán los clústeres de staging.
A continuación, combina el cambio en la rama principal, donde lo recogerán los clústeres de producción.
Selectores de clústeres y selectores de espacios de nombres Usa selectores para las diferencias duraderas entre clústeres y espacios de nombres. No uses selectores para una implementación gradual en varios entornos. Si quieres probar una modificación primero en el entorno de pruebas y, después, implementarla en el entorno de producción, usa ramas de Git independientes. Si los equipos de aplicaciones necesitan acceso completo a los clústeres de desarrollo, pero acceso de solo lectura a los clústeres de producción, usa el objeto ClusterSelector para aplicar las políticas de RBAC correctas solo a los clústeres pertinentes.
Revisiones por pares Usa las revisiones de compañeros para asegurarte de que los equipos correspondientes aprueban los cambios. Los revisores humanos no detectan todos los errores, especialmente los de sintaxis. Tu organización exige que el equipo de seguridad revise los cambios de configuración que afecten a varios sistemas. Pide a un miembro del equipo de seguridad que revise los cambios.
Pruebas automatizadas en el flujo de procesamiento de integración continua Usa pruebas automatizadas para detectar errores en los cambios sugeridos. Las pruebas automatizadas no pueden sustituir por completo a un revisor humano. Usa ambas. Al ejecutar un comando nomos vet en todos los cambios sugeridos, se confirma que el repositorio es una configuración de Config Sync válida.
Monitorizar errores de sincronización Asegúrate de que Config Sync aplique los cambios a tus clústeres. Los errores de sincronización solo se producen si Config Sync intenta aplicar un repositorio no válido o si el servidor de la API de Kubernetes rechaza algunos de los objetos. Un usuario omite todas tus pruebas y revisiones, y confirma un cambio no válido en el repositorio de Config Sync. Este cambio no se puede aplicar a tus clústeres. Si monitorizas los errores de sincronización, recibirás una alerta si se produce un error.

Ejemplo de estrategia de lanzamiento

En esta sección se usan los conceptos presentados en el resto del artículo para ayudarte a crear una estrategia de lanzamiento integral en todos los clústeres de tu organización. Esta estrategia presupone que tienes flotas independientes para desarrollo, preproducción y producción (como se muestra en el ejemplo de flota 1: enfoque 1).

En este caso, configura cada clúster para que se sincronice con tu repositorio de Git mediante un commit de Git específico. Para implementar un cambio en una flota determinada, hay que seguir cuatro pasos:

  1. Primero, actualiza un solo clúster (el "canario") de la flota para que use la nueva confirmación.
  2. Para comprobar que todo funciona según lo previsto, realiza pruebas y monitoriza el lanzamiento.
  3. Actualiza el resto de los clústeres de la flota.
  4. Vuelve a validar que todo funciona correctamente.

Para implementar un cambio en todos tus clústeres, repite este proceso en cada flota. Técnicamente, puedes aplicar este método con cualquier commit de Git, desde cualquier rama. Sin embargo, te recomendamos que sigas este proceso para identificar los problemas en las primeras fases del proceso de revisión:

  1. Cuando alguien abra una solicitud de cambio en el repositorio Git de Config Sync, implementa ese cambio en uno de los clústeres de desarrollo.
  2. Si se acepta la solicitud de cambio y se combina en tu rama principal, ejecuta la implementación completa en todas las flotas, tal como se ha descrito anteriormente.

Aunque algunos cambios pueden estar dirigidos solo a una flota específica, te recomendamos que implementes todos los cambios en todas las flotas. Esta estrategia elimina el problema de hacer un seguimiento de qué flota debe sincronizarse con qué confirmación. Preste especial atención a los cambios que solo afecten a la flota de producción, ya que no se habrán podido probar correctamente en las flotas anteriores. Por ejemplo, esto significa que tendrás que esperar más tiempo para que aparezcan problemas entre el despliegue en los clústeres canary y en el resto de los clústeres.

En resumen, una implementación completa de principio a fin tiene este aspecto:

  1. Alguien abre una solicitud de cambio.
  2. Se realizan pruebas y validaciones automatizadas, así como una revisión manual.
  3. Activas una tarea manualmente para desplegar el cambio en el clúster canary de la flota de desarrollo. Las pruebas de extremo a extremo automatizadas se ejecutan en este clúster.
  4. Si todo está bien, combina la solicitud de cambio en la rama principal.
  5. La combinación activa un trabajo automatizado para implementar la nueva confirmación de la punta de la rama principal en el clúster canary de la flota de desarrollo. Las pruebas integrales automatizadas se ejecutan en este clúster para detectar posibles incompatibilidades entre dos solicitudes de cambio que se han creado y combinado aproximadamente al mismo tiempo.
  6. Los siguientes trabajos se ejecutan uno después del otro (puedes activarlos manualmente o después de un tiempo predefinido para permitir que los usuarios informen de regresiones):
    1. Implementar en todos los clústeres de la flota de desarrollo.
    2. Realiza pruebas y validaciones en los clústeres de la flota de desarrollo.
    3. Despliega en el clúster de lanzamiento de la flota de staging.
    4. Ejecuta pruebas y validaciones en el clúster de lanzamiento de la flota de staging.
    5. Implementar en todos los clústeres de la flota de staging.
    6. Ejecuta pruebas y validaciones en los clústeres de la flota de staging.
    7. Despliega la carga de trabajo en el clúster de pruebas de la flota de producción.
    8. Ejecuta pruebas y validaciones en el clúster de lanzamiento de la flota de producción.
    9. Implementar en todos los clústeres de la flota de producción.
    10. Realiza pruebas y validaciones en los clústeres de la flota de producción.

Proceso de lanzamiento completo.

Siguientes pasos