在Azure DevOps Server(TFS系统)中部署回退/回滚方案(Rollback)

概述

Azure DevOps Server(之前名TFS)是微软公司实现软件研发、测试和部署一体化的全流程解决方案。在近几年的研发过程中,Azure DevOps Server 大幅增强了软件部署过程的自动化功能。对于系统运维人员而言,确保软件的稳定运行,是自己的第一工作目标。但是,在信息技术飞速发展的今天,信息系统的升级变更已经成了家常便饭。每周升级、每天升级、甚至一天升级数次,都已经见怪不怪。

为了提高软件的变更效率和质量,许多运维部门都使用部署脚本,实现系统升级的自动化。在软件升级过程中,为了确保信息系统正常运转,最大程度的降低因为升级导致系统宕机的风险,运维人员首先考虑的是回退(Rollback)方案。即,在系统升级过程中,万一出现由于升级导致的异常状况,为了最快恢复系统的正常运行,回退到部署前的版本,是一个运维人员恢复系统正常的首选方案。

在下面的内容中,我们介绍在使用Azure DevOps Server实现部署过程中,如何应用回退方案。

回退方案

在软件部署过程中,我们可以选择多种回退方案:

1. 基于虚拟机的快照技术

在升级变更之前,为即将发生变更的服务器创建快照,当系统部署失败时,直接将虚拟机退回到创建快照时的状态。

目前Azure DevOps Server支持包括VMware, SCVMM(Hyper-V)等多种虚拟化平台。如果微软原生的技术支持,一般虚拟化平台都提供快照的API,可以将API通过PowerShell、Shell等方式集成到发布流水线中。下图是在Azure DevOps中使用VMware和SCVMM的截图:

图1:Azure DevOps Server流水线中的SCVMM任务

image

图2:Azure DevOps Server流水线中的vCenter任务

image

基于虚拟机快照的回退方案,简单粗暴,但是却非常适用。在手动部署过程中,这种方案就是运维人员常用的方式。

但是虚拟机的快照并不是万能的,它存在许多不足,例如快照会消耗大量的磁盘存储;如果是域环境中运行的虚拟机,快照还原可能出现脱域的问题;快照合并的时间较长等问题。在选择使用快照技术作为回退方案时,需要重复考虑快照还原对系统造成的影响。

2. 重新部署上一个版本

在Azure DevOps Server中,重新部署上一个版本,是最为简单和快速的方式。

Azure DevOps Server 最大的特点,是完整地保留了软件研发运维过程中的所有日志、交付物数据,并且保护交付物数据的各种版本,其中就包括部署部署过程中的每一个版本。单本次部署失败时,我们可以从上一次的部署中,选择重新部署按钮,实现一键回退功能。

例如,在下图中,由于四次部署是上一次成功的部署,并且系统运行正常,我选中重新部署,就可以重复运行上一次部署的所有任务,并且在部署过程中,使用上一次部署的升级包、环境变量等数据。

图3:在Azure DevOps Server 中重新部署

image

如果你熟悉IBM UrbanCode Deploy,会发现Azure DevOps Server的重新部署功能与它的“Replace with Last Deployed”有异曲同工之妙。通过重新部署上一次的版本实现回退,简单快速。但是,问题也显而易见,不一定能够实现系统回退的效果。这种方案只适合独立运行的信息系统。

例如,当系统依赖与第三方系统运行,需要和第三方系统同步升级时,重新部署只能将自己的系统回退到了上一个版本,但是并不能将系统恢复到健康状态,因为此时第三方系统已经完成了升级,可能第三方系统不能兼容你的上一个版本。同样,如果当前版本对应的数据库结构已经完成了升级,重新部署也不能恢复系统的健康状态。

3. 停止自动部署,手动修复问题

