Compartilhar via


Implantação azul-verde nos Aplicativos de Contêiner do Azure

Blue-Green Deployment é uma estratégia de lançamento de software que visa minimizar o tempo de inatividade e reduzir o risco associado à implantação de novas versões de um aplicativo. Em uma implantação azul-verde, dois ambientes idênticos, conhecidos como "azul" e "verde", são configurados. Um ambiente (azul) está executando a versão atual do aplicativo e um ambiente (verde) está executando a nova versão do aplicativo.

Depois que o ambiente verde é testado, o tráfego dinâmico é direcionado para ele e o ambiente azul é usado para implantar uma nova versão do aplicativo durante o próximo ciclo de implantação.

Você pode habilitar a implantação azul-verde nos Aplicativos de Contêiner do Azure combinando revisões de aplicativos de contêiner, pesos de tráfego e rótulos de revisão.

Screenshot of Azure Container Apps: Blue/Green deployment.

Use revisões para criar instâncias das versões azul e verde do aplicativo.

Revisão Descrição
Revisão azul A revisão rotulada como azul é a versão atualmente em execução e estável do aplicativo. Essa revisão é aquela com a qual os usuários interagem e é o alvo do tráfego de produção.
Revisão verde A revisão rotulada como verde é uma cópia da revisão azul, exceto que usa uma versão mais recente do código do aplicativo e, possivelmente, um novo conjunto de variáveis de ambiente. Ele não recebe nenhum tráfego de produção inicialmente, mas é acessível por meio de um nome de domínio totalmente qualificado (FQDN) rotulado.

Depois de testar e verificar a nova revisão, você pode apontar o tráfego de produção para a nova revisão. Se você encontrar problemas, você pode facilmente reverter para a versão anterior.

Ações Descrição
Teste e verificação A revisão verde é exaustivamente testada e verificada para garantir que a nova versão do aplicativo funcione conforme o esperado. Esse teste pode envolver várias tarefas, incluindo testes funcionais, testes de desempenho e verificações de compatibilidade.
Interruptor de tráfego Depois que a revisão verde passa em todos os testes necessários, uma mudança de tráfego é executada para que a revisão verde comece a atender à carga de produção. Essa troca é feita de forma controlada, garantindo uma transição suave.
Reversão Se ocorrerem problemas na revisão verde, você poderá reverter a opção de tráfego, roteando o tráfego de volta para a revisão azul estável. Essa reversão garante um impacto mínimo nos usuários se houver problemas na nova versão. A revisão verde ainda está disponível para a próxima implantação.
Mudança de função As funções das revisões azul e verde mudam após uma implantação bem-sucedida para a revisão verde . Durante o próximo ciclo de lançamento, a revisão verde representa o ambiente de produção estável enquanto a nova versão do código do aplicativo é implantada e testada na revisão azul.

Este artigo mostra como implementar a implantação azul-verde em um aplicativo de contêiner. Para executar os exemplos a seguir, você precisa de um ambiente de aplicativo de contêiner onde possa criar um novo aplicativo.

Observação

Consulte o repositório containerapps-blue-green para obter um exemplo completo de um fluxo de trabalho do GitHub que implementa a implantação azul-verde para aplicativos de contêiner.

Criar um aplicativo de contêiner com várias revisões ativas habilitadas

O aplicativo de contêiner deve ter a propriedade definida para multiple habilitar a configuration.activeRevisionsMode divisão de tráfego. Para obter nomes de revisão determinísticos, você pode definir a definição de configuração como um valor de cadeia de template.revisionSuffix caracteres que identifique exclusivamente uma versão. Por exemplo, você pode usar números de compilação ou o git confirma hashes curtos.

Para os comandos a seguir, um conjunto de hashes de confirmação foi usado.

export APP_NAME=<APP_NAME>
export APP_ENVIRONMENT_NAME=<APP_ENVIRONMENT_NAME>
export RESOURCE_GROUP=<RESOURCE_GROUP>

# A commitId that is assumed to correspond to the app code currently in production
export BLUE_COMMIT_ID=fb699ef
# A commitId that is assumed to correspond to the new version of the code to be deployed
export GREEN_COMMIT_ID=c6f1515

# create a new app with a new revision
az containerapp create --name $APP_NAME \
  --environment $APP_ENVIRONMENT_NAME \
  --resource-group $RESOURCE_GROUP \
  --image mcr.microsoft.com/k8se/samples/test-app:$BLUE_COMMIT_ID \
  --revision-suffix $BLUE_COMMIT_ID \
  --env-vars REVISION_COMMIT_ID=$BLUE_COMMIT_ID \
  --ingress external \
  --target-port 80 \
  --revisions-mode multiple

# Fix 100% of traffic to the revision
az containerapp ingress traffic set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --revision-weight $APP_NAME--$BLUE_COMMIT_ID=100

# give that revision a label 'blue'
az containerapp revision label add \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --label blue \
  --revision $APP_NAME--$BLUE_COMMIT_ID

Salve o código a seguir em um arquivo chamado main.bicep.

