Creación de una canalización de CI/CD para microservicios en Kubernetes mediante Azure DevOps y Helm

La creación de un proceso confiable de integración continua y entrega continua (CI/CD) para una arquitectura de microservicios puede ser difícil. Cada equipo necesita liberar servicios de forma rápida y confiable, sin interrumpir a otros equipos ni desestabilizar la aplicación en su conjunto.

En este artículo se describe un ejemplo de canalización de CI/CD para implementar microservicios en Azure Kubernetes Service (AKS). Cada equipo y cada proyecto son diferentes, por lo que no debe tomar este artículo como un conjunto de reglas absolutas. En su lugar, úselo como punto de partida para diseñar su propio proceso de CI/CD.

En la lista siguiente se resumen los objetivos de una canalización de CI/CD para microservicios hospedados en Kubernetes:

  • Los equipos pueden compilar e implementar sus servicios de manera independiente.
  • Cambios de código que pasan el proceso de CI se implementan automáticamente en un entorno similar a producción.
  • Cada etapa del pipeline aplica controles de calidad.
  • Una nueva versión de un servicio se puede implementar en paralelo con la versión anterior.

Para obtener más información, consulte CI/CD para arquitecturas de microservicios.

Supuestos

Para este ejemplo, estas son algunas suposiciones sobre el equipo de desarrollo y la base de código:

  • El repositorio de código es un repositorio único y sus carpetas están organizadas por microservicio.
  • La estrategia de ramificación del equipo se basa en el desarrollo basado en el tronco.
  • El equipo utiliza ramas de versión para administrar las versiones. Se crean versiones independientes para cada microservicio.
  • El proceso de CI/CD usa Azure Pipelines para compilar, probar e implementar los microservicios en AKS.
  • Las imágenes de contenedor de todos los microservicios se almacenan en una única instancia de Azure Container Registry compartida, con un repositorio independiente para cada microservicio. Utiliza los permisos del repositorio ABAC de Azure Container Registry para limitar cada identidad del pipeline a su propio repositorio, o utiliza registros independientes cuando se requieran límites de confianza más estrictos.
  • El equipo usa gráficos de Helm para empaquetar cada microservicio.
  • Se usa un modelo de implementación de inserción, donde Azure Pipelines y los agentes asociados realizan implementaciones mediante la conexión directa al clúster de AKS.

Estas suposiciones guían muchos de los detalles específicos de la canalización de CI/CD. Sin embargo, puede adaptar el enfoque básico que se describe aquí para otros procesos, herramientas y servicios, como Acciones de GitHub, Jenkins o Docker Hub.

Alternatives

Al elegir una estrategia de CI/CD con AKS, tenga en cuenta las siguientes alternativas comunes:

  • En lugar de usar Helm como una herramienta de implementación y administración de paquetes, puede usar Kustomize, una herramienta de administración de configuración nativa de Kubernetes que introduce una manera sin plantilla de personalizar y parametrizar la configuración de la aplicación.

  • En lugar de usar Azure DevOps para repositorios Git y canalizaciones, puede usar repositorios de GitHub para repositorios Git privados y públicos, y Acciones de GitHub para canalizaciones de CI/CD.

    Acciones de GitHub proporciona integración con AKS con flujos de trabajo de inicio y admite OpenID Connect (OIDC) para la autenticación segura y sin secretos para Azure.

  • En lugar de usar un modelo de despliegue push, considere la posibilidad de administrar la configuración de Kubernetes a gran escala usando GitOps (modelo de despliegue pull). Un operador de Kubernetes en clúster como Flux o Argo CD sincroniza el estado del clúster en función de la configuración almacenada en un repositorio de Git. GitOps elimina la necesidad de que las canalizaciones tengan acceso directo al clúster, reduce la superficie expuesta a ataques y proporciona funcionalidades de detección de desfase y recuperación automática.

    Tip

    A la hora de evaluar los modelos de implementación basados en push frente a los basados en pull (GitOps), tenga en cuenta los requisitos de su carga de trabajo. Los despliegues de tipo push ofrecen actualizaciones deterministas y control directo del pipeline, lo que se ajusta bien a las prácticas de despliegue seguras. Las implementaciones basadas en pull (GitOps) ofrecen coherencia, auditabilidad y autorreparación, lo que las hace ideales para entornos en los que los clústeres deben reconciliarse con un estado deseado sin acceso directo del canal al clúster.

