Condividi tramite


Esercitazione: Usare una strategia di distribuzione canary per Kubernetes

Azure DevOps Services | Azure DevOps Server 2022

Questa guida dettagliata illustra come usare l'attività manifesto kubernetes con la canary strategia. Una strategia di distribuzione canary distribuisce nuove versioni di un'applicazione accanto a versioni stabili e di produzione.

Usare il flusso di lavoro associato per distribuire il codice e confrontare le distribuzioni di app canary e di base. In base alla valutazione, si decide se promuovere o rifiutare la distribuzione canary.

Questa esercitazione usa il Registro Docker e le connessioni al servizio Azure Resource Manager per connettersi alle risorse di Azure. Per un cluster privato servizio Azure Kubernetes (servizio Azure Kubernetes) o un cluster con account locali disabilitati, una connessione al servizio Azure Resource Manager è un modo migliore per connettersi.

Prerequisiti

File del repository GitHub

Il repository GitHub contiene i file seguenti:

File Descrizione
./app/app.py Un server Web semplice basato su Flask. Il file configura un contatore personalizzato per il numero di risposte valide e non valide, in base al valore della success_rate variabile.
./app/Dockerfile Usato per la compilazione dell'immagine con ogni modifica apportata a app.py. Ogni modifica attiva la pipeline di compilazione per compilare l'immagine ed eseguirne il push nel registro contenitori.
./manifests/deployment.yml Contiene la specifica del sampleapp carico di lavoro di distribuzione corrispondente all'immagine pubblicata. Questo file manifesto viene usato per la versione stabile dell'oggetto di distribuzione e per derivare le varianti di base e canary dei carichi di lavoro.
./manifests/service.yml Crea il sampleapp servizio. Questo servizio instrada le richieste ai pod attivate dalle distribuzioni stable, baseline e canary.
./misc/fortio.yml Configura una distribuzione fortio. Questa distribuzione è uno strumento di test del carico che invia un flusso di richieste al servizio distribuito sampleapp . Il flusso di richieste instrada i pod nelle tre distribuzioni: stabile, baseline e canary.

Creare connessioni al servizio

  1. Nel progetto Azure DevOps passare a Impostazioni>progetto Connessioni del servizio Pipeline.>
  2. Creare una connessione al servizio Registro Docker denominata azure-pipelines-canary-acr associata all'istanza di Registro Azure Container.
  3. Creare una connessione al servizio Azure Resource Manager con l'identità del carico di lavoro denominata azure-pipelines-canary-k8s per il gruppo di risorse.

Aggiungere la fase di compilazione

  1. Nel progetto Azure DevOps passare a Pipelines>Create Pipeline (Crea pipeline) o New pipeline (Nuova pipeline).

  2. Selezionare GitHub per il percorso del codice e selezionare il repository forked azure-pipelines-canary-k8s .

  3. Nella scheda Configura scegliere Pipeline di avvio.

  4. Nella scheda Revisione sostituire yaml della pipeline con il codice seguente.

    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)
    

    Se la connessione al servizio registro Docker creata è associata a un registro contenitori denominato example.azurecr.io, l'immagine viene impostata su example.azurecr.io/azure-pipelines-canary-k8s:$(Build.BuildId).

  5. Selezionare Salva ed esegui e verificare che il processo venga eseguito correttamente.

Modificare il file manifesto

Nel fork del repository modificare manifesti/deployment.yml per sostituire <foobar> con l'URL del registro contenitori, ad esempio example.azurecr.io/azure-pipelines-canary-k8s.

Configurare la distribuzione continua

Configurare ora la distribuzione continua, distribuire la fase canary e promuovere o rifiutare il canary tramite l'approvazione manuale.

Crea un ambiente

È possibile eseguire la distribuzione con YAML o Versione classica.

  1. Nel progetto Azure DevOps passare ad Ambienti pipeline>e quindi selezionare Crea ambiente o Nuovo ambiente.
  2. Nella prima schermata Nuovo ambiente immettere akscanary in Nome, selezionare Kubernetes in Risorsa e selezionare Avanti.
  3. Compilare la schermata della risorsa Kubernetes come indicato di seguito:
    • Provider: selezionare servizio Azure Kubernetes.
    • Sottoscrizione di Azure: selezionare la sottoscrizione di Azure.
    • Cluster: selezionare il cluster del servizio Azure Kubernetes.
    • Spazio dei nomi: selezionare Nuovo e immettere canarydemo.
  4. Selezionare Convalida e crea.

