发布管理 vNext 组件部署瓶颈

Release Management vNext Component Deployment Bottleneck

我们使用带有 vNext 发布模板的 Release Management 2015。我们为应用程序的每个部分部署了基于 Powershell DSC 的组件,事实上,我们部署了两个不同的应用程序,它们正在积极开发中,并且通常几乎同时部署。

我们在部署过程中经常遇到以下错误:

OperationFailedException: New deployment is not allowed as an another deployment is in progress. Retry the deployment after sometime.

完整的堆栈跟踪显示错误不是来自 Powershell 本身,而是来自负责在目标机器上执行 powershell 脚本的 Release Management 系统:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Microsoft.TeamFoundation.Release.Common.Helpers.OperationFailedException: New deployment is not allowed as an another deployment is in progress. Retry the deployment after sometime.
   at Microsoft.TeamFoundation.Release.EnvironmentProvider.OnPrem.Implementation.OnPremDeploymentProvider.ReadDeploymentResponse(DeploymentResponse response)
   at Microsoft.TeamFoundation.Release.EnvironmentProvider.OnPrem.Implementation.OnPremDeploymentProvider.RunScript(String scriptPath, String configurationPath, MachineSpecification machine, StorageSpecification storage, Dictionary`2 configurationVariables)
   at Microsoft.TeamFoundation.Release.MonitorServices.Dsc.OnPrem.OnPremDeploymentActions.InvokePlatform(String activityId, MachineSpecification machineSpecification, StorageSpecification storageSpecification, String scriptPath, String configurationPath, Dictionary`2 configurationVariables)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.TeamFoundation.Release.DeploymentAgent.Services.Deployer.Dsc.DscComponentInstaller.InvokeMethodByReflection(String methodArguments)

上述错误导致整个部署失败,我们被迫重试该阶段或整个部署以使其完成。

有两种情况会导致这种情况:

  1. 两个发布模板同时在同一目标服务器上执行它们的 powershell 脚本
  2. 单个发布模板具有并行控制流,其中包含两个不同的组件,它们都在同一目标服务器上执行脚本

换句话说,Release Management 用于在远程服务器上执行 powershell 脚本的机制似乎一次只能执行一个脚本,并且无法 wait/hold 其他人执行完成。

如果所讨论的脚本主动修改其执行所在的服务器,则此 kinda/sorta 有意义,但在我们的示例中,服务器基本上充当 运行 脚本的临时区域。脚本的 "real" 目标与执行 powershell 的服务器无关。

除了每个服务器同时部署一个组件(哇)之外,这里还有什么工作要做?这似乎是一个重大疏忽,它让我认真考虑完全放弃发布管理。

我在远程服务器上使用 运行ning Powershell 脚本时遇到了一个问题。我最终走了一条稍微不同的路线。相反,我只是 运行 带有 Invoke-Command 块的普通 Powershell 命令。我相信您应该能够 运行 并行执行此操作。

Function Get-PSCredential($User,$Password) {
    $SecPass = ConvertTo-SecureString -AsPlainText -String $Password -Force
    $Creds = New-Object System.Management.Automation.PSCredential -ArgumentList $User,$SecPass
    Return $Creds
}    

$credential = Get-PSCredential -User $deployUser -Password $deployPass
$session = New-PSSession YourServerName -Credential $credential

Invoke-Command -Session $session -ScriptBlock {
    # do your work here
}

如果您运行宁作为可以访问机器的服务帐户,您应该能够消除凭证内容并直接使用

$session = New-PSSession YourServerName

我这周才开始使用发布管理,所以这似乎是在这么短的时间内完成的最佳方式。

此外,如果您以前从未使用过 Invoke-Command,脚本块中的所有内容实际上都在其自己的范围内,因此您需要使用 -ArgumentList 将变量传递给它(如果有的话) .如果您对此有任何疑问,请查看 this 文章。

正如我在 today, MS Release Management's way of deploying is a bit counter-intuitive: Rather than just executing your Powershell deployment script against the target server using PSRemoting, it uses PSRemoting to install a Windows Service (VisualStudioRemoteDeployer.exe) on the target server. This service then runs your deployment script locally, and the MSRM server regularly polls this Windows service (see here 中所解释的那样,查看它是否已完成部署。

我怀疑这种奇怪的设置与避免 double-hop issue 有关 - 因此它允许您的脚本从目标服务器到另一台服务器进行第二跳,例如用于网络服务调用。

无论如何,这个 Windows 服务可能形成瓶颈,因为每个服务器只能有一个这样的实例 运行ning - 因此组件并行部署到同一台服务器的事实似乎碰撞。

我认为您的问题源于您选择的设置,其中“服务器基本上充当运行脚本的临时区域”- MS Release Management 2013/2015 在这种情况下表现不佳(如您所见),您确实应该将组件直接部署到需要安装它们的目标服务器,从而避免暂存区瓶颈。

next version of MS Release Management 将使用部署代理作为一个集结点,组件将从该集结点部署到其他服务器。这有助于减少 MS Release Management 和目标服务器之间的防火墙必须允许的连接数(这可能是您选择临时区域设置的原因),同时仍然允许并行(或至少排队)部署。