程序员和运维工程师不是万能的,相反,这是一群最容易犯错误的人,因为他们实现的大部分需求,都没有可以照搬的方案。都是在开发过程中,不断试错,实现信息系统的增量发展。同样,在部署过程中,每次都存在许多不确定因素。当发现部署问题时,分析原因找到解决方案,并修复问题,将当前环境恢复到健康状态。同事,将解决方案集成到系统源代码或者部署脚本中,作为下一个版本的部署内容。

当然,作为程序员,我们可以提升系统部署智能化,提高部署过程中错误探测和解决的自动化水平,这也是后面要重点介绍的方案。

4. 在流水线中部署回退脚本

在Azure DevOps Server 中,发布流水线由一个一个的任务组合而成。在发布过程中,系统按照流水线中配置的顺序,执行每一个阶段中的任务。当发布流水线中的中的任何任务失败时,对应环境的部署可能会失败。为了让环境恢复正常,我们可以执行一个回滚脚本Shell (on Linux)或PowerShell(on windows)。脚本本身需要具以下要求:

  • 当部署工作流中的任何任务失败时,对环境的部署可能会失败。为了让环境恢复正常,我们将执行一个回滚脚本。即使在另一个任务失败时,脚本本身也会为环境执行脚本。通过Azure DevOps的发布管理,您可以使用PowerShell或shell任务来实现此目的,并将其标记为“始终运行”。这样,无论部署成功或失败,脚本都将始终得到执行。
  • 如果前一个任务失败,则应跳过未标记为“始终运行”的任何任务,但将执行始终运行的任务。根据部署失败的任务对环境进行选择性更改。执行脚本只是任务的一半。为了避免破坏任何不需要的东西,我们需要了解更多内容。首先,我们需要检测是否有故障。如果失败了,那么什么任务失败了。目前,脚本中没有一种方法可以了解这些内容。我们需要在脚本中查询这些版本。幸运的是,Azure DevOps 的市场(https://marketplace.visualstudio.com)中扩展插件“Release Management Utility tasks”(https://marketplace.visualstudio.com/items?itemName=ms-devlabs.utilitytasks),其中包含了一个任务“Powershell to rollback”,这个任务可以协助我们,使回退脚本变得更加简便。如果你想验证下面的脚本,需要将这个扩展安装在你的Azure DevOps Server中。

下面我们来演示如何实现这个功能:

首先,编写回退脚本,并将其推送到代码库中,例如我的回退脚本如下:

echo $env:Release_Tasks

try

{

$jsonobject = ConvertFrom-Json $env:Release_Tasks

}

catch

{

Write-Verbose -Verbose "Error parsing Release_Tasks environment variable"

Write-Verbose -Verbose $Error

}

foreach ($task in $jsonobject | Get-Member -MemberType NoteProperty)

{

$taskproperty = $jsonobject.$($task.Name) | ConvertFrom-Json

echo "task name: $($taskproperty.Name)"

echo "task rank: $($task.Name)"

echo "task status: $($taskproperty.Status)"

echo "Task $($taskproperty.Name) with rank $($task.Name) has status $($taskproperty.Status)"

$task_status=$taskproperty.Status

if($task_status -eq "failed")

{

Write-Warning "This is a error generated in a PowerShell script"

}

}

image

然后,在发布流水线中添加回退任务。注意需要将其标记为总是运行“即使上一任务已失败,即使已经取消部署”:

image

最后,我们看一下回退脚本运行的结果:

image

在上图中,可以看到回退脚本顺利运行,下图是回退脚本的输出:

image

在上面第4个方案中,我们只是介绍了基于Azure DevOps Server 的回退机制,而具体的回退脚本,需要根据系统部署的内容来定。需要开发人员或者运维人员根据本次变更的具体内容编写脚本。例如文件的变动,则需要编辑将备份文件覆盖回来;如果数据结构的变动,则需要更改数据库。


微软DevOps MVP 张洪君 http://www.cnblogs.com/danzhang

--End--

posted on 2019-04-05 14:41  danzhang  阅读(2054)  评论(0编辑  收藏  举报

导航