【问题标题】:How to deploy multiple micro services using DevOps pipelines如何使用 DevOps 管道部署多个微服务
【发布时间】:2019-06-24 08:08:07
【问题描述】:

我正在尝试使用 DevOps 将两个 .Net Core 应用程序部署到 Azure Kubernetes。默认管道仅构建和部署我添加的第一个项目。

我创建了一个包含两个解决方案文件夹的单个解决方案,每个文件夹都包含一个 .Net Core 项目。我为这两个项目添加了编排支持,并使用 DevOps 中的“向导”创建了一个 Azure 管道。我在成功部署第一个项目后添加了辅助项目。我认为问题存在是因为 Docker Registry Service Connection 不包含新项目,所以我删除了它并重新创建了连接,但它仍然只部署了第一个项目。我正在使用 Azure Git。

azure-pipeline.yaml 非常标准。我已接受创建管道时创建的默认值。这是我的 buildAndPush 阶段。

stages:
- stage: Build
  displayName: Build stage
  jobs:  
  - job: Build
    displayName: Build job
    pool:
      vmImage: $(vmImageName)
    steps:
    - task: Docker@2
      displayName: Build and push an image to container registry
      inputs:
        command: buildAndPush
        repository: $(imageRepository)
        dockerfile: $(dockerfilePath)
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)
    - task: PublishPipelineArtifact@0
      inputs:
        artifactName: 'manifests'
        targetPath: 'manifests'

如何获得它来构建和部署其他剩余项目?

