Compartilhar via


Tutorial: Use uma estratégia de implantação canária para Kubernetes

Azure DevOps Services | Azure DevOps Server 2022

Este guia passo a passo aborda como usar a tarefa de manifesto do Kubernetes com a estratégia canary. Uma estratégia de implantação canária implanta novas versões de um aplicativo ao lado de versões estáveis de produção.

Use o fluxo de trabalho associado para implantar o código e comparar as implantações de aplicativos de base e canárias. Com base na avaliação, você decide se deseja promover ou rejeitar a implantação canária.

Este tutorial usa conexões de serviço do Docker Registry e do Azure Resource Manager para se conectar aos recursos do Azure. Para um cluster privado do AKS (Serviço de Kubernetes do Azure) ou um cluster que tem contas locais desabilitadas, uma conexão de serviço do Azure Resource Manager é uma maneira melhor de se conectar.

Pré-requisitos

Arquivos do repositório do GitHub

O repositório do GitHub contém os seguintes arquivos:

Arquivo Descrição
./app/app.py Um servidor web simples, baseado em Flask. O arquivo configura um contador personalizado para o número de respostas boas e ruins, com base no valor da variável success_rate.
./app/Dockerfile Usado para construir a imagem a cada alteração para app.py. Cada alteração dispara o pipeline de compilação para criar a imagem e enviá-la por push para o registro de contêiner.
./manifests/deployment.yml Contém a especificação da sampleapp carga de trabalho de implantação correspondente à imagem publicada. Use esse arquivo de manifesto para a versão estável do objeto de implantação e para derivar as variantes de base e canária das cargas de trabalho.
./manifests/service.yml Cria o serviço sampleapp. Esse serviço roteia solicitações para os pods gerados pelas implantações estáveis, de base e canária.
./misc/fortio.yml Configura uma implantação do Fortio. Essa implantação é uma ferramenta de teste de carga que envia um fluxo de solicitações para o serviço implantado sampleapp. O fluxo de solicitação é roteado para pods nas três implantações: estável, de base e canária.

Criar conexões de serviço

  1. No seu projeto do Azure DevOps, vá para Configurações do projeto>Pipelines>Conexões de serviço.
  2. Crie uma conexão de serviço do Registro do Docker chamada azure-pipelines-canary-acr associada à instância do Registro de Contêiner do Azure.
  3. Crie uma conexão de serviço do Azure Resource Manager com a identidade de carga de trabalho chamada azure-pipelines-canary-k8s para seu grupo de recursos.

Adicione a fase de build

  1. Em seu projeto do Azure DevOps, acesse Pipelines>Criar Pipeline ou Novo pipeline.

  2. Selecione GitHub para o local do código e selecione o repositório azure-pipelines-canary-k8s.

  3. Na guia Configurar, escolha Pipeline inicial.

  4. Na guia Review substitua o pipeline YAML pelo código a seguir.

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      imageName: azure-pipelines-canary-k8s # name of ACR image
      dockerRegistryServiceConnection: azure-pipelines-canary-acr # name of ACR service connection
      imageRepository: 'azure-pipelines-canary-k8s' # name of image repository
      containerRegistry: example.azurecr.io # name of Azure container registry
      tag: '$(Build.BuildId)'
    
    stages:
    - stage: Build
      displayName: Build stage
      jobs:  
      - job: Build
        displayName: Build
        pool:
          vmImage: ubuntu-latest
        steps:
        - task: Docker@2
          displayName: Build and push image
          inputs:
            containerRegistry: $(dockerRegistryServiceConnection)
            repository: $(imageName)
            command: buildAndPush
            Dockerfile: app/Dockerfile
            tags: |
              $(tag)
    

    Se a conexão do serviço de registro do Docker que você criou estiver associada a um registro de contêiner chamado example.azurecr.io, a imagem será definida como example.azurecr.io/azure-pipelines-canary-k8s:$(Build.BuildId).

  5. Selecione Salvar e executar e verifique se o trabalho foi executado com êxito.

Editar o arquivo de manifesto

No fork do repositório, edite manifests/deployment.yml para substituir <foobar> pela URL do registro de contêiner, por exemplo example.azurecr.io/azure-pipelines-canary-k8s.

Configurar a implantação contínua

Agora, configure a implantação contínua, implante o estágio canário e promova ou rejeite o canário por meio da aprovação manual.

Criar um ambiente

