You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure云服务(扩展支持)PowerShell更新问题咨询

Azure Cloud Service (Extended Support) PowerShell更新脚本问题解析

场景描述

我频繁在Azure门户更新Cloud Service (Extended Support)实例并与另一实例交换,已有脚本可将CSPKG、CSDEF、CSCFG文件上传至Blob存储,流程正常。手动在门户通过Blob存储更新实例需7-9分钟,但我编写的PowerShell更新脚本看似执行成功,实例却未实际更新。脚本内容如下:

# Get an SAS token to CSPKG
Write-Host "$(Get-Date -f $timeStampFormat) Getting CSPKG Shared Access Signature (SAS) token" -ForegroundColor DarkCyan 
#$tokenStartTime = Get-Date
#$tokenEndTime = $tokenStartTime.AddYears(1)
#$cspkgToken = New-AzStorageBlobSASToken -Container “vs-deploy” -Blob “MyCloudService.cspkg” -Permission rwd -StartTime $tokenStartTime -ExpiryTime $tokenEndTime -Context $storageAccount.Context 

$cloudService = (Get-AzCloudService) |
    Where-Object {
        $_.networkProfile.LoadBalancerConfiguration.FrontendIPConfiguration.PublicIPAddressId -like "*MyIP"
    }    
$stagingServiceName = $cloudService.Name

Write-Host "$(Get-Date -f $timeStampFormat) Deploying to {0} Cloud Service" -f $stagingServiceName -ForegroundColor DarkCyan

# Load the CSCFG XML into a string from local drive
$cscfgContent = Get-Content $cscfgFilePath | Out-String

try {
    Write-Host "URI for blob: "$cspkgBlob.ICloudBlob.Uri.AbsoluteUri
    # Update the cloud service
    $cloudService.PackageUrl = $cspkgBlob.ICloudBlob.Uri.AbsoluteUri
    $cloudService.Configuration = $cscfgContent
    $cloudService | Update-AzCloudService
} catch {
    Write-Host "$(Get-Date -f $timeStampFormat) Cloud Service {0} failed to update: {1}" -f $service, $_.Exception.Message -ForegroundColor Red
    break;
}

Write-Host "$(Get-Date -f $timeStampFormat) Finished"

问题解答

1. 为何门户更新需CSDEF文件,但脚本中未提及该文件?

CSDEF(服务定义文件)是CSPKG包的组成部分,当你将CSPKG上传到Blob时,CSDEF已经被打包进CSPKG内部。Azure门户要求单独选择CSDEF,是为了在更新前验证包内的服务定义与你提供的是否一致,防止误操作。而通过PowerShell调用Update-AzCloudService时,直接使用包含CSDEF的CSPKG即可,无需单独指定CSDEF文件。

2. 部分更新方法需SAS令牌,当前脚本未使用是否遗漏了配置?

如果你的Blob容器是私有访问权限,Azure服务必须通过SAS令牌才能读取CSPKG文件。你的脚本里虽然写了生成SAS令牌的代码,但被注释掉了,且最终给PackageUrl赋值的是Blob的原始URI(不带SAS参数),这会导致Azure无法访问私有Blob中的CSPKG。正确做法是将SAS令牌拼接在Blob URI后面,生成带权限的完整URL:

$tokenStartTime = Get-Date
$tokenEndTime = $tokenStartTime.AddHours(2) # 有效期设为足够完成部署的时长即可
$cspkgToken = New-AzStorageBlobSASToken -Container "vs-deploy" -Blob "MyCloudService.cspkg" -Permission r -StartTime $tokenStartTime -ExpiryTime $tokenEndTime -Context $storageAccount.Context
$cloudService.PackageUrl = $cspkgBlob.ICloudBlob.Uri.AbsoluteUri + "?" + $cspkgToken

注意权限只需r(读取)即可,不需要wd。

3. 如何从Blob存储读取CSCFG文件,而非从本地读取?

有两种常见方式:

  • 方式一:下载到临时路径再读取
# 下载Blob中的CSCFG到临时文件
$tempCscfgPath = Join-Path $env:TEMP "MyCloudService.cscfg"
Get-AzStorageBlobContent -Container "vs-deploy" -Blob "MyCloudService.cscfg" -Destination $tempCscfgPath -Context $storageAccount.Context
# 读取内容
$cscfgContent = Get-Content $tempCscfgPath | Out-String
# 清理临时文件
Remove-Item $tempCscfgPath -Force
  • 方式二:通过SAS URL直接读取
# 生成CSCFG的只读SAS令牌
$cscfgToken = New-AzStorageBlobSASToken -Container "vs-deploy" -Blob "MyCloudService.cscfg" -Permission r -StartTime (Get-Date) -ExpiryTime (Get-Date).AddHours(1) -Context $storageAccount.Context
$cscfgFullUri = (Get-AzStorageBlob -Container "vs-deploy" -Blob "MyCloudService.cscfg" -Context $storageAccount.Context).ICloudBlob.Uri.AbsoluteUri + "?" + $cscfgToken
# 直接从URI读取内容
$cscfgContent = Invoke-RestMethod -Uri $cscfgFullUri -Method Get | Out-String

4. 脚本看似执行成功但实例未更新,我遗漏了什么步骤?

主要遗漏以下关键环节:

  1. 未使用带SAS令牌的CSPKG URL:私有Blob下Azure无权限访问无SAS的CSPKG,导致更新请求提交后无法拉取新包,实例自然不会更新。
  2. 未正确初始化$cspkgBlob变量:脚本中直接使用$cspkgBlob但没有看到获取该Blob对象的代码,会导致PackageUrl赋值错误。需要添加获取Blob的代码:
$cspkgBlob = Get-AzStorageBlob -Container "vs-deploy" -Blob "MyCloudService.cspkg" -Context $storageAccount.Context
  1. 未验证更新状态:Update-AzCloudService执行成功仅代表更新请求已提交,不代表部署完成。需要添加状态检查逻辑,确认更新是否真正完成:
# 提交更新后循环检查部署状态
do {
    $updatedService = Get-AzCloudService -Name $stagingServiceName -ResourceGroupName $cloudService.ResourceGroupName
    Write-Host "当前部署状态: $($updatedService.ProvisioningState) ($(Get-Date -f $timeStampFormat))"
    Start-Sleep -Seconds 30
} while ($updatedService.ProvisioningState -eq "Updating")

if ($updatedService.ProvisioningState -eq "Succeeded") {
    Write-Host "$(Get-Date -f $timeStampFormat) 实例更新成功完成" -ForegroundColor Green
} else {
    Write-Host "$(Get-Date -f $timeStampFormat) 实例更新失败,状态: $($updatedService.ProvisioningState)" -ForegroundColor Red
}
  1. 目标云服务匹配可能出错:Where-Object的条件可能匹配到多个实例,或者匹配到错误的服务。建议添加判断,确保只获取到一个目标实例:
$cloudService = (Get-AzCloudService) | Where-Object {
    $_.networkProfile.LoadBalancerConfiguration.FrontendIPConfiguration.PublicIPAddressId -like "*MyIP"
}
if ($cloudService.Count -ne 1) {
    Write-Host "找到$($cloudService.Count)个匹配的云服务,请检查筛选条件" -ForegroundColor Red
    exit 1
}
$stagingServiceName = $cloudService.Name

内容的提问来源于stack exchange,提问作者JayTee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 06:34:58