Create and Manage Azure Managed Disks

The azure-native:compute:Disk resource, part of the Pulumi Azure Native provider, provisions Azure managed disks: their size, storage tier, encryption, and source data. This guide focuses on three capabilities: creating empty disks and disks from snapshots or images, configuring encryption and network access policies, and selecting storage SKUs and zone redundancy.

Disks reference snapshots, images, encryption sets, and disk access resources that must exist separately. The examples are intentionally small. Combine them with your own VM attachments, backup policies, and access controls.

Create an empty disk for data storage

Most deployments start by provisioning an empty disk for VM data storage or application workloads.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const disk = new azure_native.compute.Disk("disk", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.Empty,
    },
    diskName: "myDisk",
    diskSizeGB: 200,
    location: "West US",
    resourceGroupName: "myResourceGroup",
});
import pulumi
import pulumi_azure_native as azure_native

disk = azure_native.compute.Disk("disk",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.EMPTY,
    },
    disk_name="myDisk",
    disk_size_gb=200,
    location="West US",
    resource_group_name="myResourceGroup")
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.NewDisk(ctx, "disk", &compute.DiskArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption: pulumi.String(compute.DiskCreateOptionEmpty),
			},
			DiskName:          pulumi.String("myDisk"),
			DiskSizeGB:        pulumi.Int(200),
			Location:          pulumi.String("West US"),
			ResourceGroupName: pulumi.String("myResourceGroup"),
		})
		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 disk = new AzureNative.Compute.Disk("disk", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.Empty,
        },
        DiskName = "myDisk",
        DiskSizeGB = 200,
        Location = "West US",
        ResourceGroupName = "myResourceGroup",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Disk;
import com.pulumi.azurenative.compute.DiskArgs;
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 disk = new Disk("disk", DiskArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("Empty")
                .build())
            .diskName("myDisk")
            .diskSizeGB(200)
            .location("West US")
            .resourceGroupName("myResourceGroup")
            .build());

    }
}
resources:
  disk:
    type: azure-native:compute:Disk
    properties:
      creationData:
        createOption: Empty
      diskName: myDisk
      diskSizeGB: 200
      location: West US
      resourceGroupName: myResourceGroup

The creationData property specifies how the disk is created. Setting createOption to Empty provisions a blank disk. The diskSizeGB property sets the initial capacity. Azure places the disk in the specified location and assigns it a default storage tier based on the SKU.

Copy a disk from an existing snapshot

Teams create disks from snapshots to restore data, clone environments, or provision new VMs with pre-configured state.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const disk = new azure_native.compute.Disk("disk", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.Copy,
        sourceResourceId: "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot",
    },
    diskName: "myDisk",
    location: "West US",
    resourceGroupName: "myResourceGroup",
});
import pulumi
import pulumi_azure_native as azure_native

disk = azure_native.compute.Disk("disk",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.COPY,
        "source_resource_id": "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot",
    },
    disk_name="myDisk",
    location="West US",
    resource_group_name="myResourceGroup")
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.NewDisk(ctx, "disk", &compute.DiskArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption:     pulumi.String(compute.DiskCreateOptionCopy),
				SourceResourceId: pulumi.String("subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot"),
			},
			DiskName:          pulumi.String("myDisk"),
			Location:          pulumi.String("West US"),
			ResourceGroupName: pulumi.String("myResourceGroup"),
		})
		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 disk = new AzureNative.Compute.Disk("disk", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.Copy,
            SourceResourceId = "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot",
        },
        DiskName = "myDisk",
        Location = "West US",
        ResourceGroupName = "myResourceGroup",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Disk;
import com.pulumi.azurenative.compute.DiskArgs;
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 disk = new Disk("disk", DiskArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("Copy")
                .sourceResourceId("subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot")
                .build())
            .diskName("myDisk")
            .location("West US")
            .resourceGroupName("myResourceGroup")
            .build());

    }
}
resources:
  disk:
    type: azure-native:compute:Disk
    properties:
      creationData:
        createOption: Copy
        sourceResourceId: subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot
      diskName: myDisk
      location: West US
      resourceGroupName: myResourceGroup

