【问题标题】:Waiting for a new deployment to fully initialize before swap the staging/production slot (swap VIP)?在交换暂存/生产槽(交换 VIP)之前等待新部署完全初始化?
【发布时间】:2024-05-19 14:20:02
【问题描述】:

我使用以下代码将我新部署的应用程序从暂存槽交换到生产槽(交换 VIP):

Get-HostedService -serviceName $serviceName -subscriptionId $subcription -certificate $certificate | Get-Deployment -slot staging | Move-Deployment |Get-OperationStatus –WaitToComplete

我认为 -WaitToComplete 标志将确保所有虚拟机在执行交换之前都已完全初始化,但它没有执行交换,此时生产槽中新部署的应用程序仍在初始化且不可用完全初始化大约需要 5/10 分钟。

在执行 Swap VIP 操作之前确保应用程序完全初始化的最佳方法是什么?

【问题讨论】:

  • 我需要这个,因为我正在使用自动构建来部署到 Azure

标签: powershell azure


【解决方案1】:

这个 PowerShell sn-p 将等待每个实例都准备好(基于 @astaykov 给出的答案)。

它查询暂存槽中正在运行的实例的状态,只有当所有实例都显示为“就绪”时,它才会离开循环。

$hostedService = "YOUR_SERVICE_NAME"

do {
    # query the status of the running instances
    $list = (Get-AzureRole -ServiceName $hostedService `
                           -Slot Staging `
                           -InstanceDetails).InstanceStatus 

    # total number of instances
    $total = $list.Length

    # count the number of ready instances
    $ready = ($list | Where-Object { $_ -eq "ReadyRole" }).Length

    Write-Host "$ready out of $total are ready"

    $notReady = ($ready -ne $total)
    If ($notReady) {
        Start-Sleep -s 10
    }
}
while ($notReady)

【讨论】:

  • 不错,最好添加某种超时时间(例如 5-10 分钟),因为如果其中一个角色无法启动,您将陷入无限循环。跨度>
【解决方案2】:

我猜你可能实际看到的是 DNS 条目被传播并变得可用所需要的延迟。

您应该发现,一旦状态报告为 Ready,您可能无法使用暂存 URL“http://.cloudapp.net”访问您的站点,您会发现它可能不会出现...但是如果您查看管理门户,您会在属性底部看到“VIP”的值 - 如果您使用该 IP 地址“http://xxx.xxx.xxx.xxx您应该能够访问您的网站。

当您执行 SWAP 时,您会发现类似的行为。传播 DNS 更新需要一些时间,但您可能会看到您仍然可以使用 IP 地址或暂存地址(如果可用)访问该站点。

最后,1 个问题...根据您的问题,听起来您可能正在部署到暂存作为构建的一部分,然后立即升级到生产部署...这是正确的,如果是这样,为什么不直接部署到生产部署? (我并不是说直接部署到生产中是一种最佳实践……但如果这是您的工作流程,我认为临时部署到暂存没有任何好处)

希望这会有所帮助!

【讨论】:

  • 感谢您的回复。回答您的问题:PowerShell 脚本是整个自动化和半自动化构建过程的一部分,如果它用于 CI 或测试,有时会自动直接部署到环境中,但对于生产和暂存等更安全的环境,它有一个额外的手动步骤,其中测试人员验证位于暂存槽中的新部署。这就是我们不直接部署到生产槽的原因。
  • 感谢您的澄清。是在测试人员验证了暂存部署中的部署之后,您才发现问题吗?如果是这样,那么我预计您看到的“可用性延迟”很可能导致 DNS 更改被传播。同样,您可以尝试通过直接使用 VIP 访问您的站点来测试它,看看它是否按预期响应。
  • 谢谢迈克。是的,我已将其归结为 DNS 问题。
【解决方案3】:

我对 PowerShell 不是很熟悉,但根据我在 shell 方面的经验,您完全是在流水线化命令。管道字符 (|) 之前的每个集合代表一个命令,该命令会将其结果传递给管道中的下一个命令(管道字符之后的命令)。由于您在分解完全完成之前执行这些命令,这就是您将新部署的应用程序交换到生产槽的原因。

首先要注意的是,最后一个命令(实际上是 Get-OperationStatus)有“-WaitToComplete”参数。

我看到的另一件事是这个 powershell 命令只会进行 vip 交换。部署呢?

根据您的描述,您的构建服务器似乎正在自动部署到登台,并且您有执行交换脚本的构建后事件。如果您的流程是这样的,那么 Mike Erickson 在这里建议的内容是有道理的 - 在部署到登台后立即交换。如果您要在不先检查应用程序运行状况的情况下进行交换,为什么要部署到登台?但是我不建议直接分解到服务器(删除+部署),而是升级服务。因为当我们进行服务升级时,我们的部署会保留其公共 IP 地址。如果我们删除 + 部署,我们将获得一个新的公共 IP 地址。并且已经保证在删除部署之前不会更改托管服务的公共 IP 地址。

最后,您应该稍微扩展一下您的 PowerShell 脚本。首先包括一个例程,它将检查(并等待直到)暂存槽“准备好”,然后执行交换。正如我所说,我不太喜欢 powershell,但我确信这是可行的。

只要我的 2 美分。

更新

在重温this guide之后,我现在明白了一些事情。您正在等待操作完成,但这是您正在等待完成的 VIP-SWAP 操作。如果您的陈述部署尚未准备好,您必须等待它准备好。而且就像 Mike 提到的那样,可能存在 DNS 延迟,这在guide 的末尾注明:

注意:

如果您在推广后不久访问生产站点,DNS name 可能还没有准备好。如果遇到 DNS 错误 (404),请等待 几分钟,然后再试一次。请记住,Windows Azure 创建 DNS 动态命名条目并且更改可能需要几分钟 传播。

更新 2

好吧,您将不得不查询所有角色及其所有实例,并等待所有这些都准备好。从技术上讲,您可以在每个角色至少准备一个实例的情况下进行 VIP 交换,但我认为这会使脚本更加复杂。

【讨论】:

    【解决方案4】:

    这是对上面 Richard Astbury 示例的小调整,将重试有限的次数。原始示例代码的所有功劳归功于他,所以我会投票支持他作为最重要的答案。只需在此处发布此变体,以供人们根据需要复制/粘贴:

    $hostedService = "YOUR_SERVICE_NAME"
    # Wait roughly 10 minutes, plus time required for Azure methods
    $remainingTries = 6 * 10
    
    do {
        $ready=0
        $total=0
        $remainingTries--
    
        # query the status of the running instances
        $list = (Get-AzureRole -ServiceName $hostedService -Slot Staging -InstanceDetails).InstanceStatus 
    
        # count the number of ready instances
        $list | foreach-object { IF ($_ -eq "ReadyRole") { $ready++ } }
    
        # count the number in total
        $list | foreach-object { $total++ } 
    
        "$ready out of $total are ready"
    
        if (($ready -ne $total) -and ($remainingTries -gt 0)) {
            # Not all ready, so sleep for 10 seconds before trying again
            Start-Sleep -s 10
        }
        else {
            if ($ready -ne $total) {
                throw "Timed out while waiting for service to be ready: $hostedService"
            }
    
            break;
        }
    }
    while ($true)
    

    【讨论】: