VM 应用程序概述

VM 应用程序是 Azure 计算库中的资源类型,提供一种现代、灵活的方法来管理和部署跨虚拟机和规模集的应用程序。 通过将应用程序安装与基本 VM 映像分离,可以简化更新、减少映像维护开销并加速部署周期。 此方法无需为每个应用程序更改重新生成和重新发布 VM 映像,从而实现更快的迭代和更高的作敏捷性。 VM 应用程序最适合在 Azure VM 上部署 AI、大规模、低延迟、微服务、安全且合规的工作负载。

资源 说明
Azure 计算画廊 画廊是用于管理和共享应用程序包的存储库。 用户可以共享库资源,所有子资源将自动共享。 每个订阅中的图库名称必须是唯一的。 例如,你可能有一个库用来存储所有操作系统映像,另一个库用来存储所有 VM 应用程序。
VM 应用程序 VM 应用程序的定义。 这是一个逻辑资源,用于存储其中所有版本的公共元数据。 例如,你可能有一个 Apache Tomcat 的应用程序定义,其中有多个版本。
VM 应用程序版本 可部署的资源,用于保存应用程序包和版本特定的配置。 可以将 VM 应用程序版本全局复制到离 VM 基础设施更近的目标区域。 必须先将 VM 应用程序版本复制到某个区域,然后才能将其部署到该区域中的 VM 上。
存储帐户 应用程序包首先上传到存储帐户。 然后,Azure 计算画廊使用 SAS URL 从这个存储帐户下载应用程序包,并将它存储在 VM 应用程序版本中。 Azure 计算库还会根据 VM 应用程序版本定义跨区域和区域副本复制此包。 在 Azure 计算库中创建 VM 应用程序版本后,可以删除存储帐户中的应用程序包。

显示创建 VM 应用程序并将其部署到 Azure 的步骤的关系图

主要优势:

  • 集中式和灵活的应用程序管理
    • 一次打包,随处部署:将应用程序 (windows/linux)、脚本或文件打包为虚拟机应用。 然后,在 Azure VM 或虚拟机规模集上部署它,并在 Azure 计算库中集中管理它们。 应用程序或文件可以是 .zip、.msi、.exe、.tar.gz、.deb、.rpm、.sh 或任何其他格式。
    • 版本控制:通过维护每个应用程序的多个版本来部署最新版本或特定版本。
  • 无缝共享和访问控制
    • Tenant-Wide 共享:在团队内或整个组织(租户)中共享应用程序。
    • 集成 RBAC:使用 Azure Role-Based 访问控制(RBAC)控制发布和部署访问。
  • 可靠且可自定义的部署
    • 单个应用程序控制:独立安装、更新或删除应用程序 -- 无需重新生成 VM 映像。
    • 可自定义的操作:自定义应用程序的安装、更新和删除操作,包括重新启动处理。
    • Built-In 故障处理:通过将 VM 应用程序故障连接到 VM 故障来确保可复原的部署。
  • 可扩展性与 Low-Latency 的分布
    • 全局复制和 Intra-Region 复制:自动跨区域和区域内复制应用程序以减少延迟并提高复原能力-无需 AzCopy 或手动传输。
    • 针对 High-Scale 方案进行了优化:确保即便在大规模部署期间,也能高效实现低创建延迟。
  • 从设计层面确保安全与合规
    • 策略驱动实施:使用 Azure Policy 在整个 IT 资源中实施应用程序的存在和配置。
    • 安全部署:避免基于互联网的下载和复杂的专用链接配置,这些方式并不适合受限或高安全性的环境。
  • 广泛的平台支持
    • VM 和规模集:部署到单个 VM、灵活的规模集或完全支持的统一规模集。
    • 块 Blob 支持:使用 Azure 块 Blob 高效处理大容量应用程序包(可达 2 GB),以实现分块上传和后台流式处理。

创建 VM 应用程序和 VM 应用程序版本资源

VM 应用程序存储在 Azure Compute Gallery 中。 VM 应用程序资源定义有关 VM 应用程序的以下内容:

