VM Applications overview

VM Applications are a resource type in Azure Compute Gallery (formerly known as Shared Image Gallery) that simplifies management, sharing, and global distribution of applications for your virtual machines.

While you can create an image of a VM with apps preinstalled, you would need to update your image each time you have application changes. Separating your application installation from your VM images means there’s no need to publish a new image for every line of code change.

Application packages provide benefits over other deployment and packaging methods:

  • VM Applications have support for Azure Policies

  • Grouping and versioning of your packages

  • VM applications can be globally replicated to be closer to your infrastructure, so you don’t need to use AzCopy or other storage copy mechanisms to copy the bits across Azure regions.

  • Sharing with other users through Azure Role Based Access Control (RBAC)

  • Support for virtual machines, and both flexible and uniform scale sets

  • If you have Network Security Group (NSG) rules applied on your VM or scale set, downloading the packages from an internet repository might not be possible. And with storage accounts, downloading packages onto locked-down VMs would require setting up private links.

  • Support for Block Blobs: This feature allows the handling of large files efficiently by breaking them into smaller, manageable blocks. Ideal for uploading large amounts of data, streaming, and background uploading.

What are VM app packages?

The VM application packages use multiple resource types:

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. 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.

Limitations

  • No more than 3 replicas per region: When you're creating a VM Application version, the maximum number of replicas per region is three.

  • Storage with public access or SAS URI with read privilege: The storage account needs to has public level access or use an SAS URI with read privilege, as other restriction levels fail deployments.

  • Retrying failed installations: Currently, the only way to retry a failed installation is to remove the application from the profile, then add it back.

  • Only 25 applications per VM: No more than 25 applications may be deployed to a VM at any point.

  • 2GB application size: The maximum file size of an application version is 2 GB.

  • No guarantees on reboots in your script: If your script requires a reboot, the recommendation is to place that application last during deployment. While the code attempts to handle reboots, it may fail.

  • Requires a VM Agent: The VM agent must exist on the VM and be able to receive goal states.

  • Multiple versions of same application on the same VM: You can't have multiple versions of the same application on a VM.

  • Move operations currently not supported: Moving VMs with VM Apps to other resource groups aren't supported at this time.

Note

For Azure Compute Gallery and VM Applications, Storage SAS can be deleted after replication. However, any subsequent update operation will require a valid SAS.

Cost

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.

VM applications

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

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 for installing the application
  • Remove string to show how to properly remove the app
  • Package file name to use when it's downloaded to the VM
  • Configuration file name to be used to configure the app on the VM
  • A link to the configuration file for the VM application, which you can include license files
  • Update string for how to update the VM application to a newer version
  • 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

Download directory

The download location of the application package and the configuration files are:

  • 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>

The install/update/remove commands should be written assuming the application package and the configuration file are in the current directory.

File naming

When the application file gets downloaded to the VM, it's renamed as "MyVmApp" (no extension). This is because the VM isn't aware of your package's original name or extension. It utilizes the only name it has, which is the application name itself - "MyVmApp".

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" will make your install script only need to be:

MyAppe.exe /S

Tip

If your blob was originally named "myApp.exe" instead of "myapp", then the above script would have worked without setting the packageFileName property.

Command interpreter

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>'

How updates are handled

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.

Tips for creating VM Applications on Linux

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.

.tar and .gz files

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.

In Ubuntu, you can run sudo apt show <package_name> | grep Depends to show all the packages that are installed when executing the sudo apt-get install <packge_name> command. Then you can use that output to download all .deb files to create an archive that can be used as the application package.

  1. Example, to create a VM application package to install PowerShell for Ubuntu, first run the following commands to enable the repository where PowerShell can be downloaded from and also to identify the package dependencies on a new 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. Check the output of the line Depends which lists the following packages:
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. Download each of these files using sudo apt-get download <package_name> and create a tar compressed archive with all files.
  • 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. This tar archive is the application package file.
  • The install command in this case is:
sudo tar -xvzf powershell.tar.gz && sudo dpkg -i *.deb
  • And the remove command is:
sudo apt remove powershell

Use sudo apt autoremove instead of explicitly trying to remove all the dependencies. You may have installed other applications with overlapping dependencies, and in that case, an explicit remove command would fail.

In case you don't want to resolve the dependencies yourself, and apt is able to connect to the repositories, you can install an application with just one .deb file and let apt handle the dependencies.

Example install command:

dpkg -i <package_name> || apt --fix-broken install -y

Tips for creating VM Applications on Windows

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.

.exe installer

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'

.msi installer

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 $appname /quiet /forcerestart /log ${appname}_uninstall.log

Typically, the start command would be called within a batch script. If used with the /wait parameter, the calling script will be 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%
...

Zipped files

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

Treat failure as deployment failure

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.

Troubleshooting VM Applications

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

Error messages

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.

Next steps