The azure-native:compute:Snapshot resource, part of the Pulumi Azure Native provider, defines Azure managed disk snapshots: point-in-time copies of disks or VHD blobs that can be replicated across regions and subscriptions. This guide focuses on four capabilities: VHD blob import, snapshot-to-snapshot copying, cross-region replication with bandwidth controls, and Elastic SAN integration.
Snapshots reference source data that must exist before creation: VHD blobs in Azure Storage, existing snapshots, or Elastic SAN volume snapshots. The examples are intentionally small. Combine them with your own storage accounts, encryption settings, and network policies.
Import an unmanaged VHD blob into a snapshot
Teams migrating from unmanaged disks often capture VHD blobs stored in Azure Storage as managed snapshots for backup or replication.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const snapshot = new azure_native.compute.Snapshot("snapshot", {
creationData: {
createOption: azure_native.compute.DiskCreateOption.Import,
sourceUri: "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
},
location: "West US",
resourceGroupName: "myResourceGroup",
snapshotName: "mySnapshot1",
});
import pulumi
import pulumi_azure_native as azure_native
snapshot = azure_native.compute.Snapshot("snapshot",
creation_data={
"create_option": azure_native.compute.DiskCreateOption.IMPORT_,
"source_uri": "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
},
location="West US",
resource_group_name="myResourceGroup",
snapshot_name="mySnapshot1")
package main
import (
compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewSnapshot(ctx, "snapshot", &compute.SnapshotArgs{
CreationData: &compute.CreationDataArgs{
CreateOption: pulumi.String(compute.DiskCreateOptionImport),
SourceUri: pulumi.String("https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd"),
},
Location: pulumi.String("West US"),
ResourceGroupName: pulumi.String("myResourceGroup"),
SnapshotName: pulumi.String("mySnapshot1"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var snapshot = new AzureNative.Compute.Snapshot("snapshot", new()
{
CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
{
CreateOption = AzureNative.Compute.DiskCreateOption.Import,
SourceUri = "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
},
Location = "West US",
ResourceGroupName = "myResourceGroup",
SnapshotName = "mySnapshot1",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Snapshot;
import com.pulumi.azurenative.compute.SnapshotArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var snapshot = new Snapshot("snapshot", SnapshotArgs.builder()
.creationData(CreationDataArgs.builder()
.createOption("Import")
.sourceUri("https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd")
.build())
.location("West US")
.resourceGroupName("myResourceGroup")
.snapshotName("mySnapshot1")
.build());
}
}
resources:
snapshot:
type: azure-native:compute:Snapshot
properties:
creationData:
createOption: Import
sourceUri: https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd
location: West US
resourceGroupName: myResourceGroup
snapshotName: mySnapshot1
The creationData block controls how the snapshot is created. Setting createOption to Import tells Azure to read the VHD blob from the sourceUri and convert it into a managed snapshot. When the storage account is in the same subscription, you don’t need to specify storageAccountId.
Copy a snapshot within or across subscriptions
Disaster recovery and multi-region deployments require copying snapshots to different regions or subscriptions for redundancy.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const snapshot = new azure_native.compute.Snapshot("snapshot", {
creationData: {
createOption: azure_native.compute.DiskCreateOption.Copy,
sourceResourceId: "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
},
location: "West US",
resourceGroupName: "myResourceGroup",
snapshotName: "mySnapshot2",
});
import pulumi
import pulumi_azure_native as azure_native
snapshot = azure_native.compute.Snapshot("snapshot",
creation_data={
"create_option": azure_native.compute.DiskCreateOption.COPY,
"source_resource_id": "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
},
location="West US",
resource_group_name="myResourceGroup",
snapshot_name="mySnapshot2")
package main
import (
compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewSnapshot(ctx, "snapshot", &compute.SnapshotArgs{
CreationData: &compute.CreationDataArgs{
CreateOption: pulumi.String(compute.DiskCreateOptionCopy),
SourceResourceId: pulumi.String("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1"),
},
Location: pulumi.String("West US"),
ResourceGroupName: pulumi.String("myResourceGroup"),
SnapshotName: pulumi.String("mySnapshot2"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var snapshot = new AzureNative.Compute.Snapshot("snapshot", new()
{
CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
{
CreateOption = AzureNative.Compute.DiskCreateOption.Copy,
SourceResourceId = "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
},
Location = "West US",
ResourceGroupName = "myResourceGroup",
SnapshotName = "mySnapshot2",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Snapshot;
import com.pulumi.azurenative.compute.SnapshotArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var snapshot = new Snapshot("snapshot", SnapshotArgs.builder()
.creationData(CreationDataArgs.builder()
.createOption("Copy")
.sourceResourceId("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1")
.build())
.location("West US")
.resourceGroupName("myResourceGroup")
.snapshotName("mySnapshot2")
.build());
}
}
resources:
snapshot:
type: azure-native:compute:Snapshot
properties:
creationData:
createOption: Copy
sourceResourceId: subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1
location: West US
resourceGroupName: myResourceGroup
snapshotName: mySnapshot2
Setting createOption to Copy initiates a full snapshot replication. The sourceResourceId points to the snapshot you’re copying from, which can be in the same subscription or a different one. Azure handles the data transfer and creates an independent snapshot in the target region.
Copy a snapshot with enhanced bandwidth
Large snapshots can take hours to copy across regions. Enhanced bandwidth provisioning accelerates the copy operation for time-sensitive migrations.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const snapshot = new azure_native.compute.Snapshot("snapshot", {
creationData: {
createOption: azure_native.compute.DiskCreateOption.CopyStart,
provisionedBandwidthCopySpeed: azure_native.compute.ProvisionedBandwidthCopyOption.Enhanced,
sourceResourceId: "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
},
location: "West US",
resourceGroupName: "myResourceGroup",
snapshotName: "mySnapshot2",
});
import pulumi
import pulumi_azure_native as azure_native
snapshot = azure_native.compute.Snapshot("snapshot",
creation_data={
"create_option": azure_native.compute.DiskCreateOption.COPY_START,
"provisioned_bandwidth_copy_speed": azure_native.compute.ProvisionedBandwidthCopyOption.ENHANCED,
"source_resource_id": "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
},
location="West US",
resource_group_name="myResourceGroup",
snapshot_name="mySnapshot2")
package main
import (
compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewSnapshot(ctx, "snapshot", &compute.SnapshotArgs{
CreationData: &compute.CreationDataArgs{
CreateOption: pulumi.String(compute.DiskCreateOptionCopyStart),
ProvisionedBandwidthCopySpeed: pulumi.String(compute.ProvisionedBandwidthCopyOptionEnhanced),
SourceResourceId: pulumi.String("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1"),
},
Location: pulumi.String("West US"),
ResourceGroupName: pulumi.String("myResourceGroup"),
SnapshotName: pulumi.String("mySnapshot2"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var snapshot = new AzureNative.Compute.Snapshot("snapshot", new()
{
CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
{
CreateOption = AzureNative.Compute.DiskCreateOption.CopyStart,
ProvisionedBandwidthCopySpeed = AzureNative.Compute.ProvisionedBandwidthCopyOption.Enhanced,
SourceResourceId = "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
},
Location = "West US",
ResourceGroupName = "myResourceGroup",
SnapshotName = "mySnapshot2",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Snapshot;
import com.pulumi.azurenative.compute.SnapshotArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var snapshot = new Snapshot("snapshot", SnapshotArgs.builder()
.creationData(CreationDataArgs.builder()
.createOption("CopyStart")
.provisionedBandwidthCopySpeed("Enhanced")
.sourceResourceId("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1")
.build())
.location("West US")
.resourceGroupName("myResourceGroup")
.snapshotName("mySnapshot2")
.build());
}
}
resources:
snapshot:
type: azure-native:compute:Snapshot
properties:
creationData:
createOption: CopyStart
provisionedBandwidthCopySpeed: Enhanced
sourceResourceId: subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1
location: West US
resourceGroupName: myResourceGroup
snapshotName: mySnapshot2
The CopyStart option works like Copy but allows you to specify provisionedBandwidthCopySpeed. Setting it to Enhanced allocates additional network bandwidth to speed up the transfer. This is useful for large snapshots where standard copy speeds would cause unacceptable delays.
Create a snapshot from Elastic SAN storage
Elastic SAN provides high-performance block storage for Azure workloads. Teams can capture Elastic SAN volume snapshots as managed disk snapshots for portability.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const snapshot = new azure_native.compute.Snapshot("snapshot", {
creationData: {
createOption: azure_native.compute.DiskCreateOption.CopyFromSanSnapshot,
elasticSanResourceId: "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot",
},
location: "West US",
resourceGroupName: "myResourceGroup",
snapshotName: "mySnapshot",
});
import pulumi
import pulumi_azure_native as azure_native
snapshot = azure_native.compute.Snapshot("snapshot",
creation_data={
"create_option": azure_native.compute.DiskCreateOption.COPY_FROM_SAN_SNAPSHOT,
"elastic_san_resource_id": "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot",
},
location="West US",
resource_group_name="myResourceGroup",
snapshot_name="mySnapshot")
package main
import (
compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewSnapshot(ctx, "snapshot", &compute.SnapshotArgs{
CreationData: &compute.CreationDataArgs{
CreateOption: pulumi.String(compute.DiskCreateOptionCopyFromSanSnapshot),
ElasticSanResourceId: pulumi.String("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot"),
},
Location: pulumi.String("West US"),
ResourceGroupName: pulumi.String("myResourceGroup"),
SnapshotName: pulumi.String("mySnapshot"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var snapshot = new AzureNative.Compute.Snapshot("snapshot", new()
{
CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
{
CreateOption = AzureNative.Compute.DiskCreateOption.CopyFromSanSnapshot,
ElasticSanResourceId = "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot",
},
Location = "West US",
ResourceGroupName = "myResourceGroup",
SnapshotName = "mySnapshot",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Snapshot;
import com.pulumi.azurenative.compute.SnapshotArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var snapshot = new Snapshot("snapshot", SnapshotArgs.builder()
.creationData(CreationDataArgs.builder()
.createOption("CopyFromSanSnapshot")
.elasticSanResourceId("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot")
.build())
.location("West US")
.resourceGroupName("myResourceGroup")
.snapshotName("mySnapshot")
.build());
}
}
resources:
snapshot:
type: azure-native:compute:Snapshot
properties:
creationData:
createOption: CopyFromSanSnapshot
elasticSanResourceId: subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot
location: West US
resourceGroupName: myResourceGroup
snapshotName: mySnapshot
The CopyFromSanSnapshot option converts an Elastic SAN volume snapshot into a managed disk snapshot. The elasticSanResourceId points to the Elastic SAN snapshot resource. This enables you to move data from Elastic SAN into the managed disk ecosystem for broader compatibility.
Beyond these examples
These snippets focus on specific snapshot-level features: VHD blob import and snapshot-to-snapshot copying, cross-region replication with bandwidth controls, and Elastic SAN integration. They’re intentionally minimal rather than full backup solutions.
The examples reference pre-existing infrastructure such as Azure Storage accounts with VHD blobs, and source snapshots or Elastic SAN volume snapshots. They focus on configuring the snapshot rather than provisioning everything around it.
To keep things focused, common snapshot patterns are omitted, including:
- Incremental snapshots (incremental property)
- Encryption with customer-managed keys (encryption, encryptionSettingsCollection)
- Network access policies and private endpoints (networkAccessPolicy, diskAccessId)
- SKU selection for storage tier (sku property)
These omissions are intentional: the goal is to illustrate how each snapshot feature is wired, not provide drop-in backup modules. See the Snapshot resource reference for all available configuration options.
Let's create Azure Disk Snapshots
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Snapshot Creation & Sources
You can create snapshots using four createOption values:
- Import - From an unmanaged blob using
sourceUri - Copy - From an existing snapshot in the same or different subscription
- CopyStart - Cross-region copy from an existing snapshot
- CopyFromSanSnapshot - From an Elastic SAN volume snapshot using
elasticSanResourceId
createOption to Import and provide sourceUri pointing to the blob. If the blob is in a different subscription, you must also include storageAccountId in creationData.createOption set to CopyStart with sourceResourceId pointing to the source snapshot. For faster copy speeds, set provisionedBandwidthCopySpeed to Enhanced.createOption to CopyFromSanSnapshot and provide elasticSanResourceId pointing to the Elastic SAN volume snapshot resource.Immutability & Limitations
creationData, location, snapshotName, and extendedLocation. Changing any of these requires recreating the snapshot.diskSizeGB only if the disk is not attached to a running VM. Decreasing the size is not allowed.Performance & Optimization
createOption set to CopyStart, set provisionedBandwidthCopySpeed to Enhanced for quicker copy operations.Storage & SKU
Standard_LRS, Premium_LRS, and Standard_ZRS. For incremental snapshots, the SKU defaults to match the previous snapshot if not specified.completionPercent output property to monitor the percentage complete for snapshots created via CopyStart. Check copyCompletionError for any error details if the operation fails.