Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
VM Applications are a resource type in Azure Compute Gallery that provides a modern, flexible approach to managing and deploying applications across your virtual machines and scale sets. By decoupling application installation from your base VM images, you can streamline updates, reduce image maintenance overhead, and accelerate deployment cycles. This approach eliminates the need to rebuild and republish VM images for every application change, enabling faster iteration and greater operational agility. VM Applications are best suited for deploying high scale, AI, low latency, and secure workloads on Azure.
Resource | Description |
---|---|
Azure Compute Gallery | A gallery is a repository for managing and sharing application packages. Users can share the gallery resource and all the child resources are shared automatically. The gallery name must be unique per subscription. For example, you may have one gallery to store all your OS images and another gallery to store all your VM applications. |
VM Application | The definition of your VM application. It's a logical resource that stores the common metadata for all the versions under it. For example, you may have an application definition for Apache Tomcat and have multiple versions within it. |
VM Application version | The deployable resource which holds your application package and version specific configurations. You can globally replicate your VM application versions to target regions closer to your VM infrastructure. The VM Application version must be replicated to a region before it may be deployed on a VM in that region. |
- Centralized and Flexible Application Management:
- Package Once, Deploy Anywhere: Package applications in ZIP, MSI (Microsoft Package Installed), or EXE formats and manage them centrally in Azure Compute Gallery.
- Version Control: Deploy either the latest or a specific version by maintaining multiple versions of each application.
- Seamless Sharing and Access Control
- Tenant-Wide Sharing: Share applications within teams or across your entire organization (tenant).
- Integrated RBAC: Control publishing and deployment access using Azure Role-Based Access Control (RBAC).
- Reliable and Customizable Deployments
- Individual Application Control: Install, update, or delete applications independently—no need to rebuild VM images.
- Customizable Operations: Define how to install, update, and delete operations for applications, including reboot handling.
- Built-In Failure Handling: Ensure resilient deployments by connecting VM application failure to VM failure.
- Scalable and Low-Latency Distribution
- Global and Intra-Region Replication: Automatically replicate applications across and within regions to reduce latency and improve resiliency—no need for AzCopy or manual transfers.
- Optimized for High-Scale Scenarios: Achieve low create latency even during large-scale deployments.
- Secure and Compliant by Design
- Policy-Driven Enforcement: Use Azure Policy to enforce application presence and configuration across your fleet.
- Secure Deployments: Avoid internet-based downloads and complex private link setups which aren't ideal for locked-down or secure environments.
- Broad Platform Support
- VMs and Scale Sets: Deploy to individual VMs, flexible scale sets, or uniform scale sets with full support.
- Block Blob Support: Efficiently handle large application packages (upto 2 GB) using Azure Block Blobs for chunked uploads and background streaming.
The VM application resource defines the following about your VM application:
- Azure Compute Gallery where the VM application is stored
- Name of the application
- Supported OS type like Linux or Windows
- A description of the VM application
VM application versions are the deployable resource. Versions are defined with the following properties:
- Version number
- Link to the application package file in a storage account
- Install string to properly install the application
- Remove string to properly remove the application
- Update string to properly update the VM application to a newer version
- Package file name to use when the package is downloaded to the VM.
- Configuration file name to be used to configure the application on the VM
- A link to the configuration file for the VM application, which you can include license files
- End-of-life date. End-of-life dates are informational; you're still able to deploy VM Application versions past the end-of-life date.
- Exclude from latest. You can keep a version from being used as the latest version of the application.
- Target regions for replication
- Replica count per region
{
"$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 (e.g., 1.0.0)"
}
},
"location": {
"type": "string",
"defaultValue": "China North"
},
"supportedOSType": {
"type": "string",
"allowedValues": ["Windows", "Linux"]
},
"endOfLifeDate": {
"type": "string"
},
"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. E.g. echo 'Installing application...'"
}
},
"updateScript": {
"type": "string",
"metadata": {
"description": "Optional. Script to run to update the application. E.g. echo 'Updating application...'"
}
},
"removeScript": {
"type": "string",
"metadata": {
"description": "Optional. Script to run to delete the application. E.g. 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')]"
}
}
]
}
There's no extra charge for using VM Application Packages, but you're charged for the following resources:
- Storage costs of storing each package and any replicas.
- Network egress charges for replication of the first image version from the source region to the replicated regions. Subsequent replicas are handled within the region, so there are no extra charges.
For more information on network egress, see Bandwidth pricing.
Up to 10 replicas per region: When you're creating a VM Application version, the maximum number of replicas per region is 10 for both page blob and block blob.
Storage with public access and SAS URI with read privilege: The storage account needs to have public level access and use a SAS URI with read privilege, as other restriction levels fail deployments. SAS Tokens can be bypassed by publishing the artifact on the storage account by allowing anonymous access.
Manual retry for failed installations: Currently, the only way to retry a failed installation is to remove the application from the profile, then add it back.
Up to 25 applications per VM: A maximum of 25 applications can be deployed to a single virtual machine.
2 GB application size: The maximum file size of an application version
mediaLink
is 2 GB. The maximum file size fordefaultConfigurationLink
is 1 GB.Requires a VM Agent: The VM agent must exist on the VM and be able to receive goal states.
Single version of the application per VM: Only one version of a given application can be deployed to a VM.
Move operations currently not supported: Moving VMs with associated VM Applications across resource groups is currently not supported.
Note
For Azure Compute Gallery and VM Applications, Storage SAS can be deleted after replication. However, any subsequent update operation requires a valid SAS.
The download location of the application package and the configuration files are:
- 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>
The install/update/remove commands should be written assuming the application package and the configuration file are in the current directory.
When the application file gets downloaded to the VM, the file is renamed as "MyVmApp" and has no file extension (E.g. .exe, .msi). The VM is unaware of the file's original name and extension .
Here are a few alternatives to navigate this issue:
You can modify your script to include a command for renaming the file before execution:
move .\\MyVmApp .\\MyApp.exe & MyApp.exe /S
You can also use the packageFileName
(and the corresponding configFileName
) property to instruct us what to rename your file. For example, setting it to "MyApp.exe" makes your install script as follows.
MyAppe.exe /S
Tip
If your blob is originally named as "myApp.exe" instead of "myapp", then the script works without setting the packageFileName
property.
The default command interpreters are:
- Linux:
/bin/bash
- Windows:
cmd.exe
It's possible to use a different interpreter like Chocolatey or PowerShell, as long as it's installed on the machine, by calling the executable and passing the command to it. For example, to have your command run in PowerShell on Windows instead of cmd, you can pass powershell.exe -Command '<powershell commmand>'
When you update an application version on a VM or Virtual Machine Scale Sets, the update command you provided during deployment is used. If the updated version doesn't have an update command, then the current version is removed and the new version is installed.
Update commands should be written with the expectation that it could be updating from any older version of the VM Application.
The VM Application extension always returns a success regardless of whether any VM app failed while being installed/updated/removed. The VM Application extension only reports the extension status as failure when there's a problem with the extension or the underlying infrastructure. This behavior is triggered by the "treat failure as deployment failure" flag, which is set to $false
by default and can be changed to $true
. The failure flag can be configured in PowerShell or CLI.
To create a VM Application, you need application package and scripts to properly install, update, and delete the application.
Third party applications for Linux can be packaged in a few ways. Let's explore how to handle creating the install commands for some of the most common.
These files are compressed archives and can be extracted to a desired location. Check the installation instructions for the original package to in case they need to be extracted to a specific location. If .tar.gz file contains source code, see the instructions for the package for how to install from source.
Example to install command to install golang
on a Linux machine:
sudo tar -C /usr/local -xzf go_linux
Example remove command:
sudo rm -rf /usr/local/go
Creating application packages using .deb
, .rpm
, and other platform specific packages for VMs with restricted internet access
You can download individual packages for platform specific package managers, but they usually don't contain all the dependencies. For these files, you must also include all dependencies in the application package, or have the system package manager download the dependencies through the repositories that are available to the VM. If you're working with a VM with restricted internet access, you must package all the dependencies yourself.
Figuring out the dependencies can be a bit tricky. There are third party tools that can show you the entire dependency tree.
Most third party applications in Windows are available as .exe or .msi installers. Some are also available as extract and run zip files. Let us look at the best practices for each of them.
Installer executables typically launch a user interface (UI) and require someone to select through the UI. If the installer supports a silent mode parameter, it should be included in your installation string.
Cmd.exe also expects executable files to have the extension .exe
, so you need to rename the file to have the .exe
extension.
If I want to create a VM Application package for myApp.exe
, which ships as an executable, my VM Application is called 'myApp', so I write the command assuming the application package is in the current directory:
"move .\\myApp .\\myApp.exe & myApp.exe /S -config myApp_config"
If the installer executable file doesn't support an uninstall parameter, you can sometimes look up the registry on a test machine to know where the uninstaller is located.
In the registry, the uninstall string is stored in Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\<installed application name>\UninstallString
so I would use the contents as my remove command:
'\"C:\\Program Files\\myApp\\uninstall\\helper.exe\" /S'
For command line execution of .msi
installers, the commands to install or remove an application should use msiexec
. Typically, msiexec
runs as its own separate process and cmd
doesn't wait for it to complete, which can lead to problems when installing more than one VM application. The start
command can be used with msiexec
to ensure that the installation completes before the command returns. For example:
start /wait %windir%\\system32\\msiexec.exe /i myapp /quiet /forcerestart /log myapp_install.log
Example remove command:
start /wait %windir%\\system32\\msiexec.exe /x myapp /quiet /forcerestart /log myapp_uninstall.log
Typically, the start
command would be called within a batch script. If used with the /wait
parameter, the calling script is paused until the called process terminates. Once complete, the batch script would check for the errorlevel
variable set by the start
command and exit as follows:
start /wait %windir%\\system32\\msiexec.exe /i myapp /quiet /forcerestart /log myapp_install.log
if %errorlevel% neq 0 exit /b %errorlevel%
...
For .zip or other zipped files, rename and unzip the contents of the application package to the desired destination.
Example install command:
rename myapp myapp.zip && mkdir C:\myapp && powershell.exe -Command "Expand-Archive -path myapp.zip -destinationpath C:\myapp"
Example remove command:
rmdir /S /Q C:\\myapp
To know whether a particular VM Application was successfully added to the VM instance, check the message of the VM Application extension.
To learn more about getting the status of VM extensions, see Virtual machine extensions and features for Linux and Virtual machine extensions and features for Windows.
To get status of VM extensions, use Get-AzVM:
Get-AzVM -name <VM name> -ResourceGroupName <resource group name> -Status | convertto-json -Depth 10
To get status of scale set extensions, use 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
Message | Description |
---|---|
Current VM Application Version {name} was deprecated at {date}. | You tried to deploy a VM Application version that has already been deprecated. Try using latest instead of specifying a specific version. |
Current VM Application Version {name} supports OS {OS}, while current OSDisk's OS is {OS}. | You tried to deploy a Linux application to Windows instance or vice versa. |
The maximum number of VM applications (max=5, current={count}) has been exceeded. Use fewer applications and retry the request. | We currently only support five VM applications per VM or scale set. |
More than one VM Application was specified with the same packageReferenceId. | The same application was specified more than once. |
Subscription not authorized to access this image. | The subscription doesn't have access to this application version. |
Storage account in the arguments doesn't exist. | There are no applications for this subscription. |
The platform image {image} isn't available. Verify that all fields in the storage profile are correct. For more details about storage profile information, see https://aka.ms/storageprofile. | The application doesn't exist. |
The gallery image {image} isn't available in {region} region. Contact image owner to replicate to this region, or change your requested region. | The gallery application version exists, but it wasn't replicated to this region. |
The SAS isn't valid for source uri {uri}. | A Forbidden error was received from storage when attempting to retrieve information about the url (either mediaLink or defaultConfigurationLink). |
The blob referenced by source uri {uri} doesn't exist. | The blob provided for the mediaLink or defaultConfigurationLink properties doesn't exist. |
The gallery application version url {url} can't be accessed due to the following error: remote name not found. Ensure that the blob exists and that it's either publicly accessible or is a SAS url with read privileges. | The most likely case is that a SAS uri with read privileges wasn't provided. |
The gallery application version url {url} can't be accessed due to the following error: {error description}. Ensure that the blob exists and that it's either publicly accessible or is a SAS url with read privileges. | There was an issue with the storage blob provided. The error description provides more information. |
Operation {operationName} isn't allowed on {application} since it's marked for deletion. You can only retry the delete operation (or wait for an ongoing one to complete). | Attempt to update an application that's currently being deleted. |
The value {value} of parameter 'galleryApplicationVersion.properties.publishingProfile.replicaCount' is out of range. The value must be between one and three, inclusive. | Only between one and three replicas are allowed for VM Application versions. |
Changing property 'galleryApplicationVersion.properties.publishingProfile.manageActions.install' isn't allowed. (Or update, delete) | It isn't possible to change any of the manage actions on an existing VmApplication. A new VmApplication version must be created. |
Changing property ' galleryApplicationVersion.properties.publishingProfile.settings.packageFileName ' isn't allowed. (Or configFileName) | It isn't possible to change any of the settings, such as the package file name or config file name. A new VmApplication version must be created. |
The blob referenced by source uri {uri} is too large: size = {size}. The maximum blob size allowed is '1 GB'. | The maximum size for a blob referred to by mediaLink or defaultConfigurationLink is currently 1 GB. |
The blob referenced by source uri {uri} is empty. | An empty blob was referenced. |
{type} blob type isn't supported for {operation} operation. Only page blobs and block blobs are supported. | VmApplications only supports page blobs and block blobs. |
The SAS isn't valid for source uri {uri}. | The SAS uri supplied for mediaLink or defaultConfigurationLink isn't a valid SAS uri. |
Can't specify {region} in target regions because the subscription is missing required feature {featureName}. Either register your subscription with the required feature or remove the region from the target region list. | To use VmApplications in certain restricted regions, one must have the feature flag registered for that subscription. |
Gallery image version publishing profile regions {regions} must contain the location of image version {location}. | The list of regions for replication must contain the location where the application version is. |
Duplicate regions aren't allowed in target publishing regions. | The publishing regions may not have duplicates. |
Gallery application version resources currently don't support encryption. | The encryption property for target regions isn't supported for VM Applications |
Entity name doesn't match the name in the request URL. | The gallery application version specified in the request url doesn't match the one specified in the request body. |
The gallery application version name is invalid. The application version name should follow Major(int32). Minor(int32). Patch(int32) format, where int is between 0 and 2,147,483,647 (inclusive). For example, 1.0.0, 2018.12.1 etc. |
The gallery application version must follow the format specified. |
- Learn how to create and deploy VM application packages.