Share via


Blågrön distribution i Azure Container Apps

Blue-Green Deployment är en strategi för programvarulansering som syftar till att minimera stilleståndstiden och minska risken för att distribuera nya versioner av ett program. I en blågrön distribution konfigureras två identiska miljöer som kallas "blå" och "gröna". En miljö (blå) kör den aktuella programversionen och en miljö (grön) kör den nya programversionen.

När den gröna miljön har testats dirigeras den aktiva trafiken till den och den blå miljön används för att distribuera en ny programversion under nästa distributionscykel.

Du kan aktivera blågrön distribution i Azure Container Apps genom att kombinera revisioner av containerappar, trafikvikter och revisionsetiketter.

Screenshot of Azure Container Apps: Blue/Green deployment.

Du använder revisioner för att skapa instanser av de blå och gröna versionerna av programmet.

Ändring Description
Blå revision Revisionen som är märkt som blå är den aktuella och stabila versionen av programmet. Den här revisionen är den som användarna interagerar med, och det är målet för produktionstrafiken.
Grön revision Revisionen som är märkt som grön är en kopia av den blå revisionen, förutom att den använder en nyare version av appkoden och eventuellt en ny uppsättning miljövariabler. Den tar inte emot någon produktionstrafik från början men är tillgänglig via ett märkt fullständigt kvalificerat domännamn (FQDN).

När du har testat och verifierat den nya revisionen kan du sedan peka produktionstrafik till den nya revisionen. Om du stöter på problem kan du enkelt återställa till den tidigare versionen.

Åtgärder Description
Testning och verifiering Den gröna revisionen testas noggrant och verifieras för att säkerställa att den nya versionen av programmet fungerar som förväntat. Den här testningen kan omfatta olika uppgifter, inklusive funktionella tester, prestandatester och kompatibilitetskontroller.
Trafikväxel När den gröna revisionen har godkänt alla nödvändiga tester utförs en trafikväxel så att den gröna revisionen börjar hantera produktionsbelastningen. Den här växeln görs på ett kontrollerat sätt, vilket säkerställer en smidig övergång.
Återställning Om det uppstår problem i den gröna revisionen kan du återställa trafikomkopplaren och dirigera trafiken tillbaka till den stabila blå revisionen. Den här återställningen garanterar minimal påverkan på användare om det finns problem i den nya versionen. Den gröna revisionen är fortfarande tillgänglig för nästa distribution.
Rolländring Rollerna för de blå och gröna revisionerna ändras efter en lyckad distribution till den gröna revisionen. Under nästa versionscykel representerar den gröna revisionen den stabila produktionsmiljön medan den nya versionen av programkoden distribueras och testas i den blå revisionen.

Den här artikeln visar hur du implementerar blågrön distribution i en containerapp. Om du vill köra följande exempel behöver du en containerappmiljö där du kan skapa en ny app.

Kommentar

Se containerapps-blue-green-lagringsplatsen för ett fullständigt exempel på ett GitHub-arbetsflöde som implementerar blågrön distribution för Container Apps.

Skapa en containerapp med flera aktiva revisioner aktiverade

Containerappen måste ha egenskapen configuration.activeRevisionsMode inställd på multiple för att aktivera trafikdelning. Om du vill hämta deterministiska revisionsnamn kan du ange konfigurationsinställningen template.revisionSuffix till ett strängvärde som unikt identifierar en version. Du kan till exempel använda byggnummer eller git-incheckningar för korta hashvärden.

För följande kommandon användes en uppsättning incheckningshashvärden.

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

Spara följande kod i en fil med namnet 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

Distribuera appen med Bicep-mallen med det här kommandot:

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

Distribuera en ny revision och tilldela etiketter

Den blå etiketten refererar för närvarande till en revision som tar produktionstrafiken som kommer till appens FQDN. Den gröna etiketten refererar till en ny version av en app som håller på att distribueras till produktion. En ny incheckningshash identifierar den nya versionen av appkoden. Följande kommando distribuerar en ny revision för incheckningshash och markerar den med grön etikett.

#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

I följande exempel visas hur trafikavsnittet konfigureras. Revisionen med det blåcommitId tar 100 % av produktionstrafiken medan den nyligen distribuerade revisionen med gröntcommitId inte tar någon produktionstrafik.

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

Den nyligen distribuerade revisionen kan testas med hjälp av det etikettspecifika FQDN:

#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

Skicka produktionstrafik till den gröna revisionen

När du har bekräftat att appkoden i den gröna revisionen fungerar som förväntat skickas 100 % av produktionstrafiken till revisionen. Den gröna revisionen blir nu produktionsrevisionen.

# 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

I följande exempel visas hur avsnittet traffic konfigureras efter det här steget. Den gröna revisionen med den nya programkoden tar all användartrafik medan blå revision med den gamla programversionen inte accepterar användarbegäranden.

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

Återställa distributionen om det fanns problem

Om den nya revisionen visar sig ha buggar när den har körts i produktion kan du återställa till det tidigare goda tillståndet. Efter återställningen skickas 100 % av trafiken till den gamla versionen i den blå revisionen och den revisionen utses som produktionsrevision igen.

# 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

När buggarna har åtgärdats distribueras den nya versionen av programmet som en grön revision igen. Den gröna versionen blir så småningom produktionsrevisionen.

Nästa distributionscykel

Nu markerar den gröna etiketten revisionen som för närvarande kör den stabila produktionskoden.

Under nästa distributionscykel identifierar det blå revisionen med den nya programversionen som distribueras till produktion.

Följande kommandon visar hur du förbereder dig för nästa distributionscykel.

# 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ästa steg