资产 说明 局限性
姓名 应用程序的名称 最大长度为 117 个字符。 允许的字符为大写或小写字母、数字、连字符 (-)、句点 (.)、下划线 (_)。 名称不能以句点 (.) 结尾。
supportedOSType 定义支持的 OS 类型 “Linux”或“Windows”
endOfLifeDate 应用程序的未来生命周期结束日期。 日期仅供参考,不会强制执行。
描述 可选。 VM 应用程序的说明
eula 可选。 参考最终用户许可协议 (EULA)
privacyStatementUri 可选。 参考应用程序的隐私声明。
releaseNoteUri 可选。 参考应用程序的发行说明。

VM 应用程序版本是 VM 应用程序资源中的可部署资源。 版本是用以下属性定义的:

资产 说明 局限性
位置 VM 应用程序版本的源位置。 有效的 Azure 区域
source/mediaLink 链接到存储帐户中的应用程序包文件 现有的有效存储 URL
source/defaultConfigurationLink 可选。 指向 VM 应用程序的配置文件的链接。 可以在部署时重写。 现有的有效存储 URL
manageActions/install 以字符串形式安装脚本,以正确安装应用程序 字符串格式的给定操作系统的有效命令。
manageActions/remove 以字符串形式移除脚本,以正确移除应用程序 字符串格式的给定操作系统的有效命令
manageActions/update 可选。 以字符串形式更新脚本,以将 VM 应用程序正确更新到较新的版本。 字符串格式的给定操作系统的有效命令
targetRegions/name 要复制到的目标区域的名称。 提高区域故障的复原能力并产生延迟。 有效的 Azure 区域
targetRegions/regionalReplicaCount 可选。 在该区域中创建的副本数量。 改进负载处理并产生延迟。 默认值为 1。 介于 1 和 3 之间(含限值)的整数
replicaCount 可选。 定义每个区域的副本数。 如果未定义 regionalReplicaCount,则生效。 在区域或群集发生故障时提升复原能力,同时在大规模场景下会产生延迟。 介于 1 和 3 之间(含限值)的整数。
endOfLifeDate 可选。 应用程序版本的未来生命周期结束日期。 此属性仅供客户参考,不会强制实施。 有效的未来日期
excludeFromLatest 当在 applicationProfile 中使用“latest”关键字时,请排除用作应用程序最新版本的版本。
storageAccountType 可选。 要在每个区域中用于存储应用程序包的存储帐户的类型。 默认为 Standard_LRS。 此属性不可更新。
safetyProfile/allowDeletionOfReplicatedLocations 可选。 指示是否允许从复制区域删除此库映像版本。
settings/packageFileName 将包下载到 VM 时要使用的包文件名。 最多包含 4,096 个字符。
settings/configFileName 将配置下载到 VM 时要使用的配置文件名称。 最多包含 4,096 个字符。
settings/scriptBehaviorAfterReboot 可选。 重启 VM 后安装、更新或删除库应用程序时要执行的操作。