When createOption is Copy, the sourceResourceId points to an existing snapshot. Azure replicates the snapshot’s data into the new disk. The disk inherits the snapshot’s size unless you specify a larger diskSizeGB.

Create a disk from a platform VM image

OS disks are typically created from Azure Marketplace images or custom platform images, providing a bootable disk for VM deployment.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const disk = new azure_native.compute.Disk("disk", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.FromImage,
        imageReference: {
            id: "/Subscriptions/{subscriptionId}/Providers/Microsoft.Compute/Locations/westus/Publishers/{publisher}/ArtifactTypes/VMImage/Offers/{offer}/Skus/{sku}/Versions/1.0.0",
        },
    },
    diskName: "myDisk",
    location: "West US",
    osType: azure_native.compute.OperatingSystemTypes.Windows,
    resourceGroupName: "myResourceGroup",
});
import pulumi
import pulumi_azure_native as azure_native

disk = azure_native.compute.Disk("disk",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.FROM_IMAGE,
        "image_reference": {
            "id": "/Subscriptions/{subscriptionId}/Providers/Microsoft.Compute/Locations/westus/Publishers/{publisher}/ArtifactTypes/VMImage/Offers/{offer}/Skus/{sku}/Versions/1.0.0",
        },
    },
    disk_name="myDisk",
    location="West US",
    os_type=azure_native.compute.OperatingSystemTypes.WINDOWS,
    resource_group_name="myResourceGroup")
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.NewDisk(ctx, "disk", &compute.DiskArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption: pulumi.String(compute.DiskCreateOptionFromImage),
				ImageReference: &compute.ImageDiskReferenceArgs{
					Id: pulumi.String("/Subscriptions/{subscriptionId}/Providers/Microsoft.Compute/Locations/westus/Publishers/{publisher}/ArtifactTypes/VMImage/Offers/{offer}/Skus/{sku}/Versions/1.0.0"),
				},
			},
			DiskName:          pulumi.String("myDisk"),
			Location:          pulumi.String("West US"),
			OsType:            compute.OperatingSystemTypesWindows,
			ResourceGroupName: pulumi.String("myResourceGroup"),
		})
		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 disk = new AzureNative.Compute.Disk("disk", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.FromImage,
            ImageReference = new AzureNative.Compute.Inputs.ImageDiskReferenceArgs
            {
                Id = "/Subscriptions/{subscriptionId}/Providers/Microsoft.Compute/Locations/westus/Publishers/{publisher}/ArtifactTypes/VMImage/Offers/{offer}/Skus/{sku}/Versions/1.0.0",
            },
        },
        DiskName = "myDisk",
        Location = "West US",
        OsType = AzureNative.Compute.OperatingSystemTypes.Windows,
        ResourceGroupName = "myResourceGroup",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Disk;
import com.pulumi.azurenative.compute.DiskArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import com.pulumi.azurenative.compute.inputs.ImageDiskReferenceArgs;
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 disk = new Disk("disk", DiskArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("FromImage")
                .imageReference(ImageDiskReferenceArgs.builder()
                    .id("/Subscriptions/{subscriptionId}/Providers/Microsoft.Compute/Locations/westus/Publishers/{publisher}/ArtifactTypes/VMImage/Offers/{offer}/Skus/{sku}/Versions/1.0.0")
                    .build())
                .build())
            .diskName("myDisk")
            .location("West US")
            .osType("Windows")
            .resourceGroupName("myResourceGroup")
            .build());

    }
}
resources:
  disk:
    type: azure-native:compute:Disk
    properties:
      creationData:
        createOption: FromImage
        imageReference:
          id: /Subscriptions/{subscriptionId}/Providers/Microsoft.Compute/Locations/westus/Publishers/{publisher}/ArtifactTypes/VMImage/Offers/{offer}/Skus/{sku}/Versions/1.0.0
      diskName: myDisk
      location: West US
      osType: Windows
      resourceGroupName: myResourceGroup

Setting createOption to FromImage and providing an imageReference creates a disk from a published VM image. The osType property identifies whether the disk contains Windows or Linux. The disk size matches the image unless you specify a larger value.

Encrypt a disk with customer-managed keys

