다음을 통해 공유


자습서: Kubernetes에 카나리아 배포 전략 사용

Azure DevOps Services | Azure DevOps Server 2022

이 단계별 가이드에서는 전략에 Kubernetes 매니페스트 작업을 canary 사용하는 방법을 설명합니다. 카나리아 배포 전략은 안정적인 프로덕션 버전 옆에 새 버전의 애플리케이션을 배포합니다.

연결된 워크플로를 사용하여 코드를 배포하고 기준 및 카나리아 앱 배포를 비교합니다. 평가에 따라 카나리아 배포의 수준을 올리거나 거부할지 여부를 결정합니다.

이 자습서에서는 Docker 레지스트리 및 Azure Resource Manager 서비스 연결을 사용하여 Azure 리소스에 연결합니다. AKS(Azure Kubernetes Service) 프라이빗 클러스터 또는 로컬 계정이 비활성화 된 클러스터의 경우 Azure Resource Manager 서비스 연결 이 더 나은 연결 방법입니다.

필수 조건

GitHub 리포지토리 파일

GitHub 리포지토리에는 다음 파일이 포함되어 있습니다.

파일 설명
./app/app.py 간단한 Flask 기반 웹 서버입니다. 파일은 변수 값에 따라 양호 및 잘못된 응답 수에 대한 사용자 지정 카운터를 success_rate 설정합니다.
./app/Dockerfile app.py 변경할 때마다 이미지를 빌드하는 데 사용됩니다. 각 변경은 빌드 파이프라인을 트리거하여 이미지를 빌드하고 컨테이너 레지스트리에 푸시합니다.
./manifests/deployment.yml 게시된 이미지에 sampleapp 해당하는 배포 워크로드의 사양을 포함합니다. 안정적인 배포 개체 버전과 워크로드의 기준 및 카나리아 변형을 파생하기 위해 이 매니페스트 파일을 사용합니다.
./manifests/service.yml sampleapp 서비스를 만듭니다. 이 서비스는 안정적인, 기준 및 카나리아 배포에 의해 회전된 Pod에 요청을 라우팅합니다.
./misc/fortio.yml fortio 배포를 설정합니다. 이 배포는 배포된 sampleapp 서비스에 요청 스트림을 보내는 부하 테스트 도구입니다. 요청 스트림은 안정, 기준 및 카나리아의 세 가지 배포에서 Pod로 라우팅됩니다.

서비스 연결 만들기

  1. Azure DevOps 프로젝트에서 프로젝트 설정>Pipelines>Service 연결이동합니다.
  2. Azure Container Registry 인스턴스와 연결된 azure-pipelines-canary-acr이라는 Docker 레지스트리 서비스 연결을 만듭니다.
  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. 저장 및 실행을 선택하고 작업이 성공적으로 실행되는지 확인합니다.

매니페스트 파일 편집

리포지토리 포크에서 매니페스트/deployment.yml 편집하여 컨테이너 레지스트리의 URL로 대체 <foobar> 합니다. 예를 들면 다음과 같습니다example.azurecr.io/azure-pipelines-canary-k8s.

지속적인 배포 설정

이제 지속적인 배포를 설정하고, 카나리아 단계를 배포하고, 수동 승인을 통해 카나리아를 승격하거나 거부합니다.

환경 만들기

YAML 또는 클래식을 사용하여 배포할 수 있습니다.

  1. Azure DevOps 프로젝트에서 파이프라인>환경으로 이동한 다음, 환경 또는 새 환경 만들기를 선택합니다.
  2. 첫 번째 새 환경 화면에서 이름 아래에 akscanary를 입력하고, 리소스에서 Kubernetes를 선택하고, 다음을 선택합니다.
  3. 다음과 같이 Kubernetes 리소스 화면을 채웁니다.
    • 공급자: Azure Kubernetes Service를 선택합니다.
    • Azure 구독: Azure 구독을 선택합니다.
    • 클러스터: AKS 클러스터를 선택합니다.
    • 네임스페이스: 새로 만들기를 선택하고 카나리아데모를 입력합니다.
  4. 유효성 검사 및 만들기를 선택합니다.

카나리아 단계 추가

  1. 파이프라인으로 이동하여 만든 파이프라인을 선택하고 편집을 선택합니다.

  2. 전체 파이프라인 YAML을 다음 코드로 바꿉다.

    이 코드는 스테이지를 Docker@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.py success_rate = 50success_rate = 100. 이 변경은 파이프라인을 트리거하고, 이미지를 빌드하고 컨테이너 레지스트리에 푸시하고, 스테이지를 트리거합니다 DeployCanary .
  2. 환경에 대한 akspromote 승인을 구성했기 때문에 릴리스는 해당 단계를 실행하기 전에 대기합니다. 빌드 실행 요약 페이지에서 검토를 선택한 다음 승인을 선택합니다.

승인되면 파이프라인은 매니페스트/deployment.yml 안정적인 버전의 sampleapp 워크로드를 네임스페이스에 배포합니다.

카나리아 워크플로 시작 및 승인 거부

이제 안정적인 버전의 워크로드가 sampleapp 클러스터에 있습니다. 다음으로 시뮬레이션 애플리케이션을 다음과 같이 변경합니다.

  1. 앱/app.py success_rate = 50success_rate = 100. 이 변경은 파이프라인을 트리거하고, 이미지를 빌드하고 컨테이너 레지스트리에 푸시하고, 스테이지를 트리거합니다 DeployCanary .
  2. 환경에 대한 akspromote 승인을 구성했기 때문에 릴리스는 해당 단계를 실행하기 전에 대기합니다.
  3. 빌드 실행 요약 페이지에서 검토를 선택한 다음, 후속 대화 상자에서 [거부]를 선택합니다. 이렇게 하면 배포가 거부됩니다.

거부되면 파이프라인은 코드 배포를 방지합니다.

정리

이 애플리케이션을 계속 사용하지 않려면 Azure Portal에서 리소스 그룹 및 Azure DevOps의 프로젝트를 삭제합니다.