Blue-Green Deployment in Azure Container Apps

Blue-Green Deployment to strategia wydawania oprogramowania, która ma na celu zminimalizowanie przestojów i zmniejszenie ryzyka związanego z wdrażaniem nowych wersji aplikacji. W przypadku wdrożenia niebiesko-zielonych konfigurowane są dwa identyczne środowiska, nazywane "niebieskim" i "zielonym". Jedno środowisko (niebieskie) uruchamia bieżącą wersję aplikacji, a jedno środowisko (zielone) uruchamia nową wersję aplikacji.

Po przetestowaniu środowiska zielony ruch na żywo jest kierowany do niego, a niebieskie środowisko służy do wdrażania nowej wersji aplikacji podczas następnego cyklu wdrażania.

Wdrożenie niebiesko-zielone w usłudze Azure Container Apps można włączyć, łącząc poprawki aplikacji kontenera, wagi ruchu i etykiety poprawek.

Screenshot of Azure Container Apps: Blue/Green deployment.

Poprawki służą do tworzenia wystąpień aplikacji w kolorze niebieskim i zielonym.

Wersja opis
Niebieska poprawka Wersja oznaczona jako niebieska jest aktualnie uruchomiona i stabilna wersja aplikacji. Ta poprawka jest taka, z którą użytkownicy korzystają, i jest to cel ruchu produkcyjnego.
Zielona poprawka Poprawka oznaczona jako zielona jest kopią niebieskiej poprawki, z wyjątkiem nowszej wersji kodu aplikacji i ewentualnie nowego zestawu zmiennych środowiskowych. Początkowo nie odbiera żadnego ruchu produkcyjnego, ale jest dostępny za pośrednictwem w pełni kwalifikowanej nazwy domeny (FQDN).

Po przetestowaniu i zweryfikowaniu nowej poprawki można następnie wskazać ruch produkcyjny do nowej poprawki. Jeśli wystąpią problemy, możesz łatwo przywrócić poprzednią wersję.

Akcje opis
Testowanie i weryfikacja Zielona wersja jest dokładnie przetestowana i zweryfikowana, aby upewnić się, że nowa wersja aplikacji działa zgodnie z oczekiwaniami. Te testy mogą obejmować różne zadania, w tym testy funkcjonalne, testy wydajnościowe i testy zgodności.
Przełącznik ruchu Gdy zielona poprawka przejdzie wszystkie niezbędne testy, zostanie wykonany przełącznik ruchu, aby zielona poprawka zaczyna obsługiwać obciążenie produkcyjne. Ten przełącznik jest wykonywany w kontrolowany sposób, zapewniając płynne przejście.
Wycofywanie Jeśli wystąpią problemy w zielonej wersji, możesz przywrócić przełącznik ruchu, rozsyłając ruch z powrotem do stabilnej niebieskiej poprawki. Wycofanie zapewnia minimalny wpływ na użytkowników, jeśli występują problemy w nowej wersji. Zielona wersja jest nadal dostępna dla następnego wdrożenia.
Zmiana roli Role niebieskich i zielonych poprawek zmieniają się po pomyślnym wdrożeniu do zielonej poprawki. Podczas następnego cyklu wydania zielona poprawka reprezentuje stabilne środowisko produkcyjne, podczas gdy nowa wersja kodu aplikacji jest wdrażana i testowana w niebieskiej wersji.

W tym artykule pokazano, jak zaimplementować wdrożenie niebiesko-zielone w aplikacji kontenera. Aby uruchomić poniższe przykłady, potrzebujesz środowiska aplikacji kontenera, w którym można utworzyć nową aplikację.

Uwaga

Zapoznaj się z repozytorium containerapps-blue-green, aby zapoznać się z kompletnym przykładem przepływu pracy usługi GitHub, który implementuje niebieskie-zielone wdrożenie dla usługi Container Apps.

Tworzenie aplikacji kontenera z włączonymi wieloma aktywnymi wersjami

Aplikacja kontenera musi mieć właściwość ustawioną configuration.activeRevisionsMode na , aby multiple umożliwić dzielenie ruchu. Aby uzyskać nazwy poprawek deterministycznych, możesz ustawić template.revisionSuffix ustawienie konfiguracji na wartość ciągu, która jednoznacznie identyfikuje wydanie. Możesz na przykład użyć numerów kompilacji lub skrótów skrótów krótkich zatwierdzeń usługi Git.

W przypadku następujących poleceń użyto zestawu skrótów zatwierdzeń.

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

Zapisz następujący kod w pliku o nazwie 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

Wdróż aplikację przy użyciu szablonu Bicep przy użyciu tego polecenia:

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

Wdrażanie nowej poprawki i przypisywanie etykiet

Niebieska etykieta obecnie odwołuje się do poprawki, która pobiera ruch produkcyjny przychodzący do nazwy FQDN aplikacji. Zielona etykieta odnosi się do nowej wersji aplikacji, która ma zostać wdrożona w środowisku produkcyjnym. Nowy skrót zatwierdzenia identyfikuje nową wersję kodu aplikacji. Następujące polecenie wdraża nową poprawkę dla tego skrótu zatwierdzenia i oznacza ją zieloną etykietą.

#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

W poniższym przykładzie pokazano, jak skonfigurowano sekcję ruchu. Poprawka z niebieskim commitId przyjmuje 100% ruchu produkcyjnego, podczas gdy nowo wdrożona poprawka z kolorem zielonymcommitId nie przyjmuje żadnego ruchu produkcyjnego.

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

Nowo wdrożona poprawka może zostać przetestowana przy użyciu nazwy FQDN specyficznej dla etykiety:

#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

Wysyłanie ruchu produkcyjnego do zielonej poprawki

Po potwierdzeniu, że kod aplikacji w zielonej wersji działa zgodnie z oczekiwaniami, do poprawki jest wysyłany 100% ruchu produkcyjnego. Zielona poprawka staje się teraz poprawką produkcyjną.

# 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

W poniższym przykładzie pokazano, jak traffic sekcja jest skonfigurowana po tym kroku. Zielona poprawka z nowym kodem aplikacji pobiera cały ruch użytkownika, podczas gdy niebieska poprawka ze starą wersją aplikacji nie akceptuje żądań użytkowników.

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

Wycofywanie wdrożenia, jeśli wystąpiły problemy

Jeśli po uruchomieniu w środowisku produkcyjnym zostanie znaleziona nowa poprawka, możesz przywrócić poprzedni dobry stan. Po wycofaniu 100% ruchu jest wysyłanych do starej wersji w niebieskiej wersji i ta poprawka zostanie ponownie wyznaczona jako wersja produkcyjna.

# 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

Po naprawieniu usterek nowa wersja aplikacji zostanie ponownie wdrożona jako zielona poprawka. Zielona wersja ostatecznie stanie się wersją produkcyjną.

Następny cykl wdrażania

Teraz zielona etykieta oznacza poprawkę, która obecnie uruchamia stabilny kod produkcyjny.

W następnym cyklu wdrażania niebieski identyfikuje poprawkę z nową wersją aplikacji wdrażaną w środowisku produkcyjnym.

Poniższe polecenia pokazują, jak przygotować się do następnego cyklu wdrażania.

# 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

Następne kroki