Compilaciones de validación

Supongamos que un desarrollador está trabajando en un microservicio denominado Delivery Service. Al desarrollar una nueva característica, el desarrollador comprueba el código en una rama de características. Por convención, las ramas de funcionalidades se denominan feature/*.

Diagrama del flujo de trabajo de una rama de funcionalidad.

En el diagrama se muestran dos líneas de rama horizontales de Git y una canalización de compilación debajo de ellas. En la parte superior se encuentra la rama principal, representada como una línea horizontal. La rama feature/8150 se diferencia de main. Esta rama tiene tres puntos situados en ella, denominados colectivamente «commits». Desde cada una de las tres confirmaciones, una flecha apunta hacia abajo, hacia un recuadro situado en la parte inferior del diagrama. El recuadro lleva la etiqueta Pipeline de compilación y contiene el nombre del pipeline: ci-delivery-validation. Las tres flechas discontinuas convergen en este único bloque del pipeline de compilación, lo que indica que cada commit en la rama feature/8150 activa una ejecución del pipeline ci-delivery-validation.

El archivo de definición de compilación incluye un trigger que filtra por el nombre de rama y la ruta de origen.

trigger:
  batch: true
  branches:
    include:
    # for new release to production: release flow strategy
    - release/delivery/v*
    - refs/release/delivery/v*
    - main
    - feature/delivery/*
    - topic/delivery/*
  paths:
    include:
    - /src/shipping/delivery/

Cuando se usa este enfoque, cada equipo puede tener su propia canalización de compilación. Solo el código que se registra en la carpeta /src/shipping/delivery activa una compilación de Delivery Service. La inserción de confirmaciones en una rama que coincide con el filtro desencadena una compilación de CI. En este punto del flujo de trabajo, la compilación de CI ejecuta una comprobación mínima del código:

  1. Compilación del código.
  2. Ejecución de pruebas unitarias.

El objetivo es que las compilaciones tarden poco en completarse, para que el desarrollador pueda obtener comentarios rápidamente. Cuando la funcionalidad está lista para integrarse en main, el desarrollador abre una PR. Esta operación desencadena otra compilación (o construcción) de CI que realiza algunas verificaciones adicionales:

  1. Compilación del código.
  2. Ejecución de pruebas unitarias.
  3. Ejecute pruebas estáticas de seguridad de aplicaciones (SAST) en el código fuente.
  4. Compilación de la imagen de contenedor en tiempo de ejecución.
  5. Ejecución de exámenes de vulnerabilidades en la imagen.

Diagrama en el que se muestra ci-delivery-full en la canalización de compilación.

En el diagrama se muestran dos líneas de rama horizontales de Git y una canalización de compilación debajo de ellas. En la parte superior se encuentra la rama principal, representada como una línea horizontal. Por debajo, la rama feature/8150 va en paralelo a ella y tiene tres puntos en ella que representan commits. En el extremo derecho de la rama feature/8150, una flecha discontinua conecta con un punto de la rama principal. Ese punto está marcado con otro punto etiquetado como PR, lo que indica que se ha abierto una solicitud de incorporación de cambios (pull request) en la rama principal. Desde el punto PR de la rama principal, una flecha discontinua apunta hacia abajo a un recuadro etiquetado como Pipeline de compilación, que contiene el nombre del pipeline ci-delivery-full. En esta línea se muestra que al abrir una solicitud de incorporación de cambios de la rama de características a main se desencadena la canalización ci-delivery-full, que ejecuta el conjunto extendido de comprobaciones de CI.

Nota:

En Azure Repos, uno de los servicios de Azure DevOps, puedes definir políticas para proteger las ramas. Por ejemplo, la política podría requerir una compilación de CI completada correctamente y la aprobación de un revisor antes de una fusión en la rama main.

Compilación de CI/CD completa

Cuando el equipo esté listo para implementar una nueva versión de Delivery Service, el administrador de versiones crea una rama desde la rama principal, con este patrón de nomenclatura: release/<microservice name>/<semver>. Por ejemplo: release/delivery/v1.0.2.

Diagrama que muestra una rama de lanzamiento que desencadena una canalización de compilación seguida de una canalización de lanzamiento.

La creación de esta rama desencadena una compilación de CI completa que ejecuta todos los pasos anteriores y estos pasos:

  1. Inserte la imagen de contenedor en Container Registry. La imagen se etiqueta con el número de versión en el nombre de la rama.
  2. Ejecución de helm package para empaquetar el gráfico de Helm para el servicio. El gráfico también se etiqueta con un número de versión.
  3. Inserción del paquete de Helm en Container Registry.

Si esta compilación se realiza con éxito, se activa un proceso de implementación (CD) mediante un pipeline de lanzamiento de Azure Pipelines. Esta canalización contiene los pasos siguientes:

  1. Implementación del gráfico de Helm en un entorno de control de calidad.
  2. Un aprobador cierra sesión antes de que el paquete pase a producción. Consulte Release deployment control using approvals (Liberación del control de implementación mediante aprobaciones).
  3. Vuelva a etiquetar la imagen de Docker para el espacio de nombres de producción en Container Registry. Por ejemplo, si la etiqueta actual es myrepo.azurecr.io/delivery:v1.0.2, la etiqueta de producción es myrepo.azurecr.io/prod/delivery:v1.0.2.
  4. Implementación del gráfico de Helm en el entorno de producción.

Incluso en un monorepo, limite estas tareas a cada microservicio para que los equipos puedan desplegar de forma independiente. El proceso incluye algunos pasos manuales: aprobar las PR, crear ramas de lanzamiento y aprobar los despliegues en el clúster de producción. Los equipos de cargas de trabajo pueden automatizar estos pasos si quieren.

Aislamiento de los entornos

Los servicios se implementan en varios entornos, incluidos los entornos para desarrollo, pruebas de humo, pruebas de integración, pruebas de carga y producción. Estos entornos necesitan cierto nivel de aislamiento. En Kubernetes, puede elegir entre el aislamiento físico y el aislamiento lógico. El aislamiento físico se implementa en clústeres independientes. El aislamiento lógico utiliza espacios de nombres y políticas.

Nuestra recomendación es crear un clúster de producción dedicado junto con un clúster independiente para los entornos de desarrollo y pruebas. Use el aislamiento lógico para separar los entornos dentro del clúster de desarrollo y pruebas. Los servicios implementados en el clúster de desarrollo y pruebas nunca deben tener acceso a almacenes de datos que contengan datos empresariales.

Para aplicar el aislamiento dentro de un clúster, siga estos pasos:

Autenticación y autorización

Use la autenticación sin secreto siempre que sea posible, tanto para las canalizaciones que implementan los microservicios como para las cargas de trabajo que implementan esas canalizaciones:

  • Federación de identidades de carga de trabajo para pipelines: En Azure Pipelines, utiliza una conexión de servicio de federación de identidades de carga de trabajo para autenticarte en Azure sin almacenar secretos de entidades de servicio de larga duración. Para Acciones de GitHub, configure OIDC para lograr la misma autenticación sin secretos.
  • Id. de carga de trabajo de Microsoft Entra para cargas de trabajo implementadas: configure los microservicios que implementa la canalización para usar Id. de carga de trabajo de Microsoft Entra en lugar de insertar credenciales a través de manifiestos, valores de Helm o secretos de Kubernetes. Workload ID federa las cuentas de servicio de Kubernetes con Microsoft Entra ID para que los pods puedan autenticarse en los servicios de Azure (como Azure Key Vault, Container Registry o Azure SQL) sin que la canalización tenga que administrar ningún secreto.

Administración de secretos

Nunca inserte secretos (cadenas de conexión, claves de API, contraseñas de base de datos) directamente en código fuente, Dockerfiles, archivos de valores de Helm o definiciones de canalización. En lugar de:

Importante

Evite almacenar credenciales de larga duración (secretos de cliente, certificados o contraseñas) en variables de canalización, variables de entorno o secretos de Kubernetes. En su lugar, use identidades administradas y credenciales federadas para reducir la carga de rotación de credenciales y la superficie expuesta a ataques.

Proceso de construcción

Cuando sea posible, empaquete el proceso de compilación en un contenedor de Docker. Esta configuración permite compilar artefactos de código mediante Docker sin configurar un entorno de compilación en cada máquina de compilación. Un proceso de compilación en contenedores simplifica el escalado horizontal del pipeline de CI mediante la adición de nuevos agentes de compilación. Además, cualquier desarrollador del equipo puede compilar el código ejecutando el contenedor de compilación.

Mediante el uso de compilaciones de varias fases en Docker, puede definir el entorno de compilación y la imagen en tiempo de ejecución en un único Dockerfile. Por ejemplo, el siguiente Dockerfile compila una aplicación de .NET 10:

FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
USER app
WORKDIR /app
EXPOSE 8080

FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src/Fabrikam.Workflow.Service

COPY Fabrikam.Workflow.Service/Fabrikam.Workflow.Service.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.csproj

COPY Fabrikam.Workflow.Service/. .
RUN dotnet build Fabrikam.Workflow.Service.csproj -c Release -o /app/build --no-restore

FROM build AS testrunner
WORKDIR /src/tests

COPY Fabrikam.Workflow.Service.Tests/*.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.Tests.csproj

COPY Fabrikam.Workflow.Service.Tests/. .
ENTRYPOINT ["dotnet", "test", "--logger:trx"]

FROM build AS publish
RUN dotnet publish Fabrikam.Workflow.Service.csproj -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Fabrikam.Workflow.Service.dll"]

Este Dockerfile define varias fases de compilación. Tenga en cuenta que la fase denominada base usa la imagen de runtime de ASP.NET para .NET 10, mientras que la fase denominada build usa el SDK completo de .NET 10. La build etapa compila el proyecto .NET. No obstante, el contenedor final en tiempo de ejecución se crea a partir de base, que solo contiene el tiempo de ejecución y es significativamente menor que la imagen completa del SDK.

Importante

A partir de .NET 8, las imágenes de contenedor de .NET basadas en Linux oficiales incluyen un usuario no raíz llamado app. La USER app instrucción del Dockerfile ejecuta el contenedor como este usuario sin privilegios, siguiendo el principio de privilegios mínimos. Las imágenes de contenedor de ASP.NET Core también cambiaron su puerto de escucha predeterminado de 80 a 8080.

Construcción de un Test Runner

Otro procedimiento recomendado es ejecutar pruebas unitarias en el contenedor. Por ejemplo, el código siguiente muestra parte de un Dockerfile que compila un ejecutor de pruebas:

FROM build AS testrunner
WORKDIR /src/tests

COPY Fabrikam.Workflow.Service.Tests/*.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.Tests.csproj

COPY Fabrikam.Workflow.Service.Tests/. .
ENTRYPOINT ["dotnet", "test", "--logger:trx"]

Un desarrollador puede usar este Dockerfile para ejecutar las pruebas localmente:

docker build . -t delivery-test:1 --target=testrunner
docker run delivery-test:1

La canalización de CI también debe ejecutar las pruebas como parte del paso de comprobación de la compilación.

Este archivo usa el comando docker ENTRYPOINT , no el comando docker RUN , para ejecutar las pruebas.

  • Si usa el comando RUN, las pruebas se ejecutan cada vez que se compila la imagen. Si utiliza ENTRYPOINT, las pruebas son opcionales. Solo se ejecutan cuando se dirige explícitamente a la fase testrunner.
  • Una prueba con errores no hace que se produzca un error en el comando Docker build. Este comportamiento permite distinguir los errores de compilación del contenedor de los errores de prueba.
  • Los resultados de las pruebas se pueden guardar en un volumen montado.

Mejores prácticas de contenedores

Estos son otros procedimientos recomendados que se deben tener en cuenta para los contenedores:

  • Defina convenciones de toda la organización para etiquetas de contenedor, control de versiones y convenciones de nomenclatura para los recursos implementados en el clúster (por ejemplo, pods y servicios). El uso de estas convenciones puede facilitar el diagnóstico de problemas de implementación.
  • Durante el ciclo de desarrollo y prueba, el proceso de CI/CD compila muchas imágenes de contenedor. Solo algunas de esas imágenes son candidatas a lanzamiento, y solo algunas de esas candidatas a lanzamiento pasan a producción. Tenga una estrategia clara de control de versiones para que sepa qué imágenes se implementan actualmente en producción y puede revertir fácilmente a una versión anterior si es necesario.
  • Implemente siempre etiquetas de versión de contenedor específicas, no latest.
  • Use espacios de nombres en Container Registry para aislar las imágenes aprobadas para producción de imágenes que todavía se están probando. No mueva una imagen al espacio de nombres de producción hasta que esté listo para implementarla en producción. Combinar esta práctica con el versionado semántico de las imágenes de contenedores puede reducir las probabilidades de desplegar accidentalmente una versión que no esté aprobada para su publicación.
  • Siga el principio de privilegios mínimos mediante la ejecución de contenedores como un usuario sin privilegios. En Kubernetes, usa Pod Security Standards con Pod Security admission (que sustituyó a las Pod Security Policies obsoletas en Kubernetes 1.25) para aplicar restricciones, como impedir que los contenedores se ejecuten como usuario root. Use el perfil restricted para cargas de trabajo de producción.
  • Utilice imágenes base mínimas o sin distribución (por ejemplo, imágenes basadas en Alpine, imágenes base de Azure Linux o sin distribución, o imágenes .NET optimizadas) para reducir la superficie de ataque de sus imágenes de contenedor.
  • En los registros Premium, configure una directiva de retención del registro de contenedores para eliminar los manifiestos no etiquetados. Para purgar etiquetas por edad o nombre, programe una tarea de Container Registry que ejecute acr purge. Conserve las imágenes a las que hacen referencia las implementaciones activas y los planes de reversión.

Gráficos de Helm

Considere el uso de Helm para administrar la creación e implementación de servicios. Las siguientes características de Helm admiten una canalización de CI/CD:

  • A menudo, varios objetos de Kubernetes definen un solo microservicio. Helm permite empaquetar estos objetos en un único gráfico de Helm.
  • Puede implementar un gráfico mediante un único comando de Helm en lugar de una serie de comandos kubectl.
  • Los gráficos tienen versiones explícitas. Use Helm para publicar una versión, ver versiones y revertir a una versión anterior. Helm usa el versionado semántico para hacer un seguimiento de las actualizaciones y las revisiones.
  • Los gráficos de Helm usan plantillas para evitar la duplicación de información, como etiquetas y selectores, en muchos archivos.
  • Helm puede administrar dependencias entre gráficos.
  • Puede almacenar gráficos en un repositorio de Helm, como Container Registry, e integrarlos en la canalización de compilación.

Para más información, consulte Usar Container Registry como repositorio de Helm para los gráficos de su aplicación.

Un único microservicio puede requerir varios archivos de configuración de Kubernetes. Para actualizar un servicio, es posible que tenga que editar todos estos archivos para actualizar los selectores, las etiquetas y las etiquetas de imagen. Helm trata estos archivos como un único paquete denominado gráfico y facilita la actualización de los archivos YAML mediante variables. Helm usa un lenguaje de plantilla (basado en plantillas de Go) que permite escribir archivos de configuración yaML con parámetros.

Por ejemplo, a continuación se muestra una parte de un archivo YAML que define una implementación:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "package.fullname" . | replace "." "" }}
  labels:
    app.kubernetes.io/name: {{ include "package.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
  annotations:
    kubernetes.io/change-cause: {{ .Values.reason }}

...

spec:
  template:
    spec:
      containers:
      - name: &package-container_name fabrikam-package
        image: {{ .Values.dockerregistry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        env:
        - name: LOG_LEVEL
          value: {{ .Values.log.level }}

Puede ver que el nombre de implementación, las etiquetas y la especificación de contenedor usan todos los parámetros de plantilla, que se proporcionan en el momento de la implementación. Por ejemplo, desde la línea de comandos:

helm install <release-name> oci://<registry>/<repository>/<package-chart-name> --version <desiredVersion> \
     --set image.tag=0.1.0 \
     --set image.repository=package \
     --set dockerregistry=$ACR_SERVER \
     --namespace backend

Aunque un proceso de CI/CD puede instalar un gráfico directamente en Kubernetes, crea un archivo del gráfico (archivo .tgz) y envíalo a un repositorio de Helm, como Container Registry. Para obtener más información, consulte Empaquetar e implementar gráficos de Helm (tarea HelmDeploy).

Revisions

Los gráficos de Helm siempre tienen un número de versión que debe usar el control de versiones semántico. Un gráfico también puede tener un elemento appVersion. Este campo es opcional y no es necesario estar relacionado con la versión del gráfico. Es posible que algunos equipos quieran versionar las aplicaciones por separado de las actualizaciones de los gráficos. Un enfoque más sencillo es usar un número de versión, por lo que hay una relación 1:1 entre la versión del gráfico y la versión de la aplicación. De este modo, puede almacenar un gráfico por versión e implementar fácilmente la versión deseada:

helm install <package-chart-name> --version <desiredVersion>

Otro procedimiento recomendado es proporcionar una anotación de causa del cambio en la plantilla de implementación:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "delivery.fullname" . | replace "." "" }}
  labels:
     ...
  annotations:
    kubernetes.io/change-cause: {{ .Values.reason }}

Esta anotación permite ver el campo de causa de cambios para cada revisión mediante el kubectl rollout history comando . En el ejemplo anterior, la causa del cambio se proporciona como parámetro de gráfico de Helm.

kubectl rollout history deployments/delivery-v010 -n backend
deployment.apps/delivery-v010
REVISION  CHANGE-CAUSE
1         Initial deployment

También puede usar el comando helm list para ver el historial de revisiones:

helm list -n backend
NAME              NAMESPACE   REVISION    UPDATED                                 STATUS      CHART               APP VERSION
delivery-v0.1.0   backend     1           2024-04-07 00:25:30.000000 +0000 UTC    deployed    delivery-v0.1.0     v0.1.0

Azure Pipelines

Azure Pipelines, un servicio en Azure DevOps, tiene dos tipos de canalización: canalizaciones de compilación y canalizaciones de versión. La canalización de compilación ejecuta el proceso de CI y crea artefactos de compilación. En el caso de una arquitectura de microservicios en Kubernetes, estos artefactos son las imágenes de contenedor y los gráficos de Helm que definen cada microservicio. El pipeline de lanzamiento ejecuta el proceso de CD que despliega un microservicio en un clúster.

Según el flujo de CI descrito anteriormente en este artículo, una canalización de compilación puede constar de las siguientes tareas:

  1. Construya el contenedor del ejecutor de pruebas con la tarea Docker.
  2. Ejecute las pruebas invocando docker run contra el contenedor del ejecutor de pruebas mediante la tarea Docker.
  3. Publique los resultados de la prueba mediante la PublishTestResults tarea . Para obtener más información, consulte Compilación de una imagen.
  4. Ejecute SAST en el código fuente.
  5. Genere el contenedor de entorno de ejecución usando docker build local y la tarea Docker, o bien mediante compilaciones de Container Registry y la tarea AzureCLI. Genere una lista de materiales de software (SBOM) para la imagen, por ejemplo, mediante el uso de la herramienta SBOM de Microsoft y publíquela como un artefacto de canalización asociado al resumen de imagen o adjunte a la imagen en Container Registry.
  6. Ejecute el examen de vulnerabilidades de la imagen de contenedor (por ejemplo, mediante Microsoft Defender para contenedores o una herramienta que no sea de Microsoft, como Trivy) para detectar vulnerabilidades conocidas antes de publicar la imagen.
  7. Envíe la imagen de contenedor a Container Registry (o cualquier otro registro de contenedores) mediante la tarea Docker o AzureCLI.
  8. Firma la imagen enviada mediante un resumen inmutable para garantizar su integridad y autenticidad. En Azure Pipelines, siga la guía de firma de Notation.
  9. Empaquetar el gráfico de Helm mediante la HelmDeploy tarea .
  10. Publique el paquete de Helm en Container Registry (u otro repositorio de Helm) mediante la tarea HelmDeploy.

La salida de la canalización de CI es una imagen de contenedor lista para producción y un gráfico de Helm actualizado para el microservicio. En este punto, la canalización de versión puede asumir el control. Cada microservicio tiene un proceso de publicación único. El canal de lanzamiento está configurado con una fuente de activación establecida en el canal de CI que publicó el artefacto. Esta canalización le permite implementar cada microservicio de forma independiente. La canalización de versión realiza los pasos siguientes:

  1. Implementar el gráfico de Helm en entornos de desarrollo, control de calidad y ensayo. Puede usar el helm upgrade comando con la --install marca para admitir la primera instalación y las actualizaciones posteriores.
  2. Esperar que un aprobador apruebe o rechace la implementación.
  3. Vuelve a etiquetar la imagen del contenedor para su lanzamiento.
  4. Insertar la etiqueta de versión en el registro de contenedor.
  5. Implementar el gráfico de Helm en el clúster de producción. Utiliza Ratify con Azure Policy para validar las firmas de las imágenes durante la admisión y configura por separado una directiva de imágenes permitidas para restringir las imágenes a registros de confianza.

Nota:

Para permitir que AKS extraiga imágenes de Container Registry sin secretos independientes para extraer imágenes, use la integración de AKS con Container Registry para un registro que use RBAC en todo el registro. En el caso de un registro habilitado para ABAC, esta integración no se admite. En su lugar, asigne el rol Container Registry Repository Reader a la identidad administrada por kubelet del clúster.

Para obtener más información sobre la creación de un flujo de trabajo de versiones, consulte Flujos de trabajo de versiones, versiones de borrador y opciones de versiones.

En el diagrama siguiente se muestra el proceso de CI/CD de un extremo a otro que se describe en este artículo:

Diagrama de la canalización de CI/CD de un extremo a otro.

El diagrama muestra el pipeline completo de CI/CD desde un commit del desarrollador hasta el despliegue en producción. A la izquierda, comienza con un desarrollador que inserta una confirmación en un repositorio de Git. El repositorio de Git desencadena la primera canalización de CI. El pipeline de CI contiene seis pasos secuenciales: Compilar el código, ejecutar las pruebas unitarias, construir la imagen, publicar la imagen, empaquetar con Helm y publicar el chart. Cada uno de los tres primeros pasos tiene un cuadro de salida correspondiente a su derecha: El código de compilación genera artefactos de código, Ejecutar pruebas unitarias genera resultados de prueba y la imagen de compilación genera una imagen de contenedor. El paso Insertar imagen inserta la imagen en Container Registry. El paso de empaquetado de Helm genera un archivo del chart. El paso Insertar gráfico inserta el gráfico en un repositorio de Helm. Una segunda canalización de CI está por debajo de la primera. Contiene cinco pasos secuenciales: Desplegar en QA, pruebas de integración, volver a etiquetar la imagen, publicar la imagen y desplegar en producción. Desde el paso Desplegar en QA, una línea etiquetada como Helm upgrade lleva a un clúster de Kubernetes etiquetado como «test/QA cluster». A la izquierda, debajo del desarrollador, una línea conduce desde un icono del aprobador de QA al paso Implementar en producción. Esta línea está etiquetada como aprobado. En el paso Implementar en producción, una línea etiquetada como Actualización de Helm conduce a un segundo icono de clúster de Kubernetes con la etiqueta clúster de producción.

alternativa a Acciones de GitHub

Si el equipo usa GitHub para el control de código fuente, Acciones de GitHub proporciona una plataforma de CI/CD equivalente. Además de los flujos de trabajo de inicio y la autenticación de OIDC que se han indicado anteriormente, tenga en cuenta estas funcionalidades específicas de GitHub al dirigirse a AKS:

  • Entornos y reglas de protección. Si su plan de GitHub y la visibilidad del repositorio lo permiten, use entornos de GitHub con revisores obligatorios, temporizadores de espera y ramas de implementación para aplicar controles de aprobación.
  • Examen de contenedores. Use las acciones de Acciones de GitHub Marketplace para Trivy, Microsoft Defender para DevOps o herramientas similares para el análisis de imágenes de contenedor directamente en su flujo de trabajo.

Observabilidad y supervisión

Implemente la observabilidad en toda la canalización de CI/CD y el entorno de tiempo de ejecución:

  • Supervisión de canalizaciones. Realiza un seguimiento de la duración de las compilaciones, las tasas de superación de pruebas, la frecuencia de implementación y las tasas de fallo. Azure DevOps proporciona análisis integrados. Acciones de GitHub pueden usar paneles que no son de Microsoft.
  • Supervisión en tiempo de ejecución. Utilice el servicio administrado de Azure Monitor para Prometheus y Azure Managed Grafana para supervisar el estado del clúster de AKS y las métricas de la carga de trabajo.
  • Telemetría de la aplicación. Instrumente los microservicios con Azure Monitor Application Insights para el seguimiento distribuido, el registro de solicitudes y el seguimiento de dependencias.
  • Alertas. Configure alertas para fallos de implementación, reinicios de pods, tasas de error elevadas y saturación de recursos para permitir una respuesta rápida ante incidentes.

alineación con Well-Architected Framework

Al diseñar la canalización de CI/CD para microservicios en Kubernetes, tenga en cuenta los pilares de Azure Well-Architected Framework:

Fundamento Considerations
Reliability Estrategias de reversión automática, sondas de estado en los despliegues, estrategias de despliegue blue-green o canary, presupuestos de interrupción de pods.
Security Autenticación sin secretos (Id. de carga de trabajo, OIDC), firma de imágenes, seguridad de la cadena de suministro, RBAC con privilegios mínimos, directivas de red.
Optimización de costos Ajustar correctamente el tamaño de los agentes de compilación, usar ejecutores autohospedados efímeros, implementar directivas de retención de imágenes de Container Registry y usar grupos de nodos de tipo spot solo para cargas de trabajo no productivas tolerantes a interrupciones.
Excelencia operativa GitOps para despliegues declarativos, infraestructura como código, canalizaciones como código (YAML), observabilidad y automatización de procedimientos operativos.
Eficiencia del rendimiento Fases de canalización paralelas, almacenamiento en caché de compilación (almacenamiento en caché de capas de Docker, almacenamiento en caché de dependencias), escalado automático horizontal de pods.

Contributors

Microsoft mantiene este artículo. Los siguientes colaboradores escribieron este artículo.

Autor principal:

  • Ray Kao | Ingeniero principal de soluciones

Para ver los perfiles no públicos de LinkedIn, inicie sesión en LinkedIn.

Pasos siguientes