Sharing Azure VM images across different subscriptions is indeed possible through Azure's Shared Image Gallery feature. This provides a scalable solution for distributing custom VM images within an organization or to external parties.
Here's how to properly share your VM image:
# First, create a generalized VM
az vm generalize --resource-group MyResourceGroup --name MyVM
# Create an image from the VM
az image create --resource-group MyResourceGroup --name MyImage --source MyVM
The most robust method is to use Azure Shared Image Gallery:
# Create a gallery
az sig create --resource-group MyResourceGroup --gallery-name MyGallery --location eastus
# Create image definition
az sig image-definition create \
--resource-group MyResourceGroup \
--gallery-name MyGallery \
--gallery-image-definition MyImageDefinition \
--publisher MyPublisher \
--offer MyOffer \
--sku MySKU \
--os-type Linux
# Create image version
az sig image-version create \
--resource-group MyResourceGroup \
--gallery-name MyGallery \
--gallery-image-definition MyImageDefinition \
--gallery-image-version 1.0.0 \
--target-regions "eastus" "westus" \
--replica-count 1 \
--managed-image "/subscriptions/<sub-id>/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/images/MyImage"
To share the gallery with another subscription:
# Get the gallery resource ID
galleryId=$(az sig show --resource-group MyResourceGroup --gallery-name MyGallery --query id -o tsv)
# Assign reader role to target subscription
az role assignment create \
--assignee "<target-subscription-id>" \
--role "Reader" \
--scope $galleryId
For simpler scenarios, you can also:
- Export the VHD to a storage account and share SAS tokens
- Publish to Azure Marketplace as a private offer
Remember these key points:
- Always generalize (sysprep) your VM before creating an image
- Shared Image Gallery provides version control and regional replication
- RBAC permissions must be carefully managed for security
Sharing Azure VM images across different subscriptions isn't as straightforward as one might hope. The Azure documentation focuses primarily on creating and using images within a single subscription, leaving many developers wondering about cross-subscription sharing.
There are several methods to accomplish this, each with its own advantages and limitations:
Method 1: Using Shared Image Gallery
The most robust solution is to use Azure's Shared Image Gallery feature. Here's how to implement it:
# Create a Shared Image Gallery
az sig create \
--resource-group myResourceGroup \
--gallery-name myGallery \
--location westus
# Create an image definition
az sig image-definition create \
--resource-group myResourceGroup \
--gallery-name myGallery \
--gallery-image-definition myImageDefinition \
--publisher myPublisher \
--offer myOffer \
--sku mySKU \
--os-type Linux \
--os-state generalized
# Create an image version
az sig image-version create \
--resource-group myResourceGroup \
--gallery-name myGallery \
--gallery-image-definition myImageDefinition \
--gallery-image-version 1.0.0 \
--target-regions "westus" "eastus" \
--replica-count 1 \
--managed-image "/subscriptions/<subscription-id>/resourceGroups/myResourceGroup/providers/Microsoft.Compute/images/myImage"
Method 2: Using Storage Account (Legacy Approach)
For those who can't use Shared Image Gallery, you can share via storage account:
# Create a SAS token for the VHD
az storage blob generate-sas \
--account-name mystorageaccount \
--container-name mycontainer \
--name myimage.vhd \
--permissions r \
--expiry 2023-12-31T00:00:00Z \
--https-only
When sharing images, proper RBAC configuration is crucial:
# Grant reader access to the Shared Image Gallery
az role assignment create \
--assignee "user@domain.com" \
--role "Reader" \
--scope "/subscriptions/<subscription-id>/resourceGroups/myResourceGroup/providers/Microsoft.Compute/galleries/myGallery"
- Always generalize your VM before creating an image
- Consider regional replication for better performance
- Implement proper versioning for your images
- Use Azure Policy to enforce image sharing standards
Some frequent problems and their solutions:
# Check image sharing status
az sig show \
--resource-group myResourceGroup \
--gallery-name myGallery
# Verify permissions
az role assignment list \
--assignee "user@domain.com" \
--scope "/subscriptions/<subscription-id>/resourceGroups/myResourceGroup/providers/Microsoft.Compute/galleries/myGallery"