Organizations with compliance requirements encrypt disks using their own keys managed through Azure Key Vault.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const disk = new azure_native.compute.Disk("disk", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.Empty,
    },
    diskName: "myDisk",
    diskSizeGB: 200,
    encryption: {
        diskEncryptionSetId: "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}",
    },
    location: "West US",
    resourceGroupName: "myResourceGroup",
});
import pulumi
import pulumi_azure_native as azure_native

disk = azure_native.compute.Disk("disk",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.EMPTY,
    },
    disk_name="myDisk",
    disk_size_gb=200,
    encryption={
        "disk_encryption_set_id": "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}",
    },
    location="West US",
    resource_group_name="myResourceGroup")
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.NewDisk(ctx, "disk", &compute.DiskArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption: pulumi.String(compute.DiskCreateOptionEmpty),
			},
			DiskName:   pulumi.String("myDisk"),
			DiskSizeGB: pulumi.Int(200),
			Encryption: &compute.EncryptionArgs{
				DiskEncryptionSetId: pulumi.String("/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}"),
			},
			Location:          pulumi.String("West US"),
			ResourceGroupName: pulumi.String("myResourceGroup"),
		})
		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 disk = new AzureNative.Compute.Disk("disk", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.Empty,
        },
        DiskName = "myDisk",
        DiskSizeGB = 200,
        Encryption = new AzureNative.Compute.Inputs.EncryptionArgs
        {
            DiskEncryptionSetId = "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}",
        },
        Location = "West US",
        ResourceGroupName = "myResourceGroup",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Disk;
import com.pulumi.azurenative.compute.DiskArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import com.pulumi.azurenative.compute.inputs.EncryptionArgs;
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 disk = new Disk("disk", DiskArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("Empty")
                .build())
            .diskName("myDisk")
            .diskSizeGB(200)
            .encryption(EncryptionArgs.builder()
                .diskEncryptionSetId("/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}")
                .build())
            .location("West US")
            .resourceGroupName("myResourceGroup")
            .build());

    }
}
resources:
  disk:
    type: azure-native:compute:Disk
    properties:
      creationData:
        createOption: Empty
      diskName: myDisk
      diskSizeGB: 200
      encryption:
        diskEncryptionSetId: /subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}
      location: West US
      resourceGroupName: myResourceGroup

The encryption property controls data-at-rest encryption. Setting diskEncryptionSetId points to a disk encryption set that wraps your Key Vault key. Azure encrypts all disk data with your key instead of platform-managed keys.

Configure zone-redundant storage for high availability

Production workloads that require protection against datacenter failures use zone-redundant storage to replicate data across availability zones.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const disk = new azure_native.compute.Disk("disk", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.Empty,
    },
    diskName: "myDisk",
    diskSizeGB: 200,
    location: "West US",
    resourceGroupName: "myResourceGroup",
    sku: {
        name: azure_native.compute.DiskStorageAccountTypes.Premium_ZRS,
    },
});
import pulumi
import pulumi_azure_native as azure_native

disk = azure_native.compute.Disk("disk",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.EMPTY,
    },
    disk_name="myDisk",
    disk_size_gb=200,
    location="West US",
    resource_group_name="myResourceGroup",
    sku={
        "name": azure_native.compute.DiskStorageAccountTypes.PREMIUM_ZRS,
    })
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.NewDisk(ctx, "disk", &compute.DiskArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption: pulumi.String(compute.DiskCreateOptionEmpty),
			},
			DiskName:          pulumi.String("myDisk"),
			DiskSizeGB:        pulumi.Int(200),
			Location:          pulumi.String("West US"),
			ResourceGroupName: pulumi.String("myResourceGroup"),
			Sku: &compute.DiskSkuArgs{
				Name: pulumi.String(compute.DiskStorageAccountTypes_Premium_ZRS),
			},
		})
		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 disk = new AzureNative.Compute.Disk("disk", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.Empty,
        },
        DiskName = "myDisk",
        DiskSizeGB = 200,
        Location = "West US",
        ResourceGroupName = "myResourceGroup",
        Sku = new AzureNative.Compute.Inputs.DiskSkuArgs
        {
            Name = AzureNative.Compute.DiskStorageAccountTypes.Premium_ZRS,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Disk;
import com.pulumi.azurenative.compute.DiskArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import com.pulumi.azurenative.compute.inputs.DiskSkuArgs;
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 disk = new Disk("disk", DiskArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("Empty")
                .build())
            .diskName("myDisk")
            .diskSizeGB(200)
            .location("West US")
            .resourceGroupName("myResourceGroup")
            .sku(DiskSkuArgs.builder()
                .name("Premium_ZRS")
                .build())
            .build());

    }
}
resources:
  disk:
    type: azure-native:compute:Disk
    properties:
      creationData:
        createOption: Empty
      diskName: myDisk
      diskSizeGB: 200
      location: West US
      resourceGroupName: myResourceGroup
      sku:
        name: Premium_ZRS

