Partager via


Déploiement bleu-vert dans Azure Container Apps

Le déploiement bleu-vert est une stratégie de mise en production logicielle qui vise à réduire les temps d’arrêt et à réduire le risque associé au déploiement de nouvelles versions d’une application. Dans un déploiement bleu-vert, deux environnements identiques, appelés "bleu" et "vert", sont configurés. Un environnement (bleu) exécute la version actuelle de l’application et un environnement (vert) exécute la nouvelle version de l’application.

Une fois l’environnement vert testé, le trafic actif est dirigé vers celui-ci et l’environnement bleu est utilisé pour déployer une nouvelle version d’application pendant le prochain cycle de déploiement.

Vous pouvez activer le déploiement bleu-vert dans Azure Container Apps en combinant les révisions d’applications conteneur, les pondérations du trafic et les étiquettes de révision.

Capture d’écran d'Azure Container Apps : déploiement bleu-vert.

Vous utilisez les révisions pour créer des instances des versions bleue et verte de l'application.

Revision Description
Révision bleu La révision étiquetée en bleu est la version en cours d’exécution et stable de l’application. Cette révision est celle avec laquelle les utilisateurs interagissent, et c'est la cible du trafic de production.
Révision vert La révision étiquetée en vert est une copie de la révision bleue, sauf qu’elle utilise une version plus récente du code de l’application et éventuellement un nouvel ensemble de variables d’environnement. Il ne reçoit pas de trafic de production au départ, mais il est accessible via un nom de domaine entièrement qualifié (FQDN).

Après avoir testé et vérifié la nouvelle révision, vous pouvez orienter le trafic de production vers la nouvelle révision. Si vous rencontrez des problèmes, vous pouvez facilement revenir à la version précédente.

Actions Description
Test et vérification La révision verte est soigneusement testée et vérifiée pour s’assurer que la nouvelle version des fonctions d’application comme prévu. Ces tests peuvent comporter diverses tâches, notamment des tests fonctionnels, des tests de performance et des contrôles de compatibilité.
Commutateur de trafic Une fois que la révision verte réussit tous les tests nécessaires, un commutateur de trafic est effectué afin que la révision verte commence à traiter la charge de production. Ce changement est effectué de manière contrôlée, ce qui garantit une transition en douceur.
Restauration Si des problèmes se produisent dans la révision verte, vous pouvez rétablir le commutateur de trafic, en réacheminant le trafic vers la révision bleue stable. Ce retour en arrière permet de minimiser l'impact sur les utilisateurs en cas de problèmes dans la nouvelle version. La révision verte est toujours disponible pour le déploiement suivant.
Modification du rôle Les rôles des révisions bleues et vertes changent après un déploiement réussi vers la révision verte. Au cours du prochain cycle de mise en production, la révision verte représente l’environnement de production stable pendant que la nouvelle version du code d’application est déployée et testée dans la révision bleue.

Cet article vous montre comment mettre en œuvre le déploiement bleu-vert dans une application conteneurisée. Pour exécuter les exemples suivants, vous avez besoin d'un environnement de conteneur d'applications dans lequel vous pouvez créer une nouvelle application.

Remarque

Reportez-vous au référentiel containerapps-blue-green pour obtenir un exemple complet d’un flux de travail GitHub qui implémente un déploiement bleu-vert pour Container Apps.

Créer une application conteneur avec plusieurs révisions actives activées

L’application conteneur doit avoir le jeu de propriétés configuration.activeRevisionsMode défini sur multiple pour activer le fractionnement du trafic. Pour obtenir des noms de révision déterministes, vous pouvez définir le paramètre de configuration template.revisionSuffix sur une valeur de chaîne qui identifie de manière unique une version. Par exemple, vous pouvez utiliser les numéros de build, ou les hachages courts des commits git.

Pour les commandes suivantes, un ensemble de hachages de validation a été utilisé.

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

Enregistrez le code suivant dans un fichier nommé 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

Déployez l’application avec le modèle Bicep à l'aide de cette commande :

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

Déployer une nouvelle révision et attribuer des étiquettes

L’étiquette bleue fait actuellement référence à une révision qui prend le trafic de production arrivant sur le nom de domaine complet de l’application. L’étiquette verte fait référence à une nouvelle version d’une application sur le point d’être déployée en production. Un nouveau hash de commit identifie la nouvelle version du code de l'application. La commande suivante déploie une nouvelle révision pour ce hachage de validation et la marque avec une étiquette verte.

#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

L'exemple suivant montre comment la section trafic est configurée. La révision avec le bleucommitId prend 100 % du trafic de production alors que la révision nouvellement déployée avec vertcommitId ne prend pas de trafic de production.

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

La nouvelle révision déployée peut être testée en utilisant le FQDN spécifique à l'étiquette :

#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 label FQDN
curl -s https://$APP_NAME---blue.$APP_DOMAIN/api/env | jq | grep COMMIT

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

Envoyer le trafic de production à la révision verte

Après avoir confirmé que le code de l’application dans la révision verte fonctionne comme prévu, 100 % du trafic de production est envoyé à la révision. La révision verte devient désormais la révision de production.

# 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

L'exemple suivant montre comment la section traffic est configurée après cette étape. La révision verte avec le nouveau code d’application prend tout le trafic utilisateur tandis que la révision bleue avec l’ancienne version de l’application n’accepte pas les demandes utilisateur.

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

Revenir sur le déploiement en cas de problème

Si, après avoir été mise en production, la nouvelle révision présente des bogues, vous pouvez revenir à l'état antérieur. Après la restauration, 100 % du trafic est envoyé à l’ancienne version de la révision bleue et cette révision est désignée comme révision de production à nouveau.

# 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

Une fois les bogues corrigés, la nouvelle version de l’application est déployée à nouveau en tant que révision verte. La version verte devient finalement la révision de production.

Cycle de déploiement suivant

À présent, l’étiquette verte marque la révision qui exécute actuellement le code de production stable.

Au cours du prochain cycle de déploiement, le bleu identifie la révision avec la nouvelle version de l’application déployée en production.

Les commandes suivantes montrent comment préparer le prochain cycle de déploiement.

# 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

Étapes suivantes