VM 应用程序概览
VM 应用程序是 Azure Compute Gallery(以前称为共享映像库)中的一种资源类型,可以简化虚拟机应用程序的管理、共享和全局分发。
尽管可以创建预安装了应用的 VM 的映像,但每次应用程序变化时都需要更新映像。 如果将应用程序安装与 VM 隔离,则意味着无需在更改每行代码后都要发布新的映像。
与其他部署和打包方法相比,应用程序包具有以下优点:
VM 应用程序支持 Azure 策略
对包进行分组和版本控制
VM 应用程序可以全局复制以更接近你的基础结构,因此你无需使用AzCopy 或其他存储复制机制来跨 Azure 区域复制代码。
通过 Azure 基于角色的访问控制 (RBAC) 与其他用户共享
支持虚拟机,以及灵活和统一规模集
如果你的 VM 或规模集上应用了网络安全组 (NSG) 规则,可能无法从 Internet 存储库下载包。 对于存储帐户,将包下载到锁定的 VM 需要设置专用链接。
支持块 Blob:此功能可通过将大文件分成更小的可管理块来有效地处理大文件。 非常适合上传大量数据、流式处理和后台上传。
什么是 VM 应用包?
VM 应用程序包使用多种资源类型:
资源 | 说明 |
---|---|
Azure Compute Gallery | 库是用于管理和共享应用程序包的存储库。 用户可以共享库资源,所有子资源将自动共享。 每个订阅的库名称必须是唯一的。 例如,你可能有一个库用来存储所有操作系统映像,另一个库用来存储所有 VM 应用程序。 |
VM 应用程序 | VM 应用程序的定义。 这是一个逻辑资源,用于存储其中所有版本的公共元数据。 例如,你可能有一个 Apache Tomcat 的应用程序定义,其中有多个版本。 |
VM 应用程序版本 | 可部署的资源。 可以将 VM 应用程序版本全局复制到离 VM 基础设施更近的目标区域。 必须先将 VM 应用程序版本复制到区域,然后才能将其部署到该区域中的 VM 上。 |
限制
每个区域不超过 3 个副本:创建 VM 应用程序版本时,每个区域的最大副本数量是三个。
具有公共访问权限的存储或具有读取权限的 SAS URI:存储帐户需要具有公共级别访问权限或使用具有读取权限的 SAS URI,因为其他限制级别会导致部署失败。
重试失败的安装:目前,重试失败的安装的唯一方法是从配置文件中删除该应用程序,然后将其重新添加。
每台 VM 仅限 25 个应用程序:任何时候均不得将超过 25 个应用程序部署到一台 VM。
2GB 应用程序大小:应用程序版本的最大文件大小为 2GB。
不能保证实现脚本中的重新启动功能:如果脚本需要重新启动,则建议在部署过程中将该应用程序置于最后。 尽管代码会尝试处理重启,但可能会失败。
需要 VM 代理:VM 代理必须存在于 VM 中,并且必须能够收到目标状态。
同一 VM 上的同一应用程序的多个版本:不能在一个 VM 上安装同一应用程序的多个版本。
当前不支持移动操作:目前不支持使用 VM 应用将 VM 移动到其他资源组。
注意
对于 Azure Compute Gallery 和 VM 应用程序,可以在复制后删除存储 SAS。 但是,任何后续更新操作都需要有效的 SAS。
成本
使用 VM 应用程序包不会产生额外的费用,但以下资源需要付费:
- 存储每个包和任何副本的存储成本。
- 将第一个映像版本从源区域复制到目标区域的网络传出费用。 后续副本将在区域内进行处理,因此不会产生额外费用。
有关网络流出量的详细信息,请参阅带宽定价。
VM 应用程序
VM 应用程序资源定义有关 VM 应用程序的以下内容:
- 存储 VM 应用程序的 Azure Compute Gallery
- 应用程序的名称
- 支持的操作系统类型,如 Linux 或 Windows
- VM 应用程序的说明
VM 应用程序版本
VM 应用程序版本是可部署的资源。 版本是用以下属性定义的:
- 版本号
- 链接到存储帐户中的应用程序包文件
- 安装用于安装应用程序的字符串
- 删除字符串以显示如何正确地删除应用
- 将包文件下载到 VM 时要使用的包文件名
- 要用于在 VM 上配置应用的配置文件名
- 指向 VM 应用程序的配置文件(其中可加入许可证文件)的链接
- 更新字符串以了解如何将 VM 应用程序更新到更高版本
- 生命周期结束日期。 生命周期结束日期仅供参考;你仍可以在生命周期日期后部署 VM 应用程序版本。
- 最新版本中不包含它。 可将某个版本设为不用作最新版本的应用程序。
- 用于复制的目标区域
- 每个区域的副本计数
下载目录
应用程序包和配置文件的下载位置如下:
- Linux:
/var/lib/waagent/Microsoft.CPlat.Core.VMApplicationManagerLinux/<appname>/<app version>
- Windows:
C:\Packages\Plugins\Microsoft.CPlat.Core.VMApplicationManagerWindows\1.0.9\Downloads\<appname>\<app version>
假设应用程序包和配置文件位于当前目录中,则应写入安装/更新/删除命令。
文件命名
将应用程序文件下载到 VM 后,它将重命名为“MyVmApp”(没有扩展名)。 这是因为 VM 不知道包的原始名称或扩展名。 它利用它唯一的名称,即应用程序名称本身 - “MyVmApp”。
下面是一些用于导航此问题的替代方法:
可以修改脚本以包含用于在执行前重命名文件的命令:
move .\\MyVmApp .\\MyApp.exe & MyApp.exe /S
还可以使用 packageFileName
(和相应的 configFileName
)属性来指示我们重命名文件的内容。 例如,将其设置为“MyApp.exe”将使安装脚本只需为:
MyAppe.exe /S
提示
如果 Blob 最初名为“myApp.exe”而不是“myapp”,则上述脚本无需设置 packageFileName
属性即可正常运行。
命令解释器
默认的命令解释器是:
- Linux:
/bin/bash
- Windows:
cmd.exe
只要它安装在计算机上,通过调用可执行文件并将命令传递给它,就可以使用不同的解释器,如 Chocolatey 或 PowerShell。 例如,若要让命令在 Windows 上的 PowerShell 中运行,而不是在 cmd 中运行,可以传递 powershell.exe -Command '<powershell commmand>'
如何处理更新
当更新在 VM 或虚拟机规模集上的应用程序版本时,将使用在部署期间提供的更新命令。 如果更新后的版本没有更新命令,则删除当前版本并安装新版本。
写入更新命令时,应假定能够从任何旧版本的 VM 应用程序进行更新。
关于在 Linux 上创建 VM 应用程序的技巧
适用于 Linux 的第三方应用程序可以通过几种方式打包。 让我们探讨如何针对一些最常见情况创建安装命令。
.tar 和 .gz 文件
这些文件是压缩存档,可提取到所需位置。 如需将原始程序包提取到特定位置,请查看原始包的安装说明。 如果 .tar.gz 文件包含源代码,请参阅包的说明以了解如何从源位置安装。
在 Linux 计算机上安装 golang
的安装命令示例:
sudo tar -C /usr/local -xzf go_linux
删除命令示例:
sudo rm -rf /usr/local/go
使用 .deb
、.rpm
和其他供 Internet 访问受限的 VM 使用的特定于平台的包创建应用程序包
可以为特定于平台的包管理器下载单独的包,但这些包通常不一定包含所有依赖项。 对于这些文件,还必须在应用程序包中包括所有依赖项,或者让系统包管理器通过 VM 可用的存储库来下载依赖项。 如果使用的 VM 在 Internet 访问方面受到限制,则必须自己打包所有依赖项。
找出依赖项可能有点棘手。 有第三方工具可以显示整个依赖项树。
在 Ubuntu 中,你可以运行 sudo apt show <package_name> | grep Depends
显示执行 sudo apt-get install <packge_name>
命令时安装的所有包。 然后,可以使用该输出下载所有 .deb
文件,以创建可用作应用程序包的存档。
- 例如,若要创建 VM 应用程序包来安装适用于 Ubuntu 的 PowerShell,请先运行以下命令启用可以从中下载 PowerShell 的存储库,并标识新 Ubuntu VM 上的包依赖项。
# Download the Microsoft repository GPG keys
wget -q "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb"
# Register the Microsoft repository GPG keys
sudo dpkg -i packages-microsoft-prod.deb
sudo rm -rf packages-microsoft-prod.deb
sudo apt update
sudo apt show powershell | grep Depends
- 请检查列出以下包的行“依赖”的输出:
Depends: libc6, lib32gcc-s1, libgssapi-krb5-2, libstdc++6, zlib1g, libicu72|libicu71|libicu70|libicu69|libicu68|libicu67|libicu66|libicu65|libicu63|libicu60|libicu57|libicu55|libicu52, libssl3|libssl1.1|libssl1.0.2|libssl1.
- 使用
sudo apt-get download <package_name>
下载其中的每个文件,然后创建包含所有文件的 tar 压缩存档。
- Ubuntu 18.04:
mkdir /tmp/powershell
cd /tmp/powershell
sudo apt-get download libc6
sudo apt-get download lib32gcc-s1
sudo apt-get download libgssapi-krb5-2
sudo apt-get download libstdc++6
sudo apt-get download zlib1g
sudo apt-get download libssl1.1
sudo apt-get download libicu60
sudo apt-get download powershell
sudo tar -cvzf powershell.tar.gz *.deb
- Ubuntu 20.04:
mkdir /tmp/powershell
cd /tmp/powershell
sudo apt-get download libc6
sudo apt-get download lib32gcc-s1
sudo apt-get download libgssapi-krb5-2
sudo apt-get download libstdc++6
sudo apt-get download zlib1g
sudo apt-get download libssl1.1
sudo apt-get download libicu66
sudo apt-get download powershell
sudo tar -cvzf powershell.tar.gz *.deb
- Ubuntu 22.04:
mkdir /tmp/powershell
cd /tmp/powershell
sudo apt-get download libc6
sudo apt-get download lib32gcc-s1
sudo apt-get download libgssapi-krb5-2
sudo apt-get download libstdc++6
sudo apt-get download zlib1g
sudo apt-get download libssl3
sudo apt-get download libicu70
sudo apt-get download powershell
sudo tar -cvzf powershell.tar.gz *.deb
- 此 tar 存档将是应用程序包文件。
- 在这种情况下,安装命令为:
sudo tar -xvzf powershell.tar.gz && sudo dpkg -i *.deb
- 删除命令为:
sudo apt remove powershell
使用 sudo apt autoremove
,而不是明确尝试删除所有依赖项。 你可能已经安装了包含重叠依赖项的其他应用程序,在这种情况下,显式删除命令将失败。
如果你不想自行解决依赖项并且 apt
能够连接到存储库,则可以使用一个 .deb
文件来安装应用程序,并让 apt
处理依赖项。
安装命令示例:
dpkg -i <package_name> || apt --fix-broken install -y
关于在 Windows 上创建 VM 应用程序的技巧
Windows 中的大多数第三方应用程序作为 .exe 或 .msi 安装程序提供。 部分应用程序还可用作提取和运行 zip 文件。 让我们看看每种格式的最佳实践。
.exe 安装程序
安装程序可执行文件通常启动用户界面 (UI),并要求用户选择 UI。 如果安装程序支持静默模式参数,则应将此参数包含在安装字符串中。
cmd.exe 还要求可执行文件具有扩展名 .exe
,因此你需要重命名该文件,加上 .exe
扩展名。
如果我想为作为可执行文件提供的 myApp.exe
创建一个 VM 应用程序包,我的 VM 应用程序称为“myApp”,所以我编写命令时假设应用程序包在当前目录中:
"move .\\myApp .\\myApp.exe & myApp.exe /S -config myApp_config"
如果安装程序可执行文件不支持卸载参数,有些情况下你可以在测试计算机上查找注册表,以了解卸载程序所在的位置。
在注册表中,卸载字符串存储在 Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\<installed application name>\UninstallString
中,因此我将使用内容作为删除命令:
'\"C:\\Program Files\\myApp\\uninstall\\helper.exe\" /S'
.msi 安装程序
要通过命令行来执行 .msi
安装程序,安装或删除应用程序的命令应使用 msiexec
。 通常,msiexec
作为单独的进程运行,cmd
不会等待它完成,这可能会导致在安装多个 VM 应用程序时出现问题。 start
命令可以与 msiexec
结合使用,以确保在命令返回之前安装完成。 例如:
start /wait %windir%\\system32\\msiexec.exe /i myapp /quiet /forcerestart /log myapp_install.log
删除命令示例:
start /wait %windir%\\system32\\msiexec.exe /x $appname /quiet /forcerestart /log ${appname}_uninstall.log
通常,start
命令将在批处理脚本中调用。 如果与 /wait
参数一起使用,调用脚本将暂停,直到被调用的进程终止。 完成后,批处理脚本将检查 start
命令设置的 errorlevel
变量,然后退出,如下所示:
start /wait %windir%\\system32\\msiexec.exe /i myapp /quiet /forcerestart /log myapp_install.log
if %errorlevel% neq 0 exit /b %errorlevel%
...
压缩文件
对于.zip 或压缩文件,请将应用程序包的内容重命名并解压到所需的目标。
安装命令示例:
rename myapp myapp.zip && mkdir C:\myapp && powershell.exe -Command "Expand-Archive -path myapp.zip -destinationpath C:\myapp"
删除命令示例:
rmdir /S /Q C:\\myapp
将失败视为部署失败
无论在安装/更新/删除时是否有任何 VM 应用程序失败,VM 应用程序扩展始终会返回成功。 仅当扩展或底层基础架构出现问题时,VM 应用程序扩展才将扩展状态报告为失败。 此行为是由“将失败视为部署失败”标志触发的,该标志默认设置为 $false
,并且可以更改为 $true
。 失败标志可以在 PowerShell 或 CLI 中配置。
排查 VM 应用程序问题
若要了解是否已成功将特定 VM 应用程序添加到 VM 实例,请查看 VM 应用程序扩展的消息。
若要详细了解如何获取 VM 扩展的状态,请参阅 Linux 的虚拟机扩展和功能和 Windows 的虚拟机扩展和功能。
若要获取 VM 扩展的状态,请使用 Get-AzVM:
Get-AzVM -name <VM name> -ResourceGroupName <resource group name> -Status | convertto-json -Depth 10
若要获取规模集扩展的状态,请使用 Get-AzVMSS:
$result = Get-AzVmssVM -ResourceGroupName $rgName -VMScaleSetName $vmssName -InstanceView
$resultSummary = New-Object System.Collections.ArrayList
$result | ForEach-Object {
$res = @{ instanceId = $_.InstanceId; vmappStatus = $_.InstanceView.Extensions | Where-Object {$_.Name -eq "VMAppExtension"}}
$resultSummary.Add($res) | Out-Null
}
$resultSummary | convertto-json -depth 5
Error messages
Message | 说明 |
---|---|
当前 VM 应用程序版本 {name} 已于 {date} 弃用。 | 你尝试部署的 VM 应用程序版本已被弃用。 尝试使用 latest ,而不是指定特定的版本。 |
当前 VM 应用程序版本 {name} 支持操作系统 {OS},而当前 OSDisk 的操作系统为 {OS}。 | 你尝试将 Linux 应用程序部署到 Windows 实例,或者反之。 |
已超过了 VM 应用程序的最大数量(最大值=5,当前值={count})。 使用较少的应用程序并重试请求。 | 目前每个 VM 或规模集仅支持 5 个 VM 应用程序。 |
指定了多个具有相同 packageReferenceId 的 VMApplication。 | 多次指定了相同的应用程序。 |
订阅无权访问此映像。 | 订阅无权访问此应用程序版本。 |
参数中的存储帐户不存在。 | 没有此订阅的通知。 |
平台映像 {image} 不可用。 确认存储配置文件中的所有字段均正确。 有关存储配置文件的更多详细信息,请参阅https://aka.ms/storageprofile。 | 应用程序不存在。 |
库映像 {image} 在 {region} 区域中不可用。 请联系映像所有者以将其复制到此区域,或者更改你请求的区域。 | 库应用程序版本存在,但未复制到此区域。 |
SAS 对于源 uri {uri} 无效。 | 尝试检索有关 url(mediaLink 或 defaultConfigurationLink)的信息时从存储收到 Forbidden 错误。 |
源 uri {uri} 引用的 Blob 不存在。 | 为 mediaLink 或 defaultConfigurationLink 属性提供的 Blob 不存在。 |
由于以下错误,无法访问库库应用程序版本 url {url}:找不到远程名称。 确保 blob 存在并且可公开访问,或者是具有读取权限的 SAS url。 | 最可能的情况是未提供具有读取权限的 SAS uri。 |
由于以下错误,无法访问库库应用程序版本 url {url}:{error description}。 确保 blob 存在并且可公开访问,或者是具有读取权限的 SAS url。 | 提供的存储 blob 存在问题。 错误描述提供更多信息。 |
{Application} 上不允许使用操作 {operationName},因为该操作已被标记为删除。 只能重试 Delete 操作(或等待当前操作完成)。 | 尝试更新当前正在删除的应用程序。 |
参数“galleryApplicationVersion.properties.publishingProfile.replicaCount”的值 {value} 超出范围。 此值必须介于 1 到 3 之间(均含)。 | VM Application 版本只允许 1 到 3 个副本。 |
不允许更改属性“galleryApplicationVersion.properties.publishingProfile.manageActions.install”。 (或更新、删除) | 无法更改现有 VmApplication 上的任何管理操作。 必须创建新的 VmApplication 版本。 |
不允许更改属性“galleryApplicationVersion.properties.publishingProfile.settings.packageFileName”。 (或 configFileName) | 无法更改任何设置,例如包文件名或配置文件名。 必须创建新的 VmApplication 版本。 |
源 uri {uri} 引用的 blob 太大:大小 = {size}。 允许的最大 blob 大小为“1 GB”。 | mediaLink 或 defaultConfigurationLink 引用的 blob 的最大大小当前为 1 GB。 |
源 uri {uri} 引用的 blob 为空。 | 引用了一个空的 blob。 |
{operation} 操作不支持 {type} blob 类型。 仅支持页 blob 和块 blob。 | VmApplications 仅支持页 blob 和块 blob。 |
SAS 对于源 uri {uri} 无效。 | 为 mediaLink 或 defaultConfigurationLink 提供的 SAS uri 不是有效的 SAS uri。 |
无法在目标区域指定 {region},因为订阅缺少必需的功能 {featureName}。 使用所需的功能注册订阅,或者从目标区域列表中删除区域。 | 若要在某些受限区域使用 VmApplication,必须为该订阅注册功能标志。 |
库映像版本发布配置文件区域 {regions} 必须包含映像版本的位置 {location}。 | 要复制的区域列表必须包含应用程序版本所在的位置。 |
目标发布区域中不允许出现重复区域。 | 发布区域不能有重复项。 |
库应用程序版本资源当前不支持加密。 | VM 应用程序不支持目标区域的加密属性 |
实体名称与请求 URL 中的名称不匹配。 | 请求 URL 中指定的库应用程序版本与请求正文中指定的版本不匹配。 |
库应用程序版本名称无效。 应用程序版本名称应遵循 Major(int32)。 Minor(int32)。 Patch(int32) 格式,其中 int 介于 0 到 2,147,483,647 之间(均含)。 例如 1.0.0、2018.12.1 等。 |
画廊应用程序版本必须遵循指定的格式。 |
后续步骤
- 了解如何创建和部署 VM 应用程序包。