Implementación azul-verde en Azure Container Apps
La implementación azul-verde es una estrategia de lanzamiento de software cuyo objetivo es minimizar el tiempo de inactividad y reducir el riesgo asociado a la implementación de nuevas versiones de una aplicación. En una implementación azul-verde, se configuran dos entornos idénticos, denominados "azul" y "verde". Un entorno (azul) ejecuta la versión actual de la aplicación y un entorno (verde) ejecuta la nueva versión de la aplicación.
Una vez probado el entorno verde, el tráfico activo se dirige a él y el entorno azul se usa para implementar una nueva versión de aplicación durante el siguiente ciclo de implementación.
Puede habilitar la implementación azul-verde en Azure Container Apps combinando revisiones de aplicaciones contenedoras, pesos de tráfico y etiquetas de revisión.
Las revisiones se usan para crear instancias de las versiones azul y verde de la aplicación.
Revision | Descripción |
---|---|
Revisión Azul | La revisión etiquetada como azul es la versión actualmente en ejecución y estable de la aplicación. Esta revisión es con la que interactúan los usuarios y es el destino del tráfico de producción. |
Revisión verde | La revisión etiquetada como verde es una copia de la revisión azul, excepto que usa una versión más reciente del código de la aplicación y posiblemente un nuevo conjunto de variables de entorno. No recibe ningún tráfico de producción inicialmente, pero es accesible a través de un nombre de dominio completo (FQDN) etiquetado. |
Después de probar y comprobar la nueva revisión, puede apuntar el tráfico de producción a la nueva revisión. Si encuentra problemas, puede revertir fácilmente a la versión anterior.
Acciones | Descripción |
---|---|
Pruebas y comprobación | La revisión verde se prueba y comprueba exhaustivamente para asegurarse de que la nueva versión de la aplicación funciona según lo previsto. Esta prueba puede implicar varias tareas, incluidas las pruebas funcionales, las pruebas de rendimiento y las comprobaciones de compatibilidad. |
Cambio de tráfico | Una vez que la revisión verde pasa todas las pruebas necesarias, se realiza un cambio de tráfico para que la revisión verde comience a dar servicio a la carga de producción. Este cambio se realiza de forma controlada, lo que garantiza una transición sin problemas. |
Reversión | Si se producen problemas en la revisión verde, puede revertir el cambio de tráfico, volviendo a enrutar el tráfico a la revisión estable azul. Esta reversión garantiza un impacto mínimo en los usuarios si hay problemas en la nueva versión. La revisión verde sigue estando disponible para la siguiente implementación. |
Cambio de roles | Los roles de las revisiones azules y verdes cambian después de una implementación correcta a la revisión verde. Durante el siguiente ciclo de lanzamiento, la revisión verde representa el entorno de producción estable mientras que la nueva versión del código de la aplicación se implementa y se prueba en la revisión azul. |
En este artículo se muestra cómo implementar la implementación azul-verde en una aplicación contenedora. Para ejecutar los ejemplos siguientes, necesita un entorno de aplicación contenedora donde pueda crear una aplicación.
Nota:
Consulte el repositorio containerapps-blue-green para ver un ejemplo completo de un flujo de trabajo de GitHub que implementa la implementación azul-verde para Container Apps.
Creación de una aplicación contenedora con varias revisiones activas habilitadas
La aplicación contenedora debe tener la propiedad configuration.activeRevisionsMode
establecida en multiple
para habilitar la división del tráfico. Para obtener nombres de revisión deterministas, puede establecer la configuración template.revisionSuffix
en un valor de cadena que identifique de forma unívoca una versión. Por ejemplo, puede usar números de compilación o hashes cortos de confirmaciones de Git.
Para los siguientes comandos, se ha usado un conjunto de hashes de confirmación.
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
Guarde el siguiente código en un archivo llamado 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
Implemente la aplicación con la plantilla de Bicep usando este 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
Implementación de una nueva revisión y asignación de etiquetas
La etiqueta azul se refiere actualmente a una revisión que toma el tráfico de producción que llega al FQDN de la aplicación. La etiqueta verde se refiere a una nueva versión de una aplicación que está a punto de implementarse en producción. Un nuevo hash de confirmación identifica la nueva versión del código de la aplicación. El siguiente comando implementa una nueva revisión para ese hash de confirmación y la marca con la etiqueta 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
El siguiente ejemplo muestra cómo se configura la sección de tráfico. La revisión con el commitId
azul está tomando el 100 % del tráfico de producción mientras que la revisión recién implementada con el commitId
verde no toma ningún tráfico de producción.
{
"traffic": [
{
"revisionName": "<APP_NAME>--fb699ef",
"weight": 100,
"label": "blue"
},
{
"revisionName": "<APP_NAME>--c6f1515",
"weight": 0,
"label": "green"
}
]
}
La revisión recién implementada se puede probar mediante el FQDN específico de la etiqueta:
#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
Envío del tráfico de producción a la revisión verde
Tras confirmar que el código de la aplicación en la revisión verde funciona como se esperaba, el 100 % del tráfico de producción se envía a dicha revisión. La revisión verde se convierte ahora en la revisión de producción.
# 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
El siguiente ejemplo muestra cómo queda configurada la sección traffic
después de este paso. La revisión verde con el código de la nueva aplicación toma todo el tráfico de usuarios mientras que la revisión azul con la versión antigua de la aplicación no acepta solicitudes de usuarios.
{
"traffic": [
{
"revisionName": "<APP_NAME>--fb699ef",
"weight": 0,
"label": "blue"
},
{
"revisionName": "<APP_NAME>--c6f1515",
"weight": 100,
"label": "green"
}
]
}
Reversión de la implementación si hubiera problemas
Si después de ejecutarse en producción, se detecta que la nueva revisión tiene errores, puede revertir al estado correcto anterior. Después de la reversión, el 100 % del tráfico se envía a la versión anterior en la revisión azul y esa revisión se designa de nuevo como revisión de producción.
# 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
Una vez corregidos los errores, la nueva versión de la aplicación se vuelve a implementar como una revisión verde. La versión verde finalmente se convierte en la revisión de producción.
Siguiente ciclo de implementación
Ahora la etiqueta verde marca la revisión que ejecuta actualmente el código de producción estable.
Durante el siguiente ciclo de implementación, el azul identifica la revisión con la nueva versión de la aplicación que se va a implementar en producción.
Los siguientes comandos muestran cómo prepararse para el siguiente ciclo de implementación.
# 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