Aggiungere la fase canary

  1. Passare a Pipeline, selezionare la pipeline creata e selezionare Modifica.

  2. Sostituire l'intero YAML della pipeline con il codice seguente.

    Questo codice modifica il Docker@2 passaggio eseguito in precedenza per usare una fase e aggiunge altri due passaggi per copiare i manifesti e le directory non corretta come artefatti per le fasi consecutive da usare.

    Il codice sposta anche alcuni valori in variabili per un utilizzo più semplice più avanti nella pipeline. containerRegistry Nella variabile sostituire <example> con il nome del registro contenitori.

    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. Aggiungere un'altra fase alla fine del file YAML per distribuire la versione canary. Sostituire i valori my-resource-group e my-aks-cluster con il gruppo di risorse e servizio Azure Kubernetes nome del cluster.

    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. Selezionare Convalida e salva e salvare la pipeline direttamente nel ramo principale.

Aggiungere l'approvazione manuale per promuovere o rifiutare la distribuzione canary

È possibile intervenire manualmente con YAML o Classic.

  1. Creare un nuovo ambiente Kubernetes denominato akspromote.
  2. Aprire il nuovo ambiente akspromote dall'elenco degli ambienti e selezionare Approvazioni nella scheda Approvazioni e controlli .
  3. Nella schermata Approvazioni aggiungere il proprio account utente in Responsabili approvazione.
  4. Espandere Avanzate e assicurarsi che l'opzione Consenti ai responsabili approvazione di approvare le proprie esecuzioni sia selezionata.
  5. Seleziona Crea.

Aggiungere fasi di promozione e rifiuto alla pipeline

  1. Passare a Pipeline, selezionare la pipeline creata e selezionare Modifica.

  2. Aggiungere la fase seguente PromoteRejectCanary alla fine del file YAML che promuove le modifiche.

    - 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. Aggiungere la fase seguente RejectCanaryalla fine del file che esegue il rollback delle modifiche.

    - 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. Selezionare Convalida e salva e salvare la pipeline direttamente nel ramo principale.

Distribuire una versione stabile

Per la prima esecuzione della pipeline, la versione stabile dei carichi di lavoro e le relative versioni di base o canary, non esistono nel cluster. Distribuire una versione stabile del sampleapp carico di lavoro come indicato di seguito.

È possibile distribuire una versione stabile con YAML o Versione classica.

  1. In app/app.py passare success_rate = 50 a success_rate = 100. Questa modifica attiva la pipeline, la compilazione e il push dell'immagine nel registro contenitori e attiva anche la DeployCanary fase.
  2. Poiché è stata configurata un'approvazione nell'ambiente akspromote , la versione attende prima di eseguire tale fase. Nella pagina di riepilogo dell'esecuzione della compilazione selezionare Rivedi e quindi approva.

Dopo l'approvazione, la pipeline distribuisce la versione stabile del sampleapp carico di lavoro nei manifesti/deployment.yml nello spazio dei nomi .

Avviare il flusso di lavoro canary e rifiutare l'approvazione

La versione stabile del sampleapp carico di lavoro è ora presente nel cluster. Apportare quindi la modifica seguente all'applicazione di simulazione.

  1. In app/app.py passare success_rate = 50 a success_rate = 100. Questa modifica attiva la pipeline, la compilazione e il push dell'immagine nel registro contenitori e attiva anche la DeployCanary fase.
  2. Poiché è stata configurata un'approvazione nell'ambiente akspromote , la versione attende prima di eseguire tale fase.
  3. Nella pagina di riepilogo dell'esecuzione della compilazione selezionare Rivedi e quindi selezionare Rifiuta nella finestra di dialogo successiva. In questo modo viene rifiutata la distribuzione.

Dopo il rifiuto, la pipeline impedisce la distribuzione del codice.

Eseguire la pulizia

Se non si intende continuare a usare questa applicazione, eliminare il gruppo di risorse in portale di Azure e il progetto in Azure DevOps.