次の方法で共有


チュートリアル: Kubernetes 向けカナリア デプロイ戦略

Azure DevOps Services | Azure DevOps Server 2022

この段階的なガイドは、canary 戦略で Kubernetes マニフェスト タスクを使用する方法を説明します。 カナリア デプロイ戦略は、アプリケーションの新しいバージョンを安定した次の運用バージョンの隣にデプロイします。

関連するワークフローを使用してコードをデプロイし、ベースラインとカナリア アプリのデプロイを比較します。 評価に基づいて、カナリア デプロイを昇格または拒否するかどうかを決定します。

このチュートリアルでは、Docker Registry と Azure Resource Manager サービス接続を使用して Azure リソースに接続します。 Azure Kubernetes Service (AKS) プライベート クラスターまたはローカル アカウントが無効になっているクラスターの場合は、Azure Resource Managerサービス接続は、より適切な接続方法です。

前提条件

GitHub リポジトリ ファイル

GitHub リポジトリには、次のファイルが含まれています。

ファイル 説明
./app/app.py Flask ベースのシンプルな Web サーバー。 このファイルは、success_rate 変数の値に基づいて、良い応答と悪い応答の数のカスタム カウンタを設定します。
./app/Dockerfile app.py に変更するたびにイメージをビルドするために使用されます。 変更が発生するたびに、ビルド パイプラインがトリガーされ、イメージがビルドされ、コンテナー レジストリにプッシュされます。
./manifests/deployment.yml 公開イメージに対応する sampleappデプロイ ワークロードの仕様が含まれます。 このマニフェスト ファイルは、デプロイ オブジェクトの安定バージョンと、ワークロードのベースラインとカナリアのバリアントを派生させるために使用します。
./manifests/service.yml sampleapp サービスを作成します。 このサービスは、安定版、ベースライン、およびカナリア デプロイによってスピンアップされたポッドにリクエストをルーティングします。
./misc/fortio.yml fortio デプロイを設定します。 このデプロイは、デプロイされた sampleapp サービスに要求のストリームを送信するロード テスト ツールです。 リクエスト ストリームは、安定版、ベースライン、カナリアの 3 つのデプロイメントのポッドにルーティングされます。

サービス接続を作成する

  1. Azure DevOps のプロジェクトで、[プロジェクト設定]>[パイプライン]>[サービス接続] の順に選択します。
  2. Azure Container Registry インスタンスに関連付けられている azure-pipelines-canary-acr という名前の Docker Registry サービス接続を作成します。
  3. リソース グループに対して、azure-pipelines-canary-k8s という名前のワークロード ID を使用して Azure Resource Manager サービス接続を作成します。

ビルド ステージを追加する

  1. Azure DevOps プロジェクトで、[パイプライン]>[パイプラインを作成] または [新規パイプライン] の順に選択します。

  2. コードの場所として、[Github] を選択し、フォーク下 azure-pipelines-canary-k8s リポジトリを選択します。

  3. [構成] タブで、[スタート パイプライン] を選びます。

  4. [レビュー] タブで、パイプライン YAML を次のコードに置き換えます。

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      imageName: azure-pipelines-canary-k8s # name of ACR image
      dockerRegistryServiceConnection: azure-pipelines-canary-acr # name of ACR service connection
      imageRepository: 'azure-pipelines-canary-k8s' # name of image repository
      containerRegistry: example.azurecr.io # name of Azure container registry
      tag: '$(Build.BuildId)'
    
    stages:
    - stage: Build
      displayName: Build stage
      jobs:  
      - job: Build
        displayName: Build
        pool:
          vmImage: ubuntu-latest
        steps:
        - task: Docker@2
          displayName: Build and push image
          inputs:
            containerRegistry: $(dockerRegistryServiceConnection)
            repository: $(imageName)
            command: buildAndPush
            Dockerfile: app/Dockerfile
            tags: |
              $(tag)
    

    作成した Docker レジストリ サービス接続が、example.azurecr.io という名前のコンテナ レジストリに関連付けられている場合、イメージは example.azurecr.io/azure-pipelines-canary-k8s:$(Build.BuildId) に設定されます。

  5. [保存して実行] を選択して、ジョブが正常に実行されているか確認します。

サービス マニフェスト ファイルを編集する

リポジトリ フォークで、manifests/deployment.yml を編集して、<foobar>example.azurecr.io/azure-pipelines-canary-k8s などの コンテナー レジストリの URL に置き換えます。

Azure App Service での GIT による継続的なデプロイ

次に、継続的デプロイを設定し、カナリア ステージをデプロイし、手動承認でカナリアを昇格または拒否します。

環境の作成