{
  "$schema": "https://schema.management.azure.com/schemas/2020-06-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "galleryName": {
      "type": "string"
    },
    "applicationName": {
      "type": "string"
    },
    "versionName": {
      "type": "string",
      "metadata": {
        "description": "Must follow the format: major.minor.patch (Example: 1.0.0)"
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "China North 2"
    },
    "supportedOSType": {
      "type": "string",
      "allowedValues": ["Windows", "Linux"]
    },
    "endOfLifeDate": {
      "type": "string",
      "metadata": {
        "description": "Optional. This property is for information only and doesn't block app deployment."
      }
    },
    "description": {
      "type": "string",
      "defaultValue": "Description of the application"
    },
    "eula": {
      "type": "string",
      "defaultValue": ""
    },
    "privacyStatementUri": {
      "type": "string",
      "defaultValue": ""
    },
    "releaseNoteUri": {
      "type": "string",
      "defaultValue": ""
    },
    "mediaLink": {
      "type": "string"
    },
    "configLink": {
      "type": "string"
    },
    "appConfigFileName": {
      "type": "string"
    },
    "appPackageFileName": {
      "type": "string"
    },
    "replicaRegion1": {
      "type": "string",
      "defaultValue": "China North"
    },
    "replicaRegion2": {
      "type": "string",
      "defaultValue": "China North"
    },
    "installScript": {
      "type": "string",
      "metadata": {
        "description": "Optional. Script to run to install the application. Example: echo 'Installing application...'"
      }
    },
    "updateScript": {
      "type": "string",
      "metadata": {
        "description": "Optional. Script to run to update the application. Example: echo 'Updating application...'"
      }
    },
    "removeScript": {
      "type": "string",
      "metadata": {
        "description": "Optional. Script to run to delete the application. Example: echo 'Deleting application...'"
      }
    },
    "storageAccountType": {
      "type": "string",
      "allowedValues": ["PremiumV2_LRS", "Premium_LRS", "Standard_LRS", "Standard_ZRS"],
      "defaultValue": "Standard_LRS"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Compute/galleries",
      "apiVersion": "2024-03-03",
      "name": "[parameters('galleryName')]",
      "location": "[parameters('location')]",
      "properties": {
        "identifier": {}
      }
    },
    {
      "type": "Microsoft.Compute/galleries/applications",
      "apiVersion": "2024-03-03",
      "name": "[format('{0}/{1}', parameters('galleryName'), parameters('applicationName'))]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Compute/galleries', parameters('galleryName'))]"
      ],
      "properties": {
        "supportedOSType": "[parameters('supportedOSType')]",
        "endOfLifeDate": "[parameters('endOfLifeDate')]",
        "description": "[parameters('description')]",
        "eula": "[if(equals(parameters('eula'), ''), json('null'), parameters('eula'))]",
        "privacyStatementUri": "[if(equals(parameters('privacyStatementUri'), ''), json('null'), parameters('privacyStatementUri'))]",
        "releaseNoteUri": "[if(equals(parameters('releaseNoteUri'), ''), json('null'), parameters('releaseNoteUri'))]"
      }
    },
    {
      "type": "Microsoft.Compute/galleries/applications/versions",
      "apiVersion": "2024-03-03",
      "name": "[format('{0}/{1}/{2}', parameters('galleryName'), parameters('applicationName'), parameters('versionName'))]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Compute/galleries/applications', parameters('galleryName'), parameters('applicationName'))]"
      ],
      "properties": {
        "publishingProfile": {
          "source": {
            "mediaLink": "[parameters('mediaLink')]",
            "defaultConfigurationLink": "[parameters('configLink')]"
          },
          "manageActions": {
            "install": "[parameters('installScript')]",
            "remove": "[parameters('removeScript')]",
            "update": "[parameters('updateScript')]"
          },
          "settings": {
            "scriptBehaviorAfterReboot": "Rerun",
            "configFileName": "[parameters('appConfigFileName')]",
            "packageFileName": "[parameters('appPackageFileName')]"
          },
          "targetRegions": [
            {
              "name": "[parameters('location')]",
              "regionalReplicaCount": 3,
              "storageAccountType": "[parameters('storageAccountType')]"
            },
            {
              "name": "[parameters('replicaRegion1')]",
              "regionalReplicaCount": 1,
              "storageAccountType": "[parameters('storageAccountType')]"
            },
            {
              "name": "[parameters('replicaRegion2')]"
            },
          ],
          "excludeFromLatest": false,
          "replicaCount": 2,
          "storageAccountType": "[parameters('storageAccountType')]"
        },
        "safetyProfile": {
          "allowDeletionOfReplicatedLocations": true
        },
        "endOfLifeDate": "[parameters('endOfLifeDate')]"
      }
    }
  ]
}

部署 Azure VM 应用程序

将 VM 应用程序版本发布到 Azure Compute Gallery 后,可以跨 Azure 虚拟机 (VM) 和 Azure 虚拟机规模集部署版本。

Azure VM 和虚拟机规模集中的 applicationProfile 定义如下内容:

资产 说明 局限性
galleryApplications 要部署的 Gallery 应用程序
包裹参考编号 对要部署的应用程序版本的引用 有效的应用程序版本引用
configurationReference 可选。 包含此部署的配置的存储 Blob 的完整 URL。 这会替代之前为 defaultConfiguration 提供的任何值。 有效的存储 Blob 引用
顺序 可选。 部署应用程序的顺序 有效的整数
treatFailureAsDeploymentFailure 可选。 将应用程序失败标记为 VM 部署失败以处理故障 真或假

Order 字段可用于指定应用程序之间的依赖关系。 排序规则如下:

