Implementación azul-verde en Azure Container Apps
Blue-Green Deployment es una estrategia de versión de software que pretende 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 mediante la combinación de revisiones de aplicaciones de contenedor, 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 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. |
Conmutador de tráfico | Una vez que la revisión verde supera todas las pruebas necesarias, se realiza un conmutador de tráfico para que la revisión verde comience a atender la carga de producción. Este modificador 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 conmutador de tráfico, enrutando el tráfico a la revisión azul estable. 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 rol | 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 versión, la revisión verde representa el entorno de producción estable mientras que la nueva versión del código de aplicación se implementa y prueba en la revisión azul . |
En este artículo se muestra cómo implementar la implementación azul-verde en una aplicación de contenedor. Para ejecutar los ejemplos siguientes, necesita un entorno de aplicación de contenedor donde puede crear una aplicación.
Nota:
Consulte el repositorio containerapps-blue-green para obtener 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 establecida en multiple
para habilitar la configuration.activeRevisionsMode
división de tráfico. Para obtener nombres de revisión deterministas, puede establecer la template.revisionSuffix
configuración en un valor de cadena que identifica de forma única una versión. Por ejemplo, puede usar números de compilación o git confirma hashes cortos.
Para los comandos siguientes, se usó 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 código siguiente en un archivo denominado 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 mediante 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 hace referencia actualmente a una revisión que toma el tráfico de producción que llega al FQDN de la aplicación. La etiqueta verde hace referencia 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 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
En el ejemplo siguiente se muestra cómo se configura la sección de tráfico. La revisión con el azulcommitId
está tomando el 100 % del tráfico de producción, mientras que la revisión recién implementada con verdecommitId
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 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
Envío del tráfico de producción a la revisión verde
Después de confirmar que el código de la aplicación en la revisión verde funciona según lo previsto, el 100 % del tráfico de producción se envía a la revisión. La revisión verde ahora se convierte 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
En el ejemplo siguiente se muestra cómo se configura la traffic
sección después de este paso. La revisión verde con el nuevo código de aplicación toma todo el tráfico de usuario mientras que la revisión azul con la versión anterior de la aplicación no acepta solicitudes de usuario.
{
"traffic": [
{
"revisionName": "<APP_NAME>--fb699ef",
"weight": 0,
"label": "blue"
},
{
"revisionName": "<APP_NAME>--c6f1515",
"weight": 100,
"label": "green"
}
]
}
Revertir la implementación si hay 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