Você pode implantar com YAML ou o Clássico.

  1. Em seu projeto do Azure DevOps, acesse Ambientes de Pipelines> e selecione Criar ambiente ou Novo ambiente.
  2. Na primeira tela Novo ambiente, insira akscanary em Nome, selecione Kubernetes em Recurso e selecione Avançar.
  3. Preencha a tela de recursos do Kubernetes da seguinte maneira:
    • Em Provedor: selecione Serviço de Kubernetes do Azure.
    • Assinatura do Azure: selecione sua assinatura do Azure.
    • Cluster: selecione seu cluster do AKS.
    • Namespace: Selecione Novo e insira canarydemo.
  4. Selecione Validar e criar.

Adicionar o estágio canário

  1. Vá para Pipelines, selecione o pipeline que você criou e selecione Editar.

  2. Substitua todo o pipeline YAML pelo código a seguir.

    Esse código altera a etapa Docker@2 que você executou anteriormente para usar um estágio e adiciona mais duas etapas para copiar os manifestos e diretórios diversos como artefatos para estágios consecutivos a serem usados.

    O código também move alguns valores para variáveis para facilitar o uso posterior no pipeline. Na variável containerRegistry, substitua <example> pelo nome do registro de contêiner.

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      imageName: azure-pipelines-canary-k8s
      dockerRegistryServiceConnection: azure-pipelines-canary-acr
      imageRepository: 'azure-pipelines-canary-k8s'
      containerRegistry: <example>.azurecr.io
      tag: '$(Build.BuildId)'
    
    stages:
    - stage: Build
      displayName: Build stage
      jobs:  
      - job: Build
        displayName: Build
        pool:
          vmImage: ubuntu-latest
        steps:
        - task: Docker@2
          displayName: Build and push image
          inputs:
            containerRegistry: $(dockerRegistryServiceConnection)
            repository: $(imageName)
            command: buildAndPush
            Dockerfile: app/Dockerfile
            tags: |
              $(tag)
    
        - publish: manifests
          artifact: manifests
    
        - publish: misc
          artifact: misc
    
  3. Adicione outro estágio no final do arquivo YAML para implantar a versão canário. Substitua os valores my-resource-group e my-aks-cluster com seu grupo de recursos e o nome do cluster do Serviço de Kubernetes do Azure.

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      imageName: azure-pipelines-canary-k8s
      dockerRegistryServiceConnection: azure-pipelines-canary-acr
      imageRepository: 'azure-pipelines-canary-k8s'
      containerRegistry: yourcontainerregistry.azurecr.io #update with container registry
      tag: '$(Build.BuildId)'
    
    stages:
    - stage: Build
      displayName: Build stage
      jobs:  
      - job: Build
        displayName: Build
        pool:
          vmImage: ubuntu-latest
        steps:
        - task: Docker@2
          displayName: Build and push image
          inputs:
            containerRegistry: $(dockerRegistryServiceConnection)
            repository: $(imageName)
            command: buildAndPush
            Dockerfile: app/Dockerfile
            tags: |
              $(tag)
    
        - publish: manifests
          artifact: manifests
    
        - publish: misc
          artifact: misc
    
    - stage: DeployCanary
      displayName: Deploy canary
      dependsOn: Build
      condition: succeeded()
    
      jobs:
      - deployment: Deploycanary
        displayName: Deploy canary
        pool:
          vmImage: ubuntu-latest
        environment: 'akscanary'
        strategy:
          runOnce:
            deploy:
              steps:
              - task: KubernetesManifest@1
                displayName: Create Docker Registry Secret
                inputs:
                  action: 'createSecret'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  secretType: 'dockerRegistry'
                  secretName: 'my-acr-secret'
                  dockerRegistryEndpoint: 'azure-pipelines-canary-acr'
    
              - task: KubernetesManifest@1
                displayName: Deploy to Kubernetes cluster
                inputs:
                  action: 'deploy'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  strategy: 'canary'
                  percentage: '25'
                  manifests: |
                    $(Pipeline.Workspace)/manifests/deployment.yml
                    $(Pipeline.Workspace)/manifests/service.yml
                  containers: '$(containerRegistry)/$(imageRepository):$(tag)'
                  imagePullSecrets: 'my-acr-secret'
    
              - task: KubernetesManifest@1
                displayName: Deploy Forbio to Kubernetes cluster
                inputs:
                  action: 'deploy'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  manifests: '$(Pipeline.Workspace)/misc/*'
    
  4. Selecione Validar e salvar e salve o pipeline diretamente no branch principal.

Adicionar aprovação manual para promover ou rejeitar a implantação canários