【问题讨论】:

    标签: docker kubernetes .net-core azure-devops azure-pipelines


    【解决方案1】:

    每个解决方案都需要不同的构建管道。我的建议是将两个项目放在一个解决方案下。 您可以在同一解决方案下拥有任何不同类型的项目。

    【讨论】:

    • 谢谢 Daniel - 我确实在一个解决方案中同时拥有这两个项目。当我尝试创建多个管道时,DevOps 在从 Azure Git 中选择同一个项目后假定它是同一个管道。但是,它允许我创建一个新的管道;它共享所有其他中使用的相同 azure-pipelines.yaml。当我输入这个时,我想到了一些东西 - 很快就会看到我自己的答案......
    【解决方案2】:

    如果您希望创建新管道,则需要从存储库中删除 azure-pipelines.yml 文件。这将允许您从头开始再次逐步完成 Devops“部署到 Azure Kubernetes 服务”。这应该让您有机会将任何其他项目添加到版本中。

    【讨论】:

    • 这允许您重新创建管道,但是在必要时创建新的服务连接;它仍然不允许您指定要构建和部署的项目。它会在您的 master 分支中创建一个新的 azure-pipelines.yml(除非另有说明),它将由所有后续管道共享。
    【解决方案3】:

    我已经设法使用一个 azure-pipelines.yml 文件部署了两个项目;但是,我几乎可以肯定这是不正确的。 我为每个项目复制了构建阶段,并指定了两个单独的 Dockerfile。另外,我为每个项目添加了一个deployment.yml 和service.yml 文件。请参阅下面的 azure-pipelines.yml。任何有关如何正确执行此操作的建议将不胜感激。

    # Deploy to Azure Kubernetes Service
    # Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service
    # https://docs.microsoft.com/azure/devops/pipelines/languages/docker
    
    trigger:
    - master
    
    resources:
    - repo: self
    
    variables:
    
      # Container registry service connection established during pipeline creation
      dockerRegistryServiceConnection: '<hidden>'
      imageRepository1: 'k8spocfront'
      imageRepository2: 'k8spocback'
      containerRegistry: '<hidden>.azurecr.io'
      dockerfilePath1: 'k8sPOC/Dockerfile'
      dockerfilePath2: 'k8sPOCApi/Dockerfile'
      tag: '$(Build.BuildId)'
    
      # Kubernetes Namespace
      k8sNamespace: 'default'
      imagePullSecret: '<hidden>'
    
      # Agent VM image name
      vmImageName: 'ubuntu-latest'
    
    stages:
    - stage: Build_FrontEnd
      displayName: Build stage 1
      jobs:  
      - job: Build
        displayName: Build job
        pool:
          vmImage: $(vmImageName)
        steps:
        - task: Docker@2
          displayName: Build and push an image to container registry
          inputs:
            command: buildAndPush
            repository: $(imageRepository1)
            dockerfile: $(dockerfilePath1)
            containerRegistry: $(dockerRegistryServiceConnection)
            tags: |
              $(tag)
    
    - stage: Build_BackEnd
      displayName: Build stage 2
      jobs:  
      - job: Build
        displayName: Build job
        pool:
          vmImage: $(vmImageName)
        steps:
        - task: Docker@2
          displayName: Build and push an image to container registry
          inputs:
            command: buildAndPush
            repository: $(imageRepository2)
            dockerfile: $(dockerfilePath2)
            containerRegistry: $(dockerRegistryServiceConnection)
            tags: |
              $(tag)          
    
        - task: PublishPipelineArtifact@0
          inputs:
            artifactName: 'manifests'
            targetPath: 'manifests'
    
    - stage: Deploy_FrontEnd
      displayName: Deploy stage
      dependsOn: Build_BackEnd
      jobs:
      - deployment: Deploy
        displayName: Deploy job
        pool:
          vmImage: $(vmImageName)
        environment: '<hidden>.default'
        strategy:
          runOnce:
            deploy:
              steps:
              - task: DownloadPipelineArtifact@1
                inputs:
                  artifactName: 'manifests'
                  downloadPath: '$(System.ArtifactsDirectory)/manifests'
    
              - task: KubernetesManifest@0
                displayName: Create imagePullSecret
                inputs:
                  action: createSecret
                  secretName: $(imagePullSecret)
                  namespace: $(k8sNamespace)
                  dockerRegistryEndpoint: $(dockerRegistryServiceConnection)
    
              - task: KubernetesManifest@0
                displayName: Deploy to Kubernetes cluster
                inputs:
                  action: deploy
                  namespace: $(k8sNamespace)
                  manifests: |
                    $(System.ArtifactsDirectory)/manifests/deployment1.yml
                    $(System.ArtifactsDirectory)/manifests/service1.yml
                    $(System.ArtifactsDirectory)/manifests/deployment2.yml
                    $(System.ArtifactsDirectory)/manifests/service2.yml                
                  imagePullSecrets: |
                    $(imagePullSecret)
                  containers: |
                    $(containerRegistry)/$(imageRepository1):$(tag)
                    $(containerRegistry)/$(imageRepository2):$(tag)
    

    【讨论】:

      【解决方案4】:

      我自己没有尝试过,但您可以利用 matrix 策略。
      作业将被复制并并行运行,每个构建和推送不同的图像。
      使用你的 yaml,它看起来像这样:

      # Deploy to Azure Kubernetes Service
      # Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service
      # https://docs.microsoft.com/azure/devops/pipelines/languages/docker
      
      trigger:
      - master
      
      resources:
      - repo: self
      
      variables:
        # Container registry service connection established during pipeline creation
        dockerRegistryServiceConnection: '<hidden>'
        imageRepository1: 'k8spocfront'
        imageRepository2: 'k8spocback'
        containerRegistry: '<hidden>.azurecr.io'
        dockerfilePath1: 'k8sPOC/Dockerfile'
        dockerfilePath2: 'k8sPOCApi/Dockerfile'
        tag: '$(Build.BuildId)'
      
        # Kubernetes Namespace
        k8sNamespace: 'default'
        imagePullSecret: '<hidden>'
      
        # Agent VM image name
        vmImageName: 'ubuntu-latest'
      
      stages:
      - stage: Build
        displayName: Build stage
        jobs:  
        - job: Build
          displayName: Build job
          strategy:
            matrix:
              image1:
                imageRepository: $(imageRepository1)
                dockerfilePath: $(dockerfilePath1)
              image2:
                imageRepository: $(imageRepository2)
                dockerfilePath: $(dockerfilePath2)
            maxParallel: 2
          pool:
            vmImage: $(vmImageName)
          steps:
          - task: Docker@2
            displayName: Build and push an image to container registry
            inputs:
              command: buildAndPush
              repository: $(imageRepository)
              dockerfile: $(dockerfilePath)
              containerRegistry: $(dockerRegistryServiceConnection)
              tags: |
                $(tag)
          - task: PublishPipelineArtifact@0
            inputs:
              artifactName: 'manifests'
              targetPath: 'manifests'
            condition: and(succeeded(), eq(variables['imageRepository'], $(imageRepository1)))
      
      - stage: Deploy_FrontEnd
        displayName: Deploy stage
        dependsOn: Build_BackEnd
        jobs:
        - deployment: Deploy
          displayName: Deploy job
          pool:
            vmImage: $(vmImageName)
          environment: '<hidden>.default'
          strategy:
            runOnce:
              deploy:
                steps:
                - task: DownloadPipelineArtifact@1
                  inputs:
                    artifactName: 'manifests'
                    downloadPath: '$(System.ArtifactsDirectory)/manifests'
      
                - task: KubernetesManifest@0
                  displayName: Create imagePullSecret
                  inputs:
                    action: createSecret
                    secretName: $(imagePullSecret)
                    namespace: $(k8sNamespace)
                    dockerRegistryEndpoint: $(dockerRegistryServiceConnection)
      
                - task: KubernetesManifest@0
                  displayName: Deploy to Kubernetes cluster
                  inputs:
                    action: deploy
                    namespace: $(k8sNamespace)
                    manifests: |
                      $(System.ArtifactsDirectory)/manifests/deployment1.yml
                      $(System.ArtifactsDirectory)/manifests/service1.yml
                      $(System.ArtifactsDirectory)/manifests/deployment2.yml
                      $(System.ArtifactsDirectory)/manifests/service2.yml                
                    imagePullSecrets: |
                      $(imagePullSecret)
                    containers: |
                      $(containerRegistry)/$(imageRepository1):$(tag)
                      $(containerRegistry)/$(imageRepository2):$(tag)
      

      如您所见,我只使用了一个阶段来构建 Docker 映像。我注意到您将后端清单作为管道工件发布,因此我保留了它并添加了一个条件,以便发布任务仅在应该运行时运行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-03
        • 2020-10-22
        • 2018-06-14
        • 1970-01-01
        相关资源
        最近更新 更多