The sku property controls storage type and redundancy. Setting name to Premium_ZRS enables zone-redundant storage, which replicates data synchronously across three availability zones in the region. This protects against datacenter-level failures.

Restrict disk access to private endpoints

Secure environments restrict disk access to private networks by associating disks with a disk access resource.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const disk = new azure_native.compute.Disk("disk", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.Empty,
    },
    diskAccessId: "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskAccesses/{existing-diskAccess-name}",
    diskName: "myDisk",
    diskSizeGB: 200,
    location: "West US",
    networkAccessPolicy: azure_native.compute.NetworkAccessPolicy.AllowPrivate,
    resourceGroupName: "myResourceGroup",
});
import pulumi
import pulumi_azure_native as azure_native

disk = azure_native.compute.Disk("disk",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.EMPTY,
    },
    disk_access_id="/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskAccesses/{existing-diskAccess-name}",
    disk_name="myDisk",
    disk_size_gb=200,
    location="West US",
    network_access_policy=azure_native.compute.NetworkAccessPolicy.ALLOW_PRIVATE,
    resource_group_name="myResourceGroup")
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.NewDisk(ctx, "disk", &compute.DiskArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption: pulumi.String(compute.DiskCreateOptionEmpty),
			},
			DiskAccessId:        pulumi.String("/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskAccesses/{existing-diskAccess-name}"),
			DiskName:            pulumi.String("myDisk"),
			DiskSizeGB:          pulumi.Int(200),
			Location:            pulumi.String("West US"),
			NetworkAccessPolicy: pulumi.String(compute.NetworkAccessPolicyAllowPrivate),
			ResourceGroupName:   pulumi.String("myResourceGroup"),
		})
		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 disk = new AzureNative.Compute.Disk("disk", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.Empty,
        },
        DiskAccessId = "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskAccesses/{existing-diskAccess-name}",
        DiskName = "myDisk",
        DiskSizeGB = 200,
        Location = "West US",
        NetworkAccessPolicy = AzureNative.Compute.NetworkAccessPolicy.AllowPrivate,
        ResourceGroupName = "myResourceGroup",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Disk;
import com.pulumi.azurenative.compute.DiskArgs;
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 disk = new Disk("disk", DiskArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("Empty")
                .build())
            .diskAccessId("/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskAccesses/{existing-diskAccess-name}")
            .diskName("myDisk")
            .diskSizeGB(200)
            .location("West US")
            .networkAccessPolicy("AllowPrivate")
            .resourceGroupName("myResourceGroup")
            .build());

    }
}
resources:
  disk:
    type: azure-native:compute:Disk
    properties:
      creationData:
        createOption: Empty
      diskAccessId: /subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskAccesses/{existing-diskAccess-name}
      diskName: myDisk
      diskSizeGB: 200
      location: West US
      networkAccessPolicy: AllowPrivate
      resourceGroupName: myResourceGroup

The diskAccessId property links the disk to a disk access resource that controls network exposure. Setting networkAccessPolicy to AllowPrivate blocks public internet access and requires private endpoint connections for disk operations.

Tune IOPS and throughput with Premium v2

High-performance workloads use Premium v2 disks to independently configure IOPS and throughput without being constrained by fixed disk size tiers.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const disk = new azure_native.compute.Disk("disk", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.Empty,
    },
    diskIOPSReadWrite: 125,
    diskMBpsReadWrite: 3000,
    diskName: "myPremiumV2Disk",
    diskSizeGB: 200,
    location: "West US",
    resourceGroupName: "myResourceGroup",
    sku: {
        name: azure_native.compute.DiskStorageAccountTypes.PremiumV2_LRS,
    },
});
import pulumi
import pulumi_azure_native as azure_native