targetScope = 'resourceGroup'
param location string = resourceGroup().location

@minLength(1)
@maxLength(64)
@description('Name of containerapp')
param appName string

@minLength(1)
@maxLength(64)
@description('Container environment name')
param containerAppsEnvironmentName string

@minLength(1)
@maxLength(64)
@description('CommitId for blue revision')
param blueCommitId string

@maxLength(64)
@description('CommitId for green revision')
param greenCommitId string = ''

@maxLength(64)
@description('CommitId for the latest deployed revision')
param latestCommitId string = ''

@allowed([
  'blue'
  'green'
])
@description('Name of the label that gets 100% of the traffic')
param productionLabel string = 'blue'

var currentCommitId = !empty(latestCommitId) ? latestCommitId : blueCommitId

resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2022-03-01' existing = {
  name: containerAppsEnvironmentName
}

resource blueGreenDeploymentApp 'Microsoft.App/containerApps@2022-11-01-preview' = {
  name: appName
  location: location
  tags: {
    blueCommitId: blueCommitId
    greenCommitId: greenCommitId
    latestCommitId: currentCommitId
    productionLabel: productionLabel
  }
  properties: {
    environmentId: containerAppsEnvironment.id
    configuration: {
      maxInactiveRevisions: 10 // Remove old inactive revisions
      activeRevisionsMode: 'multiple' // Multiple active revisions mode is required when using traffic weights
      ingress: {
        external: true
        targetPort: 80
        traffic: !empty(blueCommitId) && !empty(greenCommitId) ? [
          {
            revisionName: '${appName}--${blueCommitId}'
            label: 'blue'
            weight: productionLabel == 'blue' ? 100 : 0
          }
          {
            revisionName: '${appName}--${greenCommitId}'
            label: 'green'
            weight: productionLabel == 'green' ? 100 : 0
          }
        ] : [
          {
            revisionName: '${appName}--${blueCommitId}'
            label: 'blue'
            weight: 100
          }
        ]
      }
    }
    template: {
      revisionSuffix: currentCommitId
      containers:[
        {
          image: 'mcr.microsoft.com/k8se/samples/test-app:${currentCommitId}'
          name: appName
          resources: {
            cpu: json('0.5')
            memory: '1.0Gi'
          }
          env: [
            {
              name: 'REVISION_COMMIT_ID'
              value: currentCommitId
            }
          ]
        }
      ]
    }
  }
}

output fqdn string = blueGreenDeploymentApp.properties.configuration.ingress.fqdn
output latestRevisionName string = blueGreenDeploymentApp.properties.latestRevisionName

Implante o aplicativo com o modelo Bicep usando este comando:

export APP_NAME=<APP_NAME>
export APP_ENVIRONMENT_NAME=<APP_ENVIRONMENT_NAME>
export RESOURCE_GROUP=<RESOURCE_GROUP>

# A commitId that is assumed to belong to the app code currently in production
export BLUE_COMMIT_ID=fb699ef
# A commitId that is assumed to belong to the new version of the code to be deployed
export GREEN_COMMIT_ID=c6f1515

# create a new app with a blue revision
az deployment group create \
    --name createapp-$BLUE_COMMIT_ID \
    --resource-group $RESOURCE_GROUP \
    --template-file main.bicep \
    --parameters appName=$APP_NAME blueCommitId=$BLUE_COMMIT_ID containerAppsEnvironmentName=$APP_ENVIRONMENT_NAME \
    --query properties.outputs.fqdn

Implantar uma nova revisão e atribuir rótulos

O rótulo azul atualmente se refere a uma revisão que leva o tráfego de produção que chega ao FQDN do aplicativo. O rótulo verde refere-se a uma nova versão de um aplicativo que está prestes a ser lançado em produção. Um novo hash de confirmação identifica a nova versão do código do aplicativo. O comando a seguir implanta uma nova revisão para esse hash de confirmação e o marca com rótulo verde .

#create a second revision for green commitId
az containerapp update --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --image mcr.microsoft.com/k8se/samples/test-app:$GREEN_COMMIT_ID \
  --revision-suffix $GREEN_COMMIT_ID  \
  --set-env-vars REVISION_COMMIT_ID=$GREEN_COMMIT_ID

#give that revision a 'green' label
az containerapp revision label add \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --label green \
  --revision $APP_NAME--$GREEN_COMMIT_ID
#deploy a new version of the app to green revision
az deployment group create \
    --name deploy-to-green-$GREEN_COMMIT_ID \
    --resource-group $RESOURCE_GROUP \
    --template-file main.bicep \
    --parameters appName=$APP_NAME blueCommitId=$BLUE_COMMIT_ID greenCommitId=$GREEN_COMMIT_ID latestCommitId=$GREEN_COMMIT_ID productionLabel=blue containerAppsEnvironmentName=$APP_ENVIRONMENT_NAME \
    --query properties.outputs.fqdn

O exemplo a seguir mostra como a seção de tráfego é configurada. A revisão com o azulcommitId está tomando 100% do tráfego de produção, enquanto a revisão recém-implantada com o verdecommitId não leva nenhum tráfego de produção.

