Azure Container Apps'te Mavi-Yeşil Dağıtım

Mavi-Yeşil Dağıtım , kapalı kalma süresini en aza indirmeyi ve bir uygulamanın yeni sürümlerini dağıtma riskini azaltmayı hedefleyen bir yazılım sürümü stratejisidir. Mavi-yeşil dağıtımda, "mavi" ve "yeşil" olarak adlandırılan iki özdeş ortam ayarlanır. Bir ortam (mavi) geçerli uygulama sürümünü çalıştırıyor ve bir ortam (yeşil) yeni uygulama sürümünü çalıştırıyor.

Yeşil ortam test edildikten sonra canlı trafik buna yönlendirilir ve mavi ortam bir sonraki dağıtım döngüsü sırasında yeni bir uygulama sürümü dağıtmak için kullanılır.

Azure Container Apps'te kapsayıcı uygulamaları düzeltmelerini, trafik ağırlıklarını ve düzeltme etiketlerini birleştirerek mavi-yeşil dağıtımı etkinleştirebilirsiniz.

Azure Container Apps: Mavi/Yeşil dağıtımının ekran görüntüsü.

Düzeltmeleri, uygulamanın mavi ve yeşil sürümlerinin örneklerini oluşturmak için kullanırsınız.

Revizyon Açıklama
Mavi düzeltme Mavi olarak etiketlenen düzeltme, uygulamanın şu anda çalışan ve kararlı sürümüdür. Bu düzeltme, kullanıcıların etkileşimde olduğu düzeltmedir ve üretim trafiğinin hedefidir.
Yeşil düzeltme Yeşil olarak etiketlenen düzeltme, mavi düzeltmenin bir kopyasıdır, ancak uygulama kodunun daha yeni bir sürümünü ve muhtemelen yeni ortam değişkenlerini kullanır. Başlangıçta herhangi bir üretim trafiği almaz, ancak tam etki alanı adı (FQDN) etiketli bir adla erişilebilir.

Yeni düzeltmeyi test edip doğruladıktan sonra üretim trafiğini yeni düzeltmeye işaret edebilirsiniz. Sorunlarla karşılaşırsanız, önceki sürüme kolayca geri dönebilirsiniz.

Eylemler Açıklama
Test ve doğrulama Yeşil düzeltme, uygulamanın yeni sürümünün beklendiği gibi çalıştığından emin olmak için kapsamlı bir şekilde test edilir ve doğrulanır. Bu test işlevsel testler, performans testleri ve uyumluluk denetimleri gibi çeşitli görevleri içerebilir.
Trafik anahtarı Yeşil düzeltme tüm gerekli testleri geçtikten sonra, yeşil düzeltmenin üretim yüküne hizmetmeye başlaması için bir trafik anahtarı gerçekleştirilir. Bu anahtar denetimli bir şekilde yapılır ve sorunsuz bir geçiş sağlar.
Geri alma Yeşil düzeltmede sorun oluşursa trafik anahtarını geri döndürerek trafiği kararlı mavi düzeltmeye yönlendirebilirsiniz. Bu geri alma işlemi, yeni sürümde sorunlar varsa kullanıcılar üzerinde en az etkiyi sağlar. Yeşil düzeltme bir sonraki dağıtım için hala kullanılabilir.
Rol değişikliği Mavi ve yeşil düzeltmelerin rolleri, yeşil düzeltmeye başarılı bir dağıtımdan sonra değişir. Bir sonraki sürüm döngüsü sırasında yeşil düzeltme, uygulama kodunun yeni sürümü mavi düzeltmede dağıtılır ve test edilirken kararlı üretim ortamını temsil eder.

Bu makalede, bir kapsayıcı uygulamasında mavi-yeşil dağıtımı nasıl uygulayabileceğiniz gösterilmektedir. Aşağıdaki örnekleri çalıştırmak için yeni bir uygulama oluşturabileceğiniz bir kapsayıcı uygulaması ortamına ihtiyacınız vardır.

Birden çok etkin düzeltme etkinleştirilmiş bir kapsayıcı uygulaması oluşturma

Trafik bölmeyi etkinleştirmek için kapsayıcı uygulamasının configuration.activeRevisionsMode özelliği olarak multiple ayarlanmış olmalıdır. Belirleyici düzeltme adlarını almak için yapılandırma ayarını bir yayını benzersiz olarak tanımlayan bir dize değerine ayarlayabilirsiniz template.revisionSuffix . Örneğin, derleme numaralarını kullanabilir veya git kısa karmaları işleyebilir.

Aşağıdaki komutlar için bir işleme karmaları kümesi kullanılmıştır.

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

Aşağıdaki kodu adlı main.bicepbir dosyaya kaydedin.

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

Şu komutu kullanarak uygulamayı Bicep şablonuyla dağıtın:

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

Yeni bir düzeltme dağıtma ve etiket atama

Mavi etiket şu anda uygulamanın FQDN'sine gelen üretim trafiğini alan bir düzeltmeye başvuruyor. Yeşil etiket, bir uygulamanın üretime sunulmak üzere olan yeni bir sürümünü ifade eder. Yeni bir işleme karması, uygulama kodunun yeni sürümünü tanımlar. Aşağıdaki komut, bu işleme karması için yeni bir düzeltme dağıtır ve bunu yeşil etiketle işaretler.

#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

Aşağıdaki örnekte trafik bölümünün nasıl yapılandırıldığı gösterilmektedir. Maviyle commitId yapılan düzeltme, üretim trafiğinin %100'ünün alınmasına karşın, yeni dağıtılan yeşil commitId düzeltme herhangi bir üretim trafiğini almaz.

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

Yeni dağıtılan düzeltme, etikete özgü FQDN kullanılarak test edilebilir:

#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

Üretim trafiğini yeşil düzeltmeye gönderme

Yeşil düzeltmedeki uygulama kodunun beklendiği gibi çalıştığını onayladıktan sonra, üretim trafiğinin %100'ünün düzeltmeye gönderilir. Yeşil düzeltme artık üretim düzeltmesi olur.

# 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

Aşağıdaki örnekte bölümün bu adımdan traffic sonra nasıl yapılandırıldığı gösterilmektedir. Yeni uygulama koduyla yeşil düzeltme tüm kullanıcı trafiğini alır, ancak eski uygulama sürümüyle yapılan mavi düzeltme kullanıcı isteklerini kabul etmez.

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

Sorun varsa dağıtımı geri alma

Üretimde çalıştırıldıktan sonra yeni düzeltmede hata olduğu tespit edilirse önceki iyi duruma geri dönebilirsiniz. Geri alma sonrasında trafiğin %100'ünün mavi düzeltmede eski sürüme gönderilmesi ve bu düzeltmenin yeniden üretim düzeltmesi olarak belirlenmiş olması.

# 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

Hatalar düzeltildikten sonra uygulamanın yeni sürümü yeniden yeşil düzeltme olarak dağıtılır. Yeşil sürüm sonunda üretim düzeltmesi haline gelir.

Sonraki dağıtım döngüsü

Şimdi yeşil etiket, kararlı üretim kodunu çalıştıran düzeltmeyi işaretler.

Sonraki dağıtım döngüsü sırasında mavi, yeni uygulama sürümünün üretime dağıtılmasıyla düzeltmeyi tanımlar.

Aşağıdaki komutlar, bir sonraki dağıtım döngüsüne nasıl hazırlanacaklarını gösterir.

# 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

Sonraki adımlar