disk = azure_native.compute.Disk("disk",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.EMPTY,
    },
    disk_iops_read_write=125,
    disk_m_bps_read_write=3000,
    disk_name="myPremiumV2Disk",
    disk_size_gb=200,
    location="West US",
    resource_group_name="myResourceGroup",
    sku={
        "name": azure_native.compute.DiskStorageAccountTypes.PREMIUM_V2_LRS,
    })
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.NewDisk(ctx, "disk", &compute.DiskArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption: pulumi.String(compute.DiskCreateOptionEmpty),
			},
			DiskIOPSReadWrite: pulumi.Float64(125),
			DiskMBpsReadWrite: pulumi.Float64(3000),
			DiskName:          pulumi.String("myPremiumV2Disk"),
			DiskSizeGB:        pulumi.Int(200),
			Location:          pulumi.String("West US"),
			ResourceGroupName: pulumi.String("myResourceGroup"),
			Sku: &compute.DiskSkuArgs{
				Name: pulumi.String(compute.DiskStorageAccountTypes_PremiumV2_LRS),
			},
		})
		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 disk = new AzureNative.Compute.Disk("disk", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.Empty,
        },
        DiskIOPSReadWrite = 125,
        DiskMBpsReadWrite = 3000,
        DiskName = "myPremiumV2Disk",
        DiskSizeGB = 200,
        Location = "West US",
        ResourceGroupName = "myResourceGroup",
        Sku = new AzureNative.Compute.Inputs.DiskSkuArgs
        {
            Name = AzureNative.Compute.DiskStorageAccountTypes.PremiumV2_LRS,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Disk;
import com.pulumi.azurenative.compute.DiskArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import com.pulumi.azurenative.compute.inputs.DiskSkuArgs;
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 disk = new Disk("disk", DiskArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("Empty")
                .build())
            .diskIOPSReadWrite(125.0)
            .diskMBpsReadWrite(3000.0)
            .diskName("myPremiumV2Disk")
            .diskSizeGB(200)
            .location("West US")
            .resourceGroupName("myResourceGroup")
            .sku(DiskSkuArgs.builder()
                .name("PremiumV2_LRS")
                .build())
            .build());

    }
}
resources:
  disk:
    type: azure-native:compute:Disk
    properties:
      creationData:
        createOption: Empty
      diskIOPSReadWrite: 125
      diskMBpsReadWrite: 3000
      diskName: myPremiumV2Disk
      diskSizeGB: 200
      location: West US
      resourceGroupName: myResourceGroup
      sku:
        name: PremiumV2_LRS

Premium v2 disks decouple performance from capacity. The diskIOPSReadWrite and diskMBpsReadWrite properties let you specify exact IOPS and throughput values. This allows fine-grained performance tuning without oversizing the disk.

Beyond these examples

These snippets focus on specific disk-level features: disk creation from images, snapshots, and empty allocation, encryption with platform-managed and customer-managed keys, storage SKUs and zone redundancy, and network access control and private endpoints. They’re intentionally minimal rather than full storage solutions.

The examples may reference pre-existing infrastructure such as snapshots, platform images, or Azure Compute Gallery images, disk encryption sets and disk access resources, and resource groups and Azure regions. They focus on configuring the disk rather than provisioning everything around it.

To keep things focused, common disk patterns are omitted, including:

  • Disk attachment to VMs (managed through VM resources)
  • Bursting configuration and performance tier adjustments
  • Shared disk configuration (maxShares property)
  • Extended locations and edge zone placement
  • Security profiles for confidential VMs and Trusted Launch
  • Upload workflows and ImportSecure operations

These omissions are intentional: the goal is to illustrate how each disk feature is wired, not provide drop-in storage modules. See the Disk resource reference for all available configuration options.