{ 
  "traffic": [
    {
      "revisionName": "<APP_NAME>--fb699ef",
      "weight": 100,
      "label": "blue"
    },
    {
      "revisionName": "<APP_NAME>--c6f1515",
      "weight": 0,
      "label": "green"
    }
  ]
}

A revisão recém-implantada pode ser testada usando o FQDN específico do rótulo:

#get the containerapp environment default domain
export APP_DOMAIN=$(az containerapp env show -g $RESOURCE_GROUP -n $APP_ENVIRONMENT_NAME --query properties.defaultDomain -o tsv | tr -d '\r\n')

#Test the production FQDN
curl -s https://$APP_NAME.$APP_DOMAIN/api/env | jq | grep COMMIT

#Test the blue lable FQDN
curl -s https://$APP_NAME---blue.$APP_DOMAIN/api/env | jq | grep COMMIT

#Test the green lable FQDN
curl -s https://$APP_NAME---green.$APP_DOMAIN/api/env | jq | grep COMMIT

Enviar tráfego de produção para a revisão verde

Depois de confirmar que o código do aplicativo na revisão verde funciona conforme o esperado, 100% do tráfego de produção é enviado para a revisão. A revisão verde agora se torna a revisão da produção.

# set 100% of traffic to green revision
az containerapp ingress traffic set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --label-weight blue=0 green=100

# make green the prod revision
az deployment group create \
    --name make-green-prod-$GREEN_COMMIT_ID \
    --resource-group $RESOURCE_GROUP \
    --template-file main.bicep \
    --parameters appName=$APP_NAME blueCommitId=$BLUE_COMMIT_ID greenCommitId=$GREEN_COMMIT_ID latestCommitId=$GREEN_COMMIT_ID productionLabel=green containerAppsEnvironmentName=$APP_ENVIRONMENT_NAME \
    --query properties.outputs.fqdn

O exemplo a seguir mostra como a seção é configurada traffic após essa etapa. A revisão verde com o novo código do aplicativo recebe todo o tráfego do usuário, enquanto a revisão azul com a versão antiga do aplicativo não aceita solicitações do usuário.

{ 
  "traffic": [
    {
      "revisionName": "<APP_NAME>--fb699ef",
      "weight": 0,
      "label": "blue"
    },
    {
      "revisionName": "<APP_NAME>--c6f1515",
      "weight": 100,
      "label": "green"
    }
  ]
}

Reverter a implantação se houver problemas

Se depois de executar em produção, a nova revisão for encontrada com bugs, você poderá reverter para o estado bom anterior. Após a reversão, 100% do tráfego é enviado para a versão antiga na revisão azul e essa revisão é designada como a revisão de produção novamente.

# set 100% of traffic to green revision
az containerapp ingress traffic set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --label-weight blue=100 green=0
# rollback traffic to blue revision
az deployment group create \
    --name rollback-to-blue-$GREEN_COMMIT_ID \
    --resource-group $RESOURCE_GROUP \
    --template-file main.bicep \
    --parameters appName=$APP_NAME blueCommitId=$BLUE_COMMIT_ID greenCommitId=$GREEN_COMMIT_ID latestCommitId=$GREEN_COMMIT_ID productionLabel=blue containerAppsEnvironmentName=$APP_ENVIRONMENT_NAME \
    --query properties.outputs.fqdn

Depois que os bugs são corrigidos, a nova versão do aplicativo é implantada como uma revisão verde novamente. A versão verde acaba se tornando a revisão da produção.

Próximo ciclo de implantação

Agora, o rótulo verde marca a revisão que está executando o código de produção estável.

Durante o próximo ciclo de implantação, o azul identifica a revisão com a nova versão do aplicativo que está sendo distribuída para produção.

Os comandos a seguir demonstram como se preparar para o próximo ciclo de implantação.

# set the new commitId
export BLUE_COMMIT_ID=ad1436b

# create a third revision for blue commitId
az containerapp update --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --image mcr.microsoft.com/k8se/samples/test-app:$BLUE_COMMIT_ID \
  --revision-suffix $BLUE_COMMIT_ID  \
  --set-env-vars REVISION_COMMIT_ID=$BLUE_COMMIT_ID

# give that revision a 'blue' label
az containerapp revision label add \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --label blue \
  --revision $APP_NAME--$BLUE_COMMIT_ID
# set the new commitId
export BLUE_COMMIT_ID=ad1436b

# deploy new version of the app to blue revision
az deployment group create \
    --name deploy-to-blue-$BLUE_COMMIT_ID \
    --resource-group $RESOURCE_GROUP \
    --template-file main.bicep \
    --parameters appName=$APP_NAME blueCommitId=$BLUE_COMMIT_ID greenCommitId=$GREEN_COMMIT_ID latestCommitId=$BLUE_COMMIT_ID productionLabel=green containerAppsEnvironmentName=$APP_ENVIRONMENT_NAME \
    --query properties.outputs.fqdn

Próximas etapas