Compartir a través de


Recursos de Kubernetes en entornos

Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022

En este artículo se describe el uso de recursos de Kubernetes en entornos de Azure Pipelines donde puede dirigir implementaciones. Puede conectarse a clústeres de Kubernetes públicos o privados en Azure Kubernetes Service (AKS) u otros proveedores de nube.

Las vistas de recursos del entorno muestran el estado de los recursos de Kubernetes y proporcionan rastreabilidad hacia el flujo de trabajo y de vuelta al commit que lo desencadenó. También puede crear recursos dinámicos del entorno de Kubernetes para revisar las solicitudes de incorporación de cambios antes de la combinación. Para obtener más información sobre los recursos del entorno, consulte Recursos en canalizaciones de YAML y Seguridad de recursos.

Nota:

Un clúster de AKS privado no expone su punto de conexión del servidor de API a través de una dirección IP pública, por lo que debe conectarse a la red virtual del clúster. Puede configurar un agente autohospedado dentro de una red virtual que pueda acceder a la red virtual del clúster o usar grupos de DevOps administrados. Para obtener más información, consulte Opciones para conectarse a un clúster privado.

Ventajas de los recursos del entorno de Kubernetes

Los recursos del entorno de Kubernetes y las vistas de recursos en entornos proporcionan las siguientes ventajas:

  • Rastreabilidad de tubería. La tarea de implementación de manifiestos de Kubernetes agrega anotaciones que admiten la rastreabilidad de la canalización. Puede ver la organización, el proyecto y la canalización de Azure DevOps responsables de actualizar los objetos dentro del espacio de nombres.

    Captura de pantalla que muestra el rastreo de la tubería para un clúster de Kubernetes.

  • Diagnósticos de estado de recursos. La vista de estado de la carga de trabajo es una manera rápida de depurar errores o regresiones introducidos por nuevas implementaciones. ** Por ejemplo, la información de estado del pod puede ayudarle a identificar la causa de problemas como imagePullSecrets no configurado que resulta en errores ImagePullBackOff.

    Captura de pantalla que muestra la vista de estado de la carga de trabajo para una implementación de Kubernetes.

  • Revisar la aplicación. La aplicación de revisión implementa todas las solicitudes de incorporación de cambios del repositorio de Git en un recurso dinámico de Kubernetes en el entorno y publica un comentario de GitHub que vincula a la aplicación de revisión. Los revisores pueden ver cómo se ven los cambios del PR y trabajar con otros servicios dependientes antes de que los cambios se combinen en la rama de destino y se implementen en producción.

    Captura de pantalla que muestra el comentario de la aplicación Review en GitHub.

Recursos de AKS

AKS crea una instancia de ServiceAccount en el clúster y el espacio de nombres elegido, y asigna los recursos de Kubernetes en el entorno al espacio de nombres especificado. Para obtener información sobre cómo configurar una conexión de servicio de Kubernetes fuera de un entorno, consulte Conexión de servicio de Kubernetes.

En el caso de un clúster habilitado para el control de acceso basado en rol (RBAC) de Kubernetes, RoleBinding también se crea para limitar el ámbito de la cuenta de servicio al espacio de nombres elegido. En el caso de un clúster de Kubernetes con RBAC deshabilitado, la cuenta de servicio creada tiene privilegios a nivel de clúster a través de los espacios de nombres.

Para agregar un recurso de AKS a un entorno de Azure Pipelines:

  1. En la página del entorno, en Entornos de canalizaciones>, seleccione Agregar recurso y, después, Kubernetes.

  2. En la siguiente pantalla, seleccione Azure Kubernetes Service para el proveedor y, a continuación, seleccione la suscripción de Azure, el clúster de AKS y el espacio de nombres nuevo o existente. Para un nuevo espacio de nombres, escriba el nombre del espacio de nombres.

  3. Seleccione Validar y crear. El nuevo recurso aparece en la pestaña Recursos del entorno con el texto Nunca implementado.

    Captura de pantalla que muestra un recurso de Kubernetes agregado.

Recursos de Kubernetes que no son de AKS

Para asignar un recurso de Kubernetes desde un clúster que no es de AKS a un espacio de nombres, debe tener una cuenta de servicio existente para el proveedor que no es de AKS.

Para agregar un recurso de Kubernetes que no es de AKS a un entorno de Azure Pipelines:

  1. En la página del entorno, en Entornos de canalizaciones>, seleccione Agregar recurso y, después, Kubernetes.

  2. En la pantalla siguiente, seleccione Proveedor genérico (cuenta de servicio existente) para el proveedor.

  3. En Credenciales de clúster, escriba el nombre del clúster, el espacio de nombres, la dirección URL del servidor y el secreto.

    • Para obtener la dirección URL del servidor, ejecute kubectl config view --minify -o jsonpath={.clusters[0].cluster.server} en el shell local.

    • Para obtener el secreto:

      1. Para obtener nombres de secretos de cuenta de servicio, ejecute kubectl get serviceAccounts <service-account-name> -n <namespace> -o=jsonpath={.secrets[*].name}.
      2. Ejecute kubectl get secret <service-account-secret-name> -n <namespace> -o json utilizando la salida del comando anterior.

      Nota:

      Si no recibe ningún resultado del comando get ServiceAccounts, consulte Crear manualmente un token de API persistente para ServiceAccount.

  4. Seleccione Validar y crear.

Recursos de Kubernetes en canalizaciones

