Compartilhar via


Recursos do Kubernetes em ambientes

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

Este artigo descreve o uso de recursos do Kubernetes em ambientes do Azure Pipelines que você pode direcionar com implantações. Você pode se conectar a clusters kubernetes públicos ou privados no AKS (Serviço de Kubernetes do Azure) ou em outros provedores de nuvem.

As exibições de recursos de ambiente mostram o status dos recursos do Kubernetes e fornecem rastreabilidade para o pipeline, retornando até o commit que acionou. Você também pode criar recursos dinâmicos de ambiente do Kubernetes para examinar solicitações de pull antes da mesclagem. Para obter mais informações sobre recursos de ambiente, consulte Recursos em Pipelines YAML e Segurança de Recursos.

Observação

Um cluster privado do AKS não expõe seu ponto de extremidade de servidor de API por meio de um endereço IP público, portanto, você deve se conectar à rede virtual do cluster. Você pode configurar um agente auto-hospedado em uma rede virtual que pode acessar a rede virtual do cluster ou usar Pools de DevOps Gerenciados. Para obter mais informações, consulte Opções para se conectar a um cluster privado.

Vantagens dos recursos ambientais do Kubernetes

Os recursos de ambiente do Kubernetes e as exibições de recursos em ambientes oferecem os seguintes benefícios:

  • Rastreabilidade de pipeline. A tarefa de implantação de manifesto do Kubernetes adiciona anotações que dão suporte à rastreabilidade do pipeline. Você pode ver a organização, o projeto e o pipeline do Azure DevOps responsáveis pelas atualizações nos objetos dentro do namespace.

    Captura de tela que mostra a rastreabilidade do pipeline para um cluster do Kubernetes.

  • Diagnóstico de integridade do recurso. A exibição de status da carga de trabalho é uma maneira rápida de depurar erros ou regressões introduzidas por novas implantações. Por exemplo, as informações de status do pod podem ajudá-lo a identificar a causa de problemas, como a falta de configuração de imagePullSecrets, que resulta em erros de ImagePullBackOff.

    Captura de tela que mostra a visão de status da carga de trabalho para um deployment do Kubernetes.

  • Examine o aplicativo. O aplicativo de revisão implanta cada solicitação pull do repositório Git em um recurso dinâmico do Kubernetes no ambiente e posta um comentário do GitHub vinculando ao aplicativo de revisão. Os revisores podem ver como as alterações de RP parecem e funcionam com outros serviços dependentes antes que as alterações sejam mescladas no branch de destino e implantadas na produção.

    Captura de tela que mostra o comentário do aplicativo Revisão no GitHub.

Recursos do AKS

O AKS cria um ServiceAccount em seu cluster e namespace escolhidos e mapeia os recursos do Kubernetes em seu ambiente para o namespace especificado. Para obter informações sobre como configurar uma conexão de serviço do Kubernetes fora de um ambiente, consulte a conexão de serviço do Kubernetes.

Para um cluster habilitado para RBAC (controle de acesso baseado em função) do Kubernetes, RoleBinding também é criado para limitar o escopo da conta de serviço ao namespace escolhido. Para um cluster Kubernetes com RBAC desabilitado, a conta de serviço já criada tem privilégios em todo o cluster, abrangendo todos os namespaces.

Para adicionar um recurso do AKS a um ambiente do Azure Pipelines:

  1. Na página do ambiente em Pipelines>Ambientes, selecione Adicionar recurso e depois escolha Kubernetes.

  2. Na próxima tela, selecione o Serviço de Kubernetes do Azure para o Provedor e selecione sua assinatura do Azure, o Cluster do AKS e o Namespace novo ou existente. Para um novo namespace, insira o nome do namespace.

  3. Selecione Validar e criar. O novo recurso aparece na guia Recursos do ambiente com o texto Nunca implantado.

    Captura de tela que mostra um recurso do Kubernetes adicionado.

Recursos do Kubernetes que não são do AKS

Para mapear um recurso do Kubernetes de um cluster não AKS para um namespace, você precisa ter uma conta de serviço existente para o provedor não AKS.

Para adicionar um recurso kubernetes não AKS a um ambiente do Azure Pipelines:

  1. Na página do ambiente em Pipelines>Ambientes, selecione Adicionar recurso e depois escolha Kubernetes.

  2. Na próxima tela, selecione Provedor genérico (conta de serviço existente) para o Provedor.

  3. Em credenciais de cluster, insira o nome do cluster, o namespace, a URL do servidor e o segredo.

    • Para obter a URL do servidor, execute kubectl config view --minify -o jsonpath={.clusters[0].cluster.server} no shell local.

    • Para obter o segredo:

      1. Obter nomes secretos das contas de serviço executando kubectl get serviceAccounts <service-account-name> -n <namespace> -o=jsonpath={.secrets[*].name}.
      2. Execute kubectl get secret <service-account-secret-name> -n <namespace> -o json usando a saída do comando anterior.

      Observação

      Se você não obtiver resultados do get ServiceAccounts comando, consulte Criar manualmente um token de API de longa duração para um ServiceAccount.

  4. Selecione Validar e criar.

Recursos do Kubernetes em pipelines

A maneira mais fácil de criar um pipeline YAML para implantar no AKS é começar com o modelo Implantar no Azure Kubernetes Services . Você não precisa escrever código YAML ou criar associações de função explícitas manualmente. O pipeline gerado define e usa variáveis e outros valores com base nas configurações.

Usar o aplicativo de revisão

O DeployPullRequest trabalho implanta todas as solicitações de pull do repositório Git em um recurso dinâmico do Kubernetes no ambiente. Para adicionar esse trabalho ao pipeline, marque a caixa de seleção para Habilitar o fluxo de Aplicativo de Revisão para Solicitações de Pull no formulário de configuração Implantar no Azure Kubernetes Services .

Observação

Para adicionar esse trabalho a um pipeline existente, verifique se a conexão de serviço que está apoiando o recurso de ambiente do Kubernetes regular está definida como Usar credenciais de administrador de cluster. Caso contrário, devem ser criadas associações de funções para a conta de serviço subjacente no namespace da aplicação de revisão.

Os recursos de aplicativo de revisão são rotulados Revisão na listagem de recursos do ambiente.

Captura de tela que exibe o ambiente de revisão na listagem do ambiente do pipeline.

Pipeline de exemplo

O pipeline de exemplo a seguir baseia-se no modelo Implantar nos Serviços de Kubernetes do Azure . O pipeline primeiro cria e envia uma imagem para o Azure Container Registry.

O primeiro trabalho de implantação é executado para qualquer confirmação no main branch e é implantado em um recurso do Kubernetes regular no ambiente.

O segundo trabalho é executado quando uma PR é criada ou atualizada para o main branch e é implantada em um recurso de aplicativo de revisão dinâmica que ele cria no cluster sob demanda.

# 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"