Share via


Distribuzione blu-verde nelle app contenitore di Azure

Blue-Green Deployment è una strategia di rilascio software che mira a ridurre al minimo i tempi di inattività e ridurre il rischio associato alla distribuzione di nuove versioni di un'applicazione. In una distribuzione blu-verde vengono configurati due ambienti identici, denominati "blu" e "verde". Un ambiente (blu) esegue la versione corrente dell'applicazione e un ambiente (verde) esegue la nuova versione dell'applicazione.

Dopo aver testato l'ambiente verde, il traffico live viene indirizzato a esso e l'ambiente blu viene usato per distribuire una nuova versione dell'applicazione durante il ciclo di distribuzione successivo.

È possibile abilitare la distribuzione blu-verde nelle app Contenitore di Azure combinando revisioni delle app contenitore, pesi del traffico ed etichette di revisione.

Screenshot of Azure Container Apps: Blue/Green deployment.

Le revisioni vengono usate per creare istanze delle versioni blu e verde dell'applicazione.

Revisione Descrizione
Revisione blu La revisione etichettata come blu è la versione attualmente in esecuzione e stabile dell'applicazione. Questa revisione è quella con cui gli utenti interagiscono ed è la destinazione del traffico di produzione.
Revisione verde La revisione etichettata come verde è una copia della revisione blu , ad eccezione del fatto che usa una versione più recente del codice dell'app e possibilmente un nuovo set di variabili di ambiente. Inizialmente non riceve traffico di produzione, ma è accessibile tramite un nome di dominio completo (FQDN).

Dopo aver testato e verificato la nuova revisione, è possibile indirizzare il traffico di produzione alla nuova revisione. Se si verificano problemi, è possibile eseguire facilmente il rollback alla versione precedente.

Azioni Descrizione
Test e verifica La revisione verde viene testata e verificata accuratamente per garantire che la nuova versione dell'applicazione funzioni come previsto. Questo test può comportare varie attività, tra cui test funzionali, test delle prestazioni e controlli di compatibilità.
Commutatore di traffico Dopo che la revisione verde supera tutti i test necessari, viene eseguita un'opzione di traffico in modo che la revisione verde inizi a gestire il carico di produzione. Questa opzione viene eseguita in modo controllato, garantendo una transizione uniforme.
Rollback Se si verificano problemi nella revisione verde, è possibile ripristinare il commutatore di traffico, instradando il traffico alla revisione blu stabile. Questo rollback garantisce un impatto minimo sugli utenti in caso di problemi nella nuova versione. La revisione verde è ancora disponibile per la distribuzione successiva.
Modifica del ruolo I ruoli delle revisioni blu e verde cambiano dopo una corretta distribuzione alla revisione verde . Durante il ciclo di rilascio successivo, la revisione verde rappresenta l'ambiente di produzione stabile mentre la nuova versione del codice dell'applicazione viene distribuita e testata nella revisione blu .

Questo articolo illustra come implementare la distribuzione blu-verde in un'app contenitore. Per eseguire gli esempi seguenti, è necessario un ambiente dell'app contenitore in cui è possibile creare una nuova app.

Creare un'app contenitore con più revisioni attive abilitate

L'app contenitore deve avere la proprietà impostata su multiple per abilitare la configuration.activeRevisionsMode suddivisione del traffico. Per ottenere nomi di revisione deterministici, è possibile impostare l'impostazione di template.revisionSuffix configurazione su un valore stringa che identifica in modo univoco una versione. Ad esempio, è possibile usare i numeri di compilazione o i commit git di hash brevi.

Per i comandi seguenti, è stato usato un set di hash di commit.

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

Salvare il codice seguente in un file denominato 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

Distribuire l'app con il modello Bicep usando questo 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

Distribuire una nuova revisione e assegnare etichette

L'etichetta blu attualmente fa riferimento a una revisione che accetta il traffico di produzione in arrivo sul nome di dominio completo dell'app. L'etichetta verde si riferisce a una nuova versione di un'app che sta per essere implementata nell'ambiente di produzione. Un nuovo hash di commit identifica la nuova versione del codice dell'app. Il comando seguente distribuisce una nuova revisione per l'hash di commit e la contrassegna con etichetta 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

Nell'esempio seguente viene illustrato come viene configurata la sezione del traffico. La revisione con blu commitId richiede il 100% del traffico di produzione mentre la revisione appena distribuita con verdecommitId non accetta traffico di produzione.

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

La revisione appena distribuita può essere testata usando il nome di dominio completo specifico dell'etichetta:

#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

Inviare il traffico di produzione alla revisione verde

Dopo aver verificato che il codice dell'app nella revisione verde funzioni come previsto, il 100% del traffico di produzione viene inviato alla revisione. La revisione verde diventa ora la revisione di produzione.

# 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

Nell'esempio seguente viene illustrato come viene configurata la traffic sezione dopo questo passaggio. La revisione verde con il nuovo codice dell'applicazione accetta tutto il traffico utente mentre la revisione blu con la versione precedente dell'applicazione non accetta le richieste utente.

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

Eseguire il rollback della distribuzione in caso di problemi

Se dopo l'esecuzione nell'ambiente di produzione, viene rilevata la presenza di bug nella nuova revisione, è possibile eseguire il rollback allo stato corretto precedente. Dopo il rollback, il 100% del traffico viene inviato alla versione precedente nella revisione blu e tale revisione viene designata nuovamente come revisione di produzione.

# 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

Dopo aver corretto i bug, la nuova versione dell'applicazione viene distribuita nuovamente come revisione verde . La versione verde diventa infine la revisione di produzione.

Ciclo di distribuzione successivo

Ora l'etichetta verde contrassegna la revisione che esegue il codice di produzione stabile.

Durante il ciclo di distribuzione successivo, il blu identifica la revisione con la nuova versione dell'applicazione implementata nell'ambiente di produzione.

I comandi seguenti illustrano come prepararsi per il ciclo di distribuzione successivo.

# 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

Passaggi successivi