案例 安装时的含义 失败时的含义
未指定顺序 先安装有序应用程序,再安装无序应用程序。 对于无顺序的应用程序,其安装顺序无法保证。 其他应用程序(无论是有序还是无序)安装失败不会影响无序应用程序的安装。
重复顺序值 与遵循相同顺序的其他应用程序不同,按任意顺序安装应用程序。 相同顺序的所有应用程序将在低顺序的应用程序之后、高顺序的应用程序之前安装。 如果之前顺序更低的应用程序安装失败,则不安装此顺序的任何应用程序。 如果此顺序的任何应用程序安装失败,则不安装顺序更高的应用程序。
提高顺序 应用程序将在低顺序的应用程序之后、高顺序的应用程序之前安装。 如果前面的低顺序应用程序安装失败,则不会安装此应用程序。 如果此应用程序安装失败,则不安装顺序更高的应用程序。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "vmssName": {
      "type": "string"
    },
    "location": {
      "type": "string"
    },
    "subscriptionId": {
      "type": "string"
    },
    "resourceGroupName": {
      "type": "string"
    },
    "galleryName": {
      "type": "string"
    },
    "applicationName1": {
      "type": "string"
    },
    "applicationVersion1": {
      "type": "string",
      "defaultValue": "latest"
    },
    "configurationReference1": {
      "type": "string",
      "metadata": {
        "description": "Optional path to configuration file from Storage Account. Overrides default configuration file."
      }
    },
    "applicationName2": {
      "type": "string"
    },
    "applicationVersion2": {
      "type": "string",
      "defaultValue": "latest"
    }
  },
  "variables": {
    "packageReferenceId1": "[format('/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/galleries/{2}/applications/{3}/versions/{4}', parameters('subscriptionId'), parameters('resourceGroupName'), parameters('galleryName'), parameters('applicationName1'), parameters('applicationVersion1'))]",
    "packageReferenceId2": "[format('/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/galleries/{2}/applications/{3}/versions/{4}', parameters('subscriptionId'), parameters('resourceGroupName'), parameters('galleryName'), parameters('applicationName2'), parameters('applicationVersion2'))]"
  },
  "resources": [
    {
      "type": "Microsoft.Compute/virtualMachineScaleSets",
      "apiVersion": "2024-03-03",
      "name": "[parameters('vmssName')]",
      "location": "[parameters('location')]",
      "properties": {
        "virtualMachineProfile": {
          "applicationProfile": {
            "galleryApplications": [
              {
                "order": 1,
                "packageReferenceId": "[variables('packageReferenceId1')]",
                "configurationReference": "[parameters('configurationReference1')]",
                "treatFailureAsDeploymentFailure": true
              },
              {
                "order": 2,
                "packageReferenceId": "[variables('packageReferenceId2')]",
                "treatFailureAsDeploymentFailure": false
              }
            ]
          }
        }
      }
    }
  ]
}

成本

使用 VM 应用程序包不会产生额外的费用,但以下资源需要付费:

  • 存储每个包和任何副本的存储成本。
  • 将第一个映像版本从源区域复制到目标区域的网络传出费用。 后续副本将在区域内进行处理,因此不会产生额外费用。

有关网络流出量的详细信息,请参阅带宽定价

技术详细信息

注意事项和当前限制

  • 每个区域最多 10 个副本:创建 VM 应用程序版本时,每个区域的页面 Blob 和块 Blob 副本的最大数量是 10。

  • 每个区域最多 300 个版本:创建 VM 应用程序版本时,每个区域最多可以有 300 个应用程序版本。

  • 具有公共访问权限的存储以及具有读取权限的 SAS URI: 存储帐户需要具有公共级别访问权限并使用具有读取权限的 SAS URI,因为其他限制级别会失败部署。 通过允许匿名访问在存储帐户上发布项目,可以绕过 SAS 令牌。

  • 失败安装手动重试:目前,重试失败安装的唯一方法是从配置文件中删除应用程序,然后将其添加回。

  • 每个 VM 最多 25 个应用程序:最多可以将 25 个应用程序部署到单个虚拟机。

  • 2 GB 应用程序大小:应用程序版本 mediaLink 的最大文件大小为 2 GB。 最大文件大小 defaultConfigurationLink 为 1 GB。

  • 需要 VM 代理:VM 代理必须存在于 VM 中,并且必须能够收到目标状态。

  • 每个 VM 的应用程序单一版本:只能将给定应用程序的一个版本部署到 VM。

  • 当前不支持移动操作:目前不支持将具有关联 VM 应用程序的虚拟机跨资源组进行移动。