Let's create and Manage Azure Managed Disks

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Disk Creation & Sources
What properties can't I change after creating a disk?
The creationData property (including createOption and source information) and extendedLocation are immutable after disk creation. Plan your disk source and location before creating the resource.
What are the different ways to create a disk?
Use creationData.createOption to specify the source: Empty (new blank disk), FromImage (from platform/gallery image), Copy (from snapshot or disk), Import (from blob), ImportSecure (secure import with VM guest state), Upload (upload data), UploadPreparedSecure (secure upload), or CopyFromSanSnapshot (from Elastic SAN snapshot).
How do I import a disk from a blob in a different subscription?
Use createOption Import with sourceUri pointing to the blob and storageAccountId specifying the storage account resource ID.
How do I import a disk from a blob in the same subscription?
Use createOption Import with sourceUri pointing to the blob. The storageAccountId isn’t required for same-subscription imports.
How do I create a disk for secure import with VM guest state?
Use createOption ImportSecure with sourceUri, securityDataUri, storageAccountId, and securityProfile.securityType set to a ConfidentialVM variant.
How do I create a disk for upload with security features?
Use createOption UploadPreparedSecure with uploadSizeBytes and securityProfile.securityType (e.g., TrustedLaunch).
How do I create a disk from an Azure Compute Gallery image?
Use createOption FromImage with creationData.galleryImageReference.id pointing to the gallery image version resource ID.
How do I create a disk from a community or shared gallery image?
Use createOption FromImage with creationData.galleryImageReference.communityGalleryImageId (for community galleries) or sharedGalleryImageId (for direct shared galleries).
How do I copy a disk from an Elastic SAN volume snapshot?
Use createOption CopyFromSanSnapshot with creationData.elasticSanResourceId pointing to the snapshot resource ID.
Resizing & Capacity
When can I resize a disk?
Resizes are only allowed if the disk isn’t attached to a running VM, and can only increase the disk’s size (not decrease). Detach the disk or stop the VM before resizing.
Performance & Optimization
How do I configure IOPS and throughput for UltraSSD or PremiumV2 disks?
Set diskIOPSReadWrite and diskMBpsReadWrite when using sku.name UltraSSD_LRS or PremiumV2_LRS. These properties are only settable for these SKU types.
What's the difference between burstingEnabled and UltraSSD performance settings?
burstingEnabled allows bursting beyond provisioned performance for Standard/Premium disks but doesn’t apply to UltraSSD. For UltraSSD, use diskIOPSReadWrite and diskMBpsReadWrite instead.
When should I enable optimizedForFrequentAttach?
Enable optimizedForFrequentAttach only for disks detached and attached more than 5 times per day. Don’t set it for infrequently detached disks, as it causes them to not align with the VM’s fault domain.
How do I enable performance enhancements for disk uploads?
Set creationData.performancePlus to true when using createOption Upload.
How do I create an UltraSSD disk with 512-byte logical sector size?
Set sku.name to UltraSSD_LRS and creationData.logicalSectorSize to 512. UltraSSD supports 512 or 4096 byte sector sizes.
Security & Encryption
How do I encrypt a disk with customer-managed keys?
Set encryption.diskEncryptionSetId to the ARM ID of your disk encryption set, or use securityProfile.secureVMDiskEncryptionSetId for confidential VMs.
What security types are available for disks?
Use securityProfile.securityType with values like TrustedLaunch, ConfidentialVM_DiskEncryptedWithCustomerKey, or ConfidentialVM_VMGuestStateOnlyEncryptedWithPlatformKey.
How do I require Azure AD authentication for disk access?
Set dataAccessAuthMode to AzureActiveDirectory to require additional authentication when exporting or uploading to the disk.
Networking & Access
How do I enable private endpoint access for a disk?
Set networkAccessPolicy to AllowPrivate and specify diskAccessId with the ARM ID of your DiskAccess resource.
Advanced Configurations
How do I enable multi-attach for a disk?
Set maxShares to a value greater than 1 to allow the disk to be mounted on multiple VMs simultaneously.
How do I create a disk in an edge zone?
Set extendedLocation.name to the edge zone ID and extendedLocation.type to EdgeZone. This property is immutable after creation.
What storage account types are available?
Use sku.name with values: Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS, Premium_ZRS, StandardSSD_ZRS, or PremiumV2_LRS.

Using a different cloud?

Explore storage guides for other cloud providers: