练习 - 将多容器解决方案部署到 Kubernetes 群集

已完成

随项目一起提供的发布管道旨在将解决方案生成为 Docker 容器并将其部署到 Azure 应用服务。 若要支持将多个容器部署到 Kubernetes 群集,需要修改此管道。

在本单元中,您将了解如何:

  • 更新管道,以触发提交到主分支。
  • 定义要在管道之间共享的变量。
  • 生成和发布 Docker 映像。
  • 发布 Kubernetes 清单。
  • 添加任务以创建映像拉取机密,以便在 Kubernetes 和容器注册表实例之间使用。
  • 将更新后的映像部署到 Kubernetes 群集。

更新管道以支持触发器

  1. 登录到 Azure DevOps 组织,然后导航到项目。

  2. 选择“管道”,然后选择你的管道

  3. 选择 “编辑” 以编辑 azure-pipelines.yml

    Andy:这是以前的单容器解决方案的生成阶段。 我知道它不会正常运行, 所以我禁用了它。 首先,我们可以重新启用触发器以提交到 main 分支。

  4. 将文件顶部的现有 trigger 行替换为以下代码片段。 每次提交到主分支时,它都会触发管道运行。

    trigger:
    - 'main'
    

定义跨管道可访问的变量

安 迪: 我们需要添加两个管道变量。 一个用于指定排行榜存储库的名称,即 排行榜。 另一个是用于部署期间在 AKS 和 ACR 实例之间共享的映像拉取机密的名称。

  1. 将以下突出显示的代码添加到 variables 该部分。

    variables:
      buildConfiguration: 'Release'
      leaderboardRepository: 'leaderboard'
      webRepository: 'web'
      tag: '$(Build.BuildId)'
      imagePullSecret: 'secret'
    

生成 Docker 映像并将其发布到 Azure 容器注册表

安 迪: 我们已经有一个任务,用于将 Web 应用生成为 Docker 容器,我们会将其发布到容器注册表。 只需使用第二个任务为排行榜执行相同操作。

  1. 使用以下突出显示的代码片段添加第二 Docker@2 个任务来生成和发布排行榜容器。 在 Web 容器任务之后添加此任务。

    - task: Docker@2
      displayName: 'Build and push the web image to container registry'
      inputs:
        command: buildAndPush
        buildContext: $(Build.Repository.LocalPath)
        repository: $(webRepository)
        dockerfile: '$(Build.SourcesDirectory)/Tailspin.SpaceGame.Web/Dockerfile'
        containerRegistry: 'Container Registry Connection'
        tags: |
          $(tag)
    
    - task: Docker@2
      displayName: 'Build and push the leaderboard image to container registry'
      inputs:
        command: buildAndPush
        buildContext: $(Build.Repository.LocalPath)
        repository: $(leaderboardRepository)
        dockerfile: '$(Build.SourcesDirectory)/Tailspin.SpaceGame.LeaderboardContainer/Dockerfile'
        containerRegistry: 'Container Registry Connection'
        tags: |
          $(tag)
    

小窍门

请确保在此处添加的任务使用与上一个任务一致的缩进,因为空格在 YAML 文件中很重要。

发布 Kubernetes 清单

安 迪: 我认为我们可以继续进入下一阶段。 你看到有什么缺失吗?

玛拉: 你提到源项目中存在一些清单文件,用于定义部署,以及部署时 Kubernetes 所需的服务。 在完成此阶段之前,我们应该发布它们。

安 迪: 我们需要吗? 它们是否仍位于本地磁盘上?

Mara:如果我们在同一个阶段中将部署任务添加为生成,则它们仍会在本地磁盘上。 但是,由于我们的部署任务在他们自己的 部署 阶段发生,因此它在新的环境中运行,甚至可能在不同的代理上运行。 应确保发布在此阶段生成的、其他阶段需要的任何内容。

安 迪: 这是一个很好的观点。 很容易做到吗? 我们只需要确保 manifests 文件夹被复制到新代理。

Mara:这是 PublishBuildArtifacts@1 任务的用处。 它很常见,甚至有一个简写形式 publish

  1. 添加一个 publish 任务,用于存储未来阶段的 manifests 文件夹,如以下代码片段所示。 请确保此任务的缩进与上一个任务的缩进一致。

    - task: Docker@2
      displayName: 'Build and push the leaderboard image to container registry'
      inputs:
        command: buildAndPush
        buildContext: $(Build.Repository.LocalPath)
        repository: $(leaderboardRepository)
        dockerfile: '$(Build.SourcesDirectory)/Tailspin.SpaceGame.LeaderboardContainer/Dockerfile'
        containerRegistry: 'Container Registry Connection'
        tags: |
          $(tag)
    
    - publish: '$(Build.SourcesDirectory)/manifests'
      artifact: manifests
    

替换部署阶段

Mara:我要将现有部署阶段替换为使用部署作业的部署阶段部署作业是一种特殊的作业,可用于将部署与之前创建的 Azure DevOps 环境相关联。 这样就可以更轻松地跟踪部署历史记录,因为我们的解决方案变得更加复杂,这尤其有用。

  1. 删除现有 部署 阶段(生成阶段之后的所有内容),并将其替换为以下代码片段。 记下突出显示的行,该行指示要使用的部署环境。

    - stage: 'Deploy'
      displayName: 'Deploy the containers'
      dependsOn: Build
      jobs:
      - deployment: Deploy
        displayName: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: 'Dev'
        variables:
        - group: Release
        strategy:
          runOnce:
            deploy:
              steps:
    

    Mara:在部署阶段添加的第一步是使用 DownloadBuildArtifacts@0 任务下载之前发布的清单项目。

    Andy:让我猜猜,该任务是否有简写 download

    玛拉: 完全正确! 我们可以使用 current 说明符来指示我们需要来自管道当前运行的项目。

  2. 将突出显示的行添加为 部署 阶段的第一步。

    - stage: 'Deploy'
      displayName: 'Deploy the containers'
      dependsOn: Build
      jobs:
      - deployment: Deploy
        displayName: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: 'spike.default'
        variables:
        - group: Release
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: manifests
    

    安迪: 现在,我们需要创建将在 ACR 和 AKS 服务之间共享的镜像拉取密钥。 您是否知道是否有可以使用的任务?

    玛拉: 我刚查了一下,我们真幸运。 KubernetesManifest@0 任务支持用于创建所需机密的操作。

