我对 Azure APIS 越来越疯狂:-D 我们注意到,每次我分配 VM 时,都会重新执行通过使用 Azure Management Fluent API 1.34.0 构建的内部应用程序“注入”的每个 PowerShell 脚本。该脚本存储在一个存储帐户中,应用程序会小心地在 VM 中下载并执行它。该文件在“C:\Packages\Plugins\Microsoft.CPlat.Core.RunCommandWindows\1.1.5\Downloads”文件夹中一次又一次地下载。我究竟做错了什么?
2 回答
只是更新:在与 Azure 支持团队进行调查后,我与一位 Microsoft 高级工程师交谈,他发现 Azure 后端存在错误
根本原因是 VM 之前已用于调用 RunCommand API,而这仍保留在我们内部存储的 VM 模型中。当您交换磁盘时,此模型不会更改,并且 VM 配置文件包含(对您隐藏)RunCommandWindows 扩展,该扩展在新的 OSDisk 上执行,因为如果先前执行的标志存储在注册表中(当您交换盘)。我们同意您的方案需要修复,以便在交换 OSdisk 时清除 VM 模型中的运行命令。在我们准备和部署修复程序之前(通常在 1 个月内),我可以建议您在交换磁盘之前应用一种缓解措施。您可以通过调用带有 commandId = RemoveRunCommandWindowsExtension 的特殊运行命令从 VM 模型中删除运行命令扩展。它在门户上不可用,但您可以使用 REST、CLI、Powershell 或 .Net API。例如: Invoke-AzureRmVMRunCommand -ResourceGroupName 'rgname' -Name 'vmname' -CommandId 'RemoveRunCommandWindowsExtension' Powershell Invoke-AzureRmVMRunCommand -ResourceGroupName 'rgname' -Name 'vmname' -CommandId 'RemoveRunCommandWindowsExtension' CLI az vm run-command invoke -g MyResourceGroup -n MyVM --command-id RemoveRunCommandWindowsExtension 这将删除扩展,并且在您交换磁盘后它将不再安装和运行。
我希望此解决方法将对其他人有所帮助,直到将修复程序应用到支持中。
这是代码
public async Task<string> RunBasePowershellAsync(string virtualMachineName, string file, Dictionary<string, string> psParams = null)
{
if (psParams == null)
{
psParams = new Dictionary<string, string>();
}
var vm = _azure.VirtualMachines.List().SingleOrDefault(v => v.Name == virtualMachineName);
if (vm == null)
{
throw new BoardCloudServiceException($"Virtual Machine {vm} not found!");
}
var httpRequest = (HttpWebRequest)WebRequest.Create(file);
httpRequest.Method = WebRequestMethods.Http.Get;
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
var encoding = string.IsNullOrEmpty(httpResponse.CharacterSet)
? Encoding.UTF8
: Encoding.GetEncoding(httpResponse.CharacterSet);
using var stream = httpResponse.GetResponseStream();
using var reader = new StreamReader(stream, encoding);
var responseString = reader.ReadToEnd();
var lines = responseString.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
var result = await vm.RunPowerShellScriptAsync(lines, psParams.Select(p => new RunCommandInputParameter(p.Key, p.Value)).ToList());
return string.Join("", result.Value.Select(v => v.Message));
}