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. 脚本看似执行成功但实例未更新,我遗漏了什么步骤?
主要遗漏以下关键环节:
- 未使用带SAS令牌的CSPKG URL:私有Blob下Azure无权限访问无SAS的CSPKG,导致更新请求提交后无法拉取新包,实例自然不会更新。
- 未正确初始化
$cspkgBlob变量:脚本中直接使用$cspkgBlob但没有看到获取该Blob对象的代码,会导致PackageUrl赋值错误。需要添加获取Blob的代码:
$cspkgBlob = Get-AzStorageBlob -Container "vs-deploy" -Blob "MyCloudService.cspkg" -Context $storageAccount.Context
- 未验证更新状态:
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 }
- 目标云服务匹配可能出错:
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
相关产品推荐
相关产品推荐