YAML またはクラシックを使ってデプロイできます。

  1. Azure DevOps プロジェクトで、[パイプライン]>[環境] の順に選択し、[環境を作成] または [新規環境] の順に選択します。
  2. 最初の [新規環境] 画面の [名前]akscanary と入力し、[リソース][Kubernetes] を選択し、[次へ] を選択します。
  3. [Kubernetes リソース] 画面で次のように入力します。
    • プロバイダー: Azure Kubernetes サービス を選択します。
    • Azure サブスクリプション: Azure サブスクリプションを選択します。
    • クラスター: AKS クラスターを選択します。
    • 名前空間: [新規] を選択し、canarydemo と入力します。
  4. [検証と作成] を選択します。

カナリア ステージを追加する

  1. [パイプライン] に移動し、作成したパイプラインを選択したら、[編集] を選択します。

  2. パイプライン YAML 全体を次のコードに置き換えます。

    このコードは、ステージを使用するために前に実行した Docker@2 ステップを変更し、マニフェストと misc ディレクトリを連続して使用するアーティファクトとしてコピーする 2 つの手順を追加します。

    また、このコードでは、パイプラインの後半で使用しやすくするために、いくつかの値を変数に移動します。 containerRegistry 変数で、<example> をコンテナ レジストリの名前に置き換えます。

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      imageName: azure-pipelines-canary-k8s
      dockerRegistryServiceConnection: azure-pipelines-canary-acr
      imageRepository: 'azure-pipelines-canary-k8s'
      containerRegistry: <example>.azurecr.io
      tag: '$(Build.BuildId)'
    
    stages:
    - stage: Build
      displayName: Build stage
      jobs:  
      - job: Build
        displayName: Build
        pool:
          vmImage: ubuntu-latest
        steps:
        - task: Docker@2
          displayName: Build and push image
          inputs:
            containerRegistry: $(dockerRegistryServiceConnection)
            repository: $(imageName)
            command: buildAndPush
            Dockerfile: app/Dockerfile
            tags: |
              $(tag)
    
        - publish: manifests
          artifact: manifests
    
        - publish: misc
          artifact: misc
    
  3. YAML ファイルの最後に別のステージを追加して、カナリア バージョンをデプロイします。 my-resource-group および my-aks-cluster は、実際のリソース グループと Azure Kubernetes Service クラスター名に置き換えてください。

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      imageName: azure-pipelines-canary-k8s
      dockerRegistryServiceConnection: azure-pipelines-canary-acr
      imageRepository: 'azure-pipelines-canary-k8s'
      containerRegistry: yourcontainerregistry.azurecr.io #update with container registry
      tag: '$(Build.BuildId)'
    
    stages:
    - stage: Build
      displayName: Build stage
      jobs:  
      - job: Build
        displayName: Build
        pool:
          vmImage: ubuntu-latest
        steps:
        - task: Docker@2
          displayName: Build and push image
          inputs:
            containerRegistry: $(dockerRegistryServiceConnection)
            repository: $(imageName)
            command: buildAndPush
            Dockerfile: app/Dockerfile
            tags: |
              $(tag)
    
        - publish: manifests
          artifact: manifests
    
        - publish: misc
          artifact: misc
    
    - stage: DeployCanary
      displayName: Deploy canary
      dependsOn: Build
      condition: succeeded()
    
      jobs:
      - deployment: Deploycanary
        displayName: Deploy canary
        pool:
          vmImage: ubuntu-latest
        environment: 'akscanary'
        strategy:
          runOnce:
            deploy:
              steps:
              - task: KubernetesManifest@1
                displayName: Create Docker Registry Secret
                inputs:
                  action: 'createSecret'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  secretType: 'dockerRegistry'
                  secretName: 'my-acr-secret'
                  dockerRegistryEndpoint: 'azure-pipelines-canary-acr'
    
              - task: KubernetesManifest@1
                displayName: Deploy to Kubernetes cluster
                inputs:
                  action: 'deploy'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  strategy: 'canary'
                  percentage: '25'
                  manifests: |
                    $(Pipeline.Workspace)/manifests/deployment.yml
                    $(Pipeline.Workspace)/manifests/service.yml
                  containers: '$(containerRegistry)/$(imageRepository):$(tag)'
                  imagePullSecrets: 'my-acr-secret'
    
              - task: KubernetesManifest@1
                displayName: Deploy Forbio to Kubernetes cluster
                inputs:
                  action: 'deploy'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  manifests: '$(Pipeline.Workspace)/misc/*'
    
  4. [検証して保存] を選択して、パイプラインを直接メイン ブランチに保存します。

カナリア デプロイの昇格または拒否に対して手動認証を追加する

