【问题标题】:Rolling back a deployment to a Devops "Environment"将部署回滚到 Devops“环境”
【发布时间】:2021-12-12 18:28:36
【问题描述】:

我习惯于使用经典的 Devops “发布”管道将代码更改部署到 Kubernetes 集群。最近,我一直在考虑改用 Azure Pipelines“部署”作业和“环境”。它似乎工作得很好,我喜欢其中的很多功能,比如能够检查与您的部署关联的 Kubernetes 实体,并跟踪部署历史记录。

如果发现错误已发布(例如发布到生产环境),我习惯于从经典发布管道回滚到旧部署。由于发布管道基于构建工件,您只需在发布 UI 中的旧工件上运行部署即可。

现在使用“环境”选项卡下的部署,我不知道如何运行回滚,实际上没有进行代码更改以恢复到旧状态(并不必要地再次运行 CI 构建)。另一种选择是,由于部署是相对于代码(或提交)而不是工件完成的,因此可以手动运行新管道并以给定提交为目标——但这在 Devops UI 中实现起来非常麻烦,而且似乎很容易到错误。在我看来,回滚应该很容易实现,而且不容易出错。

任何想法如何做到这一点?这是我的 yaml 文件的示例

trigger:
  batch: true
  branches:
    include:
      - master

pr:
  branches:
    include:
      - master

variables:
  azureContainerRegistry: <registryUrl> 
  azureContainerRegistryServiceConnection: <serviceConnection>
  kubernetesConfigPath: kubernetes
  kubernetesNamespace: <my-namespace>
  major: 0
  buildNumber: $(major).$(Build.BuildId)
  imageName: "$(azureContainerRegistry)/<my-app>:$(buildNumber)"


stages:
  - stage: Bake
    displayName: "Build and Push image"
    jobs:
      - job: Validate
        displayName: "Build image"
        pool:
          name: "Docker"
        steps:
          - script: docker build -t $(imageName) .
            displayName: Build App 
      - job: Publish
        displayName: "Push image"
        dependsOn: Validate
        condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
        pool:
          name: "Docker"
        steps:
          - task: Docker@2
            displayName: Login to Container Registry
            inputs:
              command: login
              containerRegistry: $(azureContainerRegistryServiceConnection)
          - script: docker push $(imageName)
            displayName: PUSH $(imageName)
  - stage: DeployTest
    displayName: "Deploy TEST"
    dependsOn: Bake
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
    jobs:
      - deployment: Deploy
        environment: <my-test-env>.$(kubernetesNamespace)
        pool:
          name: "Docker"
        strategy:
          runOnce:
            deploy:
              steps:
                - task: qetza.replacetokens.replacetokens-task.replacetokens@3
                  displayName: "Replace tokens"
                  inputs:
                    targetFiles: $(kubernetesConfigPath)/base/*.yaml
                    escapeType: none
                    tokenPrefix: "{"
                    tokenSuffix: "}"
                - task: Kubernetes@1
                  displayName: "kubectl apply"
                  inputs:
                    namespace: $(kubernetesNamespace)
                    command: apply
                    arguments: -k $(kubernetesConfigPath)/test
                    versionSpec: 1.7.0
                    checkLatest: true
                - task: Kubernetes@1
                  displayName: "kubectl rollout status"
                  inputs:
                    namespace: $(kubernetesNamespace)
                    command: rollout
                    arguments: "status deployments/<my-app>"
                    versionSpec: 1.7.0
                    checkLatest: true
  - stage: DeployProd
    displayName: "Deploy PROD"
    dependsOn: DeployTest
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
    jobs:
      - deployment: Deploy
        environment: <my-prod-env>.$(kubernetesNamespace)
        pool:
          name: "Docker"
        strategy:
          runOnce:
            deploy:
              steps:
                - task: qetza.replacetokens.replacetokens-task.replacetokens@3
                  displayName: "Replace tokens"
                  inputs:
                    targetFiles: $(kubernetesConfigPath)/base/*.yaml
                    escapeType: none
                    tokenPrefix: "{"
                    tokenSuffix: "}"
                - task: Kubernetes@1
                  displayName: "kubectl apply"
                  inputs:
                    namespace: $(kubernetesNamespace)
                    command: apply
                    arguments: -k $(kubernetesConfigPath)/prod
                    versionSpec: 1.7.0
                    checkLatest: true
                - task: Kubernetes@1
                  displayName: "kubectl rollout status"
                  inputs:
                    namespace: $(kubernetesNamespace)
                    command: rollout
                    arguments: "status deployments/<my-app>"
                    versionSpec: 1.7.0
                    checkLatest: true

【问题讨论】:

  • 您是否在“发布”yaml 中以resource 的形式使用您的 CI 工件?
  • 不,我没有——事实上我什至没有发布任何工件——但如果这对我有帮助的话,我可以吗?我会添加一些我的 yaml
  • 所以它是多阶段 yaml?构建和部署?
  • 没错。 - 构建 Docker 镜像 - 推送 docker 镜像(如果 branch=master) - 部署到 k8s 集群(替换 yaml 中的令牌以引用最新构建)(如果 branch=master)

标签: azure deployment azure-devops azure-pipelines environment


【解决方案1】:

从旧版本的代码重新部署是这样做的方法。

可以手动运行一个新的管道并定位给定的提交 - 但这在 Devops UI 中实现起来相当麻烦,而且似乎 容易出错

这是您需要一个组织良好的源代码控制分支和标记策略。如果您之前从分支“releases/release-20212710.01”部署,然后从分支“releases/release-20212710.02”部署,则无需进行任何代码更改。回滚只是意味着选择旧的分支——它仍然存在,与以前的代码相同——并进行部署。

【讨论】:

  • 有趣。我习惯于只在“主”分支上部署代码。我不确定如何在主线分支旁边管理所有这些发布分支。
  • 按照你的建议,发布分支会是 PR 分支吗?
  • 不,不同于 PR 分支。 PR 分支进入进入 master,但是当你想要一个受控的发布切割时,一个发布分支是 master 获取的。
  • 分支不是实现这一目标的唯一方法;另一种选择是tagmaster 在您要发布的时候。
  • 对,那么您会在管道的发布(部署)阶段添加标签吗?您能否展示一个在管道 yaml 中执行此操作的示例?
猜你喜欢
  • 1970-01-01
  • 2020-01-25
  • 2020-11-23
  • 2021-02-27
  • 1970-01-01
  • 2020-08-31
  • 1970-01-01
  • 2016-04-20
  • 1970-01-01
相关资源
最近更新 更多