Blau-Grün-Bereitstellung in Azure Container Apps

Blue-Green Deployment ist eine Software release-Strategie, die darauf abzielt, Ausfallzeiten zu minimieren und das Risiko zu verringern, das mit der Bereitstellung neuer Versionen einer Anwendung verbunden ist. In einer blaugrünen Bereitstellung werden zwei identische Umgebungen eingerichtet, die als "blau" und "grün" bezeichnet werden. Eine Umgebung (blau) führt die aktuelle Anwendungsversion aus, und eine Umgebung (grün) führt die neue Anwendungsversion aus.

Sobald die grüne Umgebung getestet wurde, wird der Livedatenverkehr an sie weitergeleitet, und die blaue Umgebung wird verwendet, um während des nächsten Bereitstellungszyklus eine neue Anwendungsversion bereitzustellen.

Sie können die blaugrüne Bereitstellung in Azure-Container-Apps aktivieren, indem Sie Container-Apps-Überarbeitungen, Datenverkehrsgewichte und Überarbeitungsbezeichnungen kombinieren.

Screenshot of Azure Container Apps: Blue/Green deployment.

Sie verwenden Überarbeitungen, um Instanzen der blauen und grünen Versionen der Anwendung zu erstellen.

Revision Beschreibung
Blaue Überarbeitung Die als blau bezeichnete Überarbeitung ist die derzeit ausgeführte und stabile Version der Anwendung. Diese Überarbeitung ist die, mit der Benutzer interagieren, und es ist das Ziel des Produktionsdatenverkehrs.
Grüne Überarbeitung Die als grün bezeichnete Überarbeitung ist eine Kopie der blauen Revision, mit der Ausnahme, dass sie eine neuere Version des App-Codes und möglicherweise neue Umgebungsvariablen verwendet. Er empfängt zunächst keinen Produktionsdatenverkehr, kann aber über einen vollqualifizierten Vollqualifizierten (Fully Qualified Do Standard-Namen (FQDN) zugänglich sein.

Nachdem Sie die neue Revision getestet und überprüft haben, können Sie dann den Produktionsdatenverkehr auf die neue Revision verweisen. Wenn Probleme auftreten, können Sie problemlos ein Rollback auf die vorherige Version ausführen.

Aktionen Beschreibung
Testen und Überprüfen Die grüne Revision wird gründlich getestet und überprüft, um sicherzustellen, dass die neue Version der Anwendung erwartungsgemäß funktioniert. Dieser Test kann verschiedene Aufgaben umfassen, einschließlich Funktionstests, Leistungstests und Kompatibilitätsprüfungen.
Datenverkehrswechsel Sobald die grüne Revision alle erforderlichen Tests bestanden hat, wird eine Verkehrsumschaltung durchgeführt, damit die grüne Revision die Produktionslast bedient. Dieser Schalter erfolgt auf kontrollierte Weise und sorgt für einen reibungslosen Übergang.
Rollback Wenn Probleme in der grünen Revision auftreten, können Sie den Datenverkehrswechsel rückgängig machen und den Datenverkehr zurück zur stabilen blauen Revision weiterleiten. Dieses Rollback sorgt für minimale Auswirkungen auf Benutzer, wenn probleme in der neuen Version auftreten. Die grüne Revision ist für die nächste Bereitstellung weiterhin verfügbar.
Rollenänderung Die Rollen der blauen und grünen Überarbeitungen ändern sich nach einer erfolgreichen Bereitstellung in der grünen Revision. Während des nächsten Releasezyklus stellt die grüne Revision die stabile Produktionsumgebung dar, während die neue Version des Anwendungscodes bereitgestellt und in der blauen Revision getestet wird.

In diesem Artikel erfahren Sie, wie Sie die blaugrüne Bereitstellung in einer Container-App implementieren. Zum Ausführen der folgenden Beispiele benötigen Sie eine Container-App-Umgebung, in der Sie eine neue App erstellen können.

Erstellen einer Container-App mit aktivierten mehreren aktiven Überarbeitungen

Für die Container-App muss die configuration.activeRevisionsMode Eigenschaft festgelegt sein, um die Datenverkehrsteilung zu multiple aktivieren. Um deterministische Revisionsnamen zu erhalten, können Sie die Konfigurationseinstellung auf einen Zeichenfolgenwert festlegen, der template.revisionSuffix eine Version eindeutig identifiziert. Sie können z. B. Buildnummern verwenden oder Git commits kurze Hashes.

Für die folgenden Befehle wurde eine Reihe von Commit-Hashes verwendet.

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

Speichern Sie den folgenden Code in einer Datei mit dem Namen 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

Stellen Sie die App mit der Vorlage "Bicep" mithilfe dieses Befehls bereit:

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

Bereitstellen einer neuen Überarbeitung und Zuweisen von Bezeichnungen

Die blaue Bezeichnung bezieht sich derzeit auf eine Überarbeitung, die den Produktionsdatenverkehr auf den FQDN der App einnimmt. Die grüne Bezeichnung bezieht sich auf eine neue Version einer App, die in der Produktion eingeführt werden soll. Ein neuer Commit-Hash identifiziert die neue Version des App-Codes. Der folgende Befehl stellt eine neue Revision für diesen Commit-Hash bereit und kennzeichnet sie mit grüner Bezeichnung.

#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

Das folgende Beispiel zeigt, wie der Datenverkehrsbereich konfiguriert ist. Die Revision mit dem BlauencommitId nimmt 100 % des Produktionsverkehrs in Anspruch, während die neu bereitgestellte Revision mit GrüncommitId keinen Produktionsverkehr in Anspruch nimmt.

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

Die neu bereitgestellte Revision kann mithilfe des bezeichnungsspezifischen FQDN getestet werden:

#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

Senden des Produktionsdatenverkehrs an die grüne Revision

Nach der Bestätigung, dass der App-Code in der grünen Revision erwartungsgemäß funktioniert, werden 100 % des Produktionsdatenverkehrs an die Revision gesendet. Die grüne Revision wird nun zur Produktionsrevision.

# 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

Das folgende Beispiel zeigt, wie der traffic Abschnitt nach diesem Schritt konfiguriert wird. Die grüne Revision mit dem neuen Anwendungscode akzeptiert den gesamten Benutzerdatenverkehr, während die blaue Überarbeitung mit der alten Anwendungsversion keine Benutzeranforderungen akzeptiert.

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

Zurücksetzen der Bereitstellung, wenn Probleme aufgetreten sind

Wenn nach der Ausführung in der Produktion die neue Überarbeitung fehler enthält, können Sie einen Rollback auf den vorherigen ordnungsgemäßen Zustand durchführen. Nach dem Rollback werden 100 % des Datenverkehrs in der blauen Revision an die alte Version gesendet und diese Revision wird erneut als Produktionsrevision festgelegt.

# 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

Nachdem die Fehler behoben wurden, wird die neue Version der Anwendung erneut als grüne Revision bereitgestellt. Die grüne Version wird schließlich zur Produktionsrevision.

Nächster Bereitstellungszyklus

Jetzt markiert die grüne Bezeichnung die Überarbeitung, die derzeit den stabilen Produktionscode ausführt.

Während des nächsten Bereitstellungszyklus identifiziert blau die Revision mit der neuen Anwendungsversion, die für die Produktion bereitgestellt wird.

Die folgenden Befehle veranschaulichen, wie Sie sich auf den nächsten Bereitstellungszyklus vorbereiten.

# 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

Nächste Schritte