YAML またはクラシックを使って手動で介入できます。

  1. akspromote という新しい Kubernetes 環境を作成します。
  2. 環境リストから新しい akspromote 環境を開き、[承認と確認] タブで [承認] を選択します。
  3. [承認] 画面での [承認者] で独自のユーザー アカウントを追加します。
  4. [詳細設定] を展開し、[承認者が独自に実行を承認できるようにする] が選択されているかを確認します。
  5. [作成] を選択します

昇格と拒否ステージをパイプラインに追加する

  1. [パイプライン] に移動し、作成したパイプラインを選択したら、[編集] を選択します。

  2. 変更を促進する YAML ファイルの最後に次の PromoteRejectCanary ステージを追加します。

    - stage: PromoteRejectCanary
      displayName: Promote or Reject canary
      dependsOn: DeployCanary
      condition: succeeded()
    
      jobs:
      - deployment: PromoteCanary
        displayName: Promote Canary
        pool: 
          vmImage: ubuntu-latest
        environment: 'akspromote'
        strategy:
          runOnce:
            deploy:
              steps:      
              - task: KubernetesManifest@1
                displayName: Create Docker Registry Secret for akspromote
                inputs:
                  action: 'createSecret'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  secretType: 'dockerRegistry'
                  secretName: 'my-acr-secret'
                  dockerRegistryEndpoint: 'azure-pipelines-canary-acr'
    
              - task: KubernetesManifest@1
                displayName: promote canary
                inputs:
                  action: 'promote'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  strategy: 'canary'
                  manifests: '$(Pipeline.Workspace)/manifests/*'
                  containers: '$(containerRegistry)/$(imageRepository):$(tag)'
                  imagePullSecrets: 'my-acr-secret'
        ```
    
    
  3. 変更をロール バックするファイルの最後に次の RejectCanary ステージを追加します。

    - stage: RejectCanary
      displayName: Reject canary
      dependsOn: PromoteRejectCanary
      condition: failed()
    
      jobs:
      - deployment: RejectCanary
        displayName: Reject Canary
        pool: 
          vmImage: ubuntu-latest
        environment: 'akscanary'
        strategy:
          runOnce:
            deploy:
              steps:        
              - task: KubernetesManifest@1
                displayName: Create Docker Registry Secret for reject canary
                inputs:
                  action: 'createSecret'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'kubernetes-testing'
                  kubernetesCluster: 'my-aks-cluster'
                  secretType: 'dockerRegistry'
                  secretName: 'my-acr-secret'
                  dockerRegistryEndpoint: 'azure-pipelines-canary-acr'    
              - task: KubernetesManifest@1
                displayName: Reject canary deployment
                inputs:
                  action: 'reject'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  namespace: 'default'
                  strategy: 'canary'
                  manifests: '$(Pipeline.Workspace)/manifests/*'
        ```
    
  4. [検証して保存] を選択して、パイプラインを直接メイン ブランチに保存します。

安定バージョンをデプロイする

パイプラインの初回実行の場合、ワークロードの安定したバージョン、そのベースラインまたはカナリア バージョンは、クラスタに存在しません。 次のように、sampleapp ワークロードの安定したバージョンをデプロイします。

YAML またはクラシックを使って安定バージョンをデプロイできます。

  1. app/app.py で、success_rate = 50success_rate = 100 に変更します。 この変更により、パイプラインがトリガーされ、イメージがビルドされてコンテナー レジストリにプッシュされ、DeployCanary ステージもトリガーされます。
  2. akspromote 環境で承認を構成したため、そのステージが実行する前に、リリースは待機します。 ビルド概要パイプラインで、[レビュー] > [承認] の順に選択します。

承認されると、パイプラインは、manifests/deployment.ymlsampleapp ワークロードの安定したバージョンを名前空間にデプロイします。

カナリア ワークフローを開始して承認を拒否する

これで、sampleapp ワークロードの安定したバージョンがクラスターに既存します。 次に、シミュレーション アプリケーションに対して以下の変更を行います。

  1. app/app.py で、success_rate = 50success_rate = 100 に変更します。 この変更により、パイプラインがトリガーされ、イメージがビルドされてコンテナー レジストリにプッシュされ、DeployCanary ステージもトリガーされます。
  2. akspromote 環境で承認を構成したため、そのステージが実行する前に、リリースは待機します。
  3. ビルド実行の概要ページで、[確認] を選択し、後続のダイアログ ボックスで [拒否] を選択します。 これにより、デプロイが拒否されます。

拒否した後は、コードのデプロイがパイプラインによって阻止されます。

クリーンアップ

このアプリケーションを引き続き使用しない場合は、Azure portal のリソース グループと Azure DevOps のプロジェクトを削除します。