Kubernetes 清单任务

Kubernetes 清单任务旨在管理 Kubernetes 所需的所有主流部署操作。 它支持多种 action 选项,包括创建机密到部署映像。 在这种情况下,将使用 createSecret 操作以及以下参数:

  • action 指示要运行的功能。 在这种情况下, createSecret 创建共享机密。
  • connectionType 指定要使用的服务连接的类型。 选项: azureResourceManagerkubernetesServiceConnection
  • secretName 指定要创建的机密的名称。
  • dockerRegistryEndpoint 指定 Azure 容器注册表服务连接的名称。
  • azureSubscriptionConnection 指定 ARM 服务连接的名称。
  • azureResourceGroup 指定资源组的名称。
  • kubernetesCluster 指定 AKS 群集的名称。
  • namespace 指定此作适用的 Kubernetes 命名空间。
  1. 将以下代码片段添加到管道末尾。 确保资源组名称和群集名称都与之前创建的资源组名称和群集名称匹配。 确保此任务的缩进与下载任务的缩进一致。

    - task: KubernetesManifest@1
      displayName: Create imagePullSecret
      inputs:
        action: createSecret
        connectionType: azureResourceManager
        secretName: $(imagePullSecret)
        dockerRegistryEndpoint: 'Container Registry Connection'
        azureSubscriptionConnection: 'Kubernetes Cluster Connection'
        azureResourceGroup: 'tailspin-space-game-rg'
        kubernetesCluster: 'tailspinspacegame-24591'
        namespace: 'default'
    

    安 迪: 最后一步是触发将映像部署到 Kubernetes 群集。 根据文档,看起来我们可以使用相同的任务,但使用不同的操作和参数。

    • action 指示要运行的功能。 在这种情况下,deploy 将被部署到 AKS 群集。
    • connectionType 指定要使用的服务连接的类型。 选项: azureResourceManagerkubernetesServiceConnection
    • azureSubscriptionConnection 指定 ARM 服务连接的名称。
    • azureResourceGroup 指定资源组的名称。
    • kubernetesCluster 指定 AKS 群集的名称。
    • namespace 指定此作适用的 Kubernetes 命名空间。
    • imagePullSecrets 指定从容器注册表拉取所需的机密列表。
    • containers 指定要部署的容器映像的列表。
  2. 将以下代码片段添加到管道末尾。 确保资源组名称和群集名称都与之前创建的资源组名称和群集名称匹配。 请确保此任务的缩进与上一个任务的缩进一致。

    - task: KubernetesManifest@1
      displayName: Deploy to Kubernetes cluster
      inputs:
        action: deploy
        connectionType: azureResourceManager
        azureSubscriptionConnection: 'Kubernetes Cluster Connection'
        azureResourceGroup: 'tailspin-space-game-rg'
        kubernetesCluster: 'tailspinspacegame-24591'
        namespace: 'default'
        manifests: |
          $(Pipeline.Workspace)/manifests/deployment.yml
          $(Pipeline.Workspace)/manifests/service.yml
        imagePullSecrets: |
          $(imagePullSecret)
        containers: |
          $(RegistryName)/$(webRepository):$(tag)
          $(RegistryName)/$(leaderboardRepository):$(tag)
    

运行管道

  1. 从页面右上角选择“ 保存 ”。 选择 “保存” 以确认提交消息。

  2. 选择 “运行”,确认分支名称,然后选择“ 运行 ”以触发管道运行。

  3. 选择 “管道”,然后选择你的管道以查看运行时的日志。

  4. 管道运行完成后,从左窗格中选择 “环境 ”,然后选择 开发 环境以查看部署作业。

  5. 现在,让我们去看看已部署的 Web 应用和 API 端点。 为此,我们需要获取 Web排行榜 服务的外部 IP 地址。

  6. 导航到 Azure 门户,选择 AKS 群集,然后选择 “服务和入口”。

    有关如何查找 Web 和排行榜服务的外部 IP 的屏幕截图。

  7. 选择 Web 服务的“外部 IP”,在 AKS 上查看站点。

    Space Game 网站的屏幕截图。

  8. 返回到 Azure 门户窗口,然后复制排行榜服务的外部 IP。 此 IP 地址是排行榜 API 公开托管的位置。

  9. 将以下链接中的占位符替换为复制的外部 IP。 还可以添加 pageSize=10 查询参数,以便更轻松地在浏览器中查看 JSON 响应。 在新浏览器选项卡中使用如下所示的 URL。

    http://[IP]/api/Leaderboard?pageSize=10
    
  10. 可以从 AKS 群集中托管的排行榜 API 查看原始 JSON 响应。 现在,你有一个 REST API,可以从其他应用程序调用。

    显示排行榜服务的 JSON 响应的 Web 浏览器的屏幕截图。

安 迪: 这原来很棒! 我认为使用 Kubernetes 是采用更广泛的微服务策略的好方法。