Você pode intervir manualmente com o YAML ou o Clássico.

  1. Crie um novo ambiente do Kubernetes chamado akspromote.
  2. Abra o novo ambiente akspromote na lista de ambientes e selecione Aprovações na guia Aprovações e verificações.
  3. Na tela Aprovações, adicione sua própria conta de usuário em Aprovadores.
  4. Expanda Avançado e certifique-se de que a opção Permitir que os aprovadores aprovem suas próprias execuções esteja selecionada.
  5. Selecione Criar.

Adicionar estágios de promoção e rejeição ao pipeline

  1. Vá para Pipelines, selecione o pipeline que você criou e selecione Editar.

  2. Adicione o seguinte estágio PromoteRejectCanary no final do arquivo YAML que promove as alterações.

    - stage: PromoteRejectCanary
      displayName: Promote or Reject canary
      dependsOn: DeployCanary
      condition: succeeded()
    
      jobs:
      - deployment: PromoteCanary
        displayName: Promote Canary
        pool: 
          vmImage: ubuntu-latest
        environment: 'akspromote'
        strategy:
          runOnce:
            deploy:
              steps:      
              - task: KubernetesManifest@1
                displayName: Create Docker Registry Secret for akspromote
                inputs:
                  action: 'createSecret'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  secretType: 'dockerRegistry'
                  secretName: 'my-acr-secret'
                  dockerRegistryEndpoint: 'azure-pipelines-canary-acr'
    
              - task: KubernetesManifest@1
                displayName: promote canary
                inputs:
                  action: 'promote'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  strategy: 'canary'
                  manifests: '$(Pipeline.Workspace)/manifests/*'
                  containers: '$(containerRegistry)/$(imageRepository):$(tag)'
                  imagePullSecrets: 'my-acr-secret'
        ```
    
    
  3. Adicione o seguinte estágio RejectCanary no final do arquivo que reverte as alterações.

    - stage: RejectCanary
      displayName: Reject canary
      dependsOn: PromoteRejectCanary
      condition: failed()
    
      jobs:
      - deployment: RejectCanary
        displayName: Reject Canary
        pool: 
          vmImage: ubuntu-latest
        environment: 'akscanary'
        strategy:
          runOnce:
            deploy:
              steps:        
              - task: KubernetesManifest@1
                displayName: Create Docker Registry Secret for reject canary
                inputs:
                  action: 'createSecret'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'kubernetes-testing'
                  kubernetesCluster: 'my-aks-cluster'
                  secretType: 'dockerRegistry'
                  secretName: 'my-acr-secret'
                  dockerRegistryEndpoint: 'azure-pipelines-canary-acr'    
              - task: KubernetesManifest@1
                displayName: Reject canary deployment
                inputs:
                  action: 'reject'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  namespace: 'default'
                  strategy: 'canary'
                  manifests: '$(Pipeline.Workspace)/manifests/*'
        ```
    
  4. Selecione Validar e salvar e salve o pipeline diretamente no branch principal.

Implantar uma versão estável

Para a primeira execução do pipeline, a versão estável das cargas de trabalho e suas versões de linha de base ou canário não existem no cluster. Implante uma versão estável da carga de trabalho sampleapp da seguinte maneira.

Você pode implantar uma versão estável com o YAML ou o Clássico.

  1. Em app/app.py, altere success_rate = 50 para success_rate = 100. Essa alteração dispara o pipeline, criando e enviando a imagem para o registro de contêiner e também dispara o estágio DeployCanary.
  2. Como você configurou uma aprovação no ambiente akspromote, a versão aguarda antes de executar esse estágio. Na página de resumo da execução de compilação, selecione Examinar e, em seguida, selecione Aprovar.

Depois de aprovado, o pipeline implanta a versão estável da carga de trabalho sampleapp em manifestos/deployment.yml no namespace.

Iniciar o fluxo de trabalho canário e rejeitar a aprovação

A versão estável da carga de trabalho sampleapp agora existe no cluster. Em seguida, faça esta alteração no aplicativo de simulação.

  1. Em app/app.py, altere success_rate = 50 para success_rate = 100. Essa alteração dispara o pipeline, criando e enviando a imagem para o registro de contêiner e também dispara o estágio DeployCanary.
  2. Como você configurou uma aprovação no ambiente akspromote, a versão aguarda antes de executar esse estágio.
  3. Na página de resumo da execução de build, selecione Analisar e, em seguida, selecione Rejeitar na caixa de diálogo subsequente. Isso rejeita a implantação.

Depois de rejeitado, o pipeline impede a implantação do código.

Limpar

Se você não quiser continuar a usar esse aplicativo, exclua o grupo de recursos no portal do Azure e o projeto no Azure DevOps com as etapas a seguir.