注意

对于 Azure Compute Gallery 和 VM 应用程序,可以在复制后删除存储 SAS。 但是,任何后续的更新操作都需要有效的 SAS。

在 VM 中下载目录

应用程序包和配置文件的下载位置如下:

  • Linux:/var/lib/waagent/Microsoft.CPlat.Core.VMApplicationManagerLinux/<application name>/<application version>
  • Windows:C:\Packages\Plugins\Microsoft.CPlat.Core.VMApplicationManagerWindows\1.0.9\Downloads\<application name>\<application version>

假设应用程序包和配置文件位于当前目录中,则应写入安装/更新/删除命令。

文件命名

将应用程序文件下载到 VM 时,该文件将重命名为“MyVmApp”,并且没有文件扩展名(例如 .exe、.msi)。 VM 不知道文件的原始名称和扩展名。

这里有几个解决这个问题的替代方案:

可以修改脚本以包含用于在执行前重命名文件的命令:

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 应用程序进行更新。

将失败视为部署失败

无论安装/更新/删除任何 VM 应用是否失败,VM 应用程序扩展始终都会返回 成功 。 仅当扩展或底层基础架构出现问题时,VM 应用程序扩展才将扩展状态报告为失败。 此行为是由“将失败视为部署失败”标志触发的,该标志默认设置为 $false,并且可以更改为 $true。 失败标志可以在 PowerShellCLI 中配置。

在 Linux 上打包和安装 VM 应用程序

若要创建 VM 应用程序,需要应用程序包和脚本才能正确安装、更新和删除应用程序。
适用于 Linux 的第三方应用程序可以通过几种方式打包。 让我们探讨如何针对一些最常见情况创建安装命令。

.tar 和 .gz 文件

这些文件是压缩存档,可提取到所需位置。 如需将原始程序包提取到特定位置,请查看原始包的安装说明。 如果 .tar.gz 文件包含源代码,请参阅包的说明以了解如何从源位置安装。

在 Linux 计算机上安装 golang 的安装命令示例:

sudo tar -C /usr/local -xzf go_linux

删除命令示例:

sudo rm -rf /usr/local/go

使用 .deb.rpm 和其他平台特定的包为互联网访问受限的 VM 创建应用程序包

可以为特定于平台的包管理器下载单独的包,但这些包通常不一定包含所有依赖项。 对于这些文件,还必须在应用程序包中包括所有依赖项,或者让系统包管理器通过 VM 可用的存储库来下载依赖项。 如果使用的 VM 在 Internet 访问方面受到限制,则必须自己打包所有依赖项。

找出依赖项可能有点棘手。 有第三方工具可以显示整个依赖项树。

在 Ubuntu 中,你可以运行 sudo apt show <package_name> | grep Depends 显示执行 sudo apt-get install <packge_name> 命令时安装的所有包。 然后,可以使用该输出下载所有 .deb 文件,以创建可用作应用程序包的存档。

若要创建用于在 Ubuntu 上安装 PowerShell 的 VM 应用程序包,请执行以下步骤:

  1. 运行以下命令,使存储库能够下载 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
  1. 请检查输出的“依赖”行,它列出了以下包:
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.
  1. 使用 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
  1. 此 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),并要求用户通过用户界面进行选择。 如果安装程序支持静默模式参数,则应将此参数包含在安装字符串中。

cmd.exe 还要求可执行文件具有扩展名 .exe,因此你需要重命名该文件,加上 .exe 扩展名。

如果想要创建 myApp.exeVM 应用程序包(作为可执行文件提供),则 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 myapp /quiet /forcerestart /log myapp_uninstall.log

通常,start 命令将在批处理脚本中调用。 如果与参数一起使用 /wait ,调用脚本将暂停,直到调用进程终止。 完成后,批处理脚本将检查 errorlevel 命令设置的 start 变量,然后退出,如下所示:

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 实例,请检查 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

错误信息

消息 说明
当前 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},因为该操作已被标记为删除。 只能重试删除操作(或等待正在进行的操作完成)。 尝试更新当前正在删除的应用程序。
参数“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。
不支持将 {type} blob 类型用于 {operation} 操作。 仅支持页 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 等。 画廊应用程序版本必须遵循指定的格式。

后续步骤