La manera más fácil de crear una canalización YAML para implementar en AKS es empezar con la plantilla Deploy to Azure Kubernetes Services (Implementar en Azure Kubernetes Services ). No es necesario escribir código YAML ni crear manualmente enlaces de roles explícitos. Los conjuntos de canalizaciones generados manejan y usan variables y otros valores basados en tu configuración.

Uso de la aplicación de revisión

El DeployPullRequest trabajo despliega todas las solicitudes de incorporación de cambios desde tu repositorio de Git a un recurso dinámico de Kubernetes en el entorno. Para agregar este trabajo a la canalización, active la casilla Habilitar el flujo de Review App para las Pull Requests en el formulario de configuración Deploy to Azure Kubernetes Services.

Nota:

Para agregar este trabajo a una canalización existente, asegúrese de que la conexión de servicio que respalda el recurso de entorno normal de Kubernetes esté establecida en Uso de credenciales de administrador de clústeres. De lo contrario, se deben crear asignaciones de funciones para la cuenta de servicio subyacente en el espacio de nombres de la aplicación de revisión.

Los recursos de la aplicación etiquetados como Reseña aparecen en el listado de Recursos del entorno.

Captura de pantalla que muestra el entorno de revisión en la lista de entornos de flujo de trabajo.

Canalización de ejemplo

La canalización de ejemplo siguiente se basa en la plantilla Implementar en Azure Kubernetes Services. La canalización primero compila e inserta una imagen en Azure Container Registry.

A continuación, el primer trabajo de implementación se ejecuta para las confirmaciones en la main rama e implementa en un recurso de Kubernetes normal en el entorno.

El segundo trabajo se ejecuta cuando se crea o actualiza una solicitud de incorporación de cambios en la rama main e implementa contra un recurso de aplicación de revisión dinámica que crea en el clúster a petición.

# Deploy to Azure Kubernetes Service
# Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker

trigger:
- main

resources:
- repo: self

variables:

  # Container registry service connection established during pipeline creation
  dockerRegistryServiceConnection: '12345' # Docker service connection identifier
  imageRepository: 'name-of-image-repository' # name of image repository
  containerRegistry: 'mycontainer.azurecr.io' # path to container registry
  dockerfilePath: '**/Dockerfile'
  tag: '$(Build.BuildId)'
  imagePullSecret: 'my-app-secret' # image pull secret

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

  # Name of the new namespace being created to deploy the PR changes.
  k8sNamespaceForPR: 'review-app-$(System.PullRequest.PullRequestId)'

stages:
- stage: Build
  displayName: Build stage
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)
    steps:
    - task: Docker@2
      displayName: Build and push an image to container registry
      inputs:
        command: buildAndPush
        repository: $(imageRepository)
        dockerfile: $(dockerfilePath)
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)

    - upload: manifests
      artifact: manifests

- stage: Production
  displayName: Deploy stage
  dependsOn: Build

  jobs:
  - deployment: Production
    condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/pull/')))
    displayName: Production
    pool:
      vmImage: $(vmImageName)
    environment: 'myenvironmentname.myresourcename'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: KubernetesManifest@1
            displayName: Create imagePullSecret
            inputs:
              action: createSecret
              secretName: $(imagePullSecret)
              dockerRegistryEndpoint: $(dockerRegistryServiceConnection)

          - task: KubernetesManifest@1
            displayName: Deploy to Kubernetes cluster
            inputs:
              action: deploy
              manifests: |
                $(Pipeline.Workspace)/manifests/deployment.yml
                $(Pipeline.Workspace)/manifests/service.yml
              imagePullSecrets: |
                $(imagePullSecret)
              containers: |
                $(containerRegistry)/$(imageRepository):$(tag)

  - deployment: DeployPullRequest
    displayName: Deploy Pull request
    condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/pull/'))
    pool:
      vmImage: $(vmImageName)

    environment: 'myenvironmentname.$(k8sNamespaceForPR)'
    strategy:
      runOnce:
        deploy:
          steps:
          - reviewApp: default

          - task: Kubernetes@1
            displayName: 'Create a new namespace for the pull request'
            inputs:
              command: apply
              useConfigurationFile: true
              inline: '{ "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "$(k8sNamespaceForPR)" }}'

          - task: KubernetesManifest@1
            displayName: Create imagePullSecret
            inputs:
              action: createSecret
              secretName: $(imagePullSecret)
              namespace: $(k8sNamespaceForPR)
              dockerRegistryEndpoint: $(dockerRegistryServiceConnection)

          - task: KubernetesManifest@1
            displayName: Deploy to the new namespace in the Kubernetes cluster
            inputs:
              action: deploy
              namespace: $(k8sNamespaceForPR)
              manifests: |
                $(Pipeline.Workspace)/manifests/deployment.yml
                $(Pipeline.Workspace)/manifests/service.yml
              imagePullSecrets: |
                $(imagePullSecret)
              containers: |
                $(containerRegistry)/$(imageRepository):$(tag)

          - task: Kubernetes@1
            name: get
            displayName: 'Get services in the new namespace'
            continueOnError: true
            inputs:
              command: get
              namespace: $(k8sNamespaceForPR)
              arguments: svc
              outputFormat: jsonpath='http://{.items[0].status.loadBalancer.ingress[0].ip}:{.items[0].spec.ports[0].port}'

          # Get the IP of the deployed service and writing it to a variable for posting comment
          - script: |
              url="$(get.KubectlOutput)"
              message="Your review app has been deployed"
              if [ ! -z "$url" -a "$url" != "http://:" ]
              then
                message="${message} and is available at $url."
              fi
              echo "##vso[task.setvariable variable=GITHUB_COMMENT]$message"