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.
Vous utilisez des révisions pour créer des instances des versions bleues et vertes de l’application.
Revision | Description |
---|---|
Révision bleue | 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 il s’agit de la cible du trafic de production. |
Révision verte | 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 initialement, mais est accessible via un nom de domaine complet étiqueté (FQDN). |
Après avoir testé et vérifié la nouvelle révision, vous pouvez ensuite pointer 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. Ce test peut impliquer différentes tâches, notamment les tests fonctionnels, les tests de performances et les case activée 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 commutateur est effectué de manière contrôlée, ce qui garantit une transition fluide. |
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. Cette restauration garantit un impact minimal 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 explique comment implémenter un déploiement bleu-vert dans une application conteneur. Pour exécuter les exemples suivants, vous avez besoin d’un environnement d’application conteneur dans lequel vous pouvez créer une 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 la propriété définie pour multiple
activer le configuration.activeRevisionsMode
fractionnement du trafic. Pour obtenir des noms de révision déterministes, vous pouvez définir le template.revisionSuffix
paramètre de configuration sur une valeur de chaîne qui identifie de manière unique une version. Par exemple, vous pouvez utiliser des numéros de build ou valider des hachages courts.
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 affecter 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 hachage de validation 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 du 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 révision nouvellement déployée peut être testée à l’aide du nom de domaine complet 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 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
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 traffic
section 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"
}
]
}
Restaurer le déploiement en cas de problèmes
Si, après l’exécution en production, la nouvelle révision est trouvée pour avoir des bogues, vous pouvez revenir à l’état correct précédent. 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 se préparer au 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