Configure Azure Storage Cache Targets

The azure-native:storagecache:StorageTarget resource, part of the Pulumi Azure Native provider, connects backend storage to an Azure HPC Cache instance. This guide focuses on three capabilities: NFS and Blob NFS target configuration, namespace junction mapping, and cache behavior tuning.

Storage targets belong to an HPC Cache and reference external storage systems. The examples are intentionally small. Combine them with your own cache instances, NFS servers, and Blob containers.

Connect NFS storage with namespace junctions

HPC workloads often aggregate multiple NFS exports into a unified namespace, allowing clients to access different storage paths through a single mount point.

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

const storageTarget = new azure_native.storagecache.StorageTarget("storageTarget", {
    cacheName: "sc1",
    junctions: [
        {
            namespacePath: "/path/on/cache",
            nfsAccessPolicy: "default",
            nfsExport: "exp1",
            targetPath: "/path/on/exp1",
        },
        {
            namespacePath: "/path2/on/cache",
            nfsAccessPolicy: "rootSquash",
            nfsExport: "exp2",
            targetPath: "/path2/on/exp2",
        },
    ],
    nfs3: {
        target: "10.0.44.44",
        usageModel: "READ_ONLY",
        verificationTimer: 30,
    },
    resourceGroupName: "scgroup",
    storageTargetName: "st1",
    targetType: azure_native.storagecache.StorageTargetType.Nfs3,
});
import pulumi
import pulumi_azure_native as azure_native

storage_target = azure_native.storagecache.StorageTarget("storageTarget",
    cache_name="sc1",
    junctions=[
        {
            "namespace_path": "/path/on/cache",
            "nfs_access_policy": "default",
            "nfs_export": "exp1",
            "target_path": "/path/on/exp1",
        },
        {
            "namespace_path": "/path2/on/cache",
            "nfs_access_policy": "rootSquash",
            "nfs_export": "exp2",
            "target_path": "/path2/on/exp2",
        },
    ],
    nfs3={
        "target": "10.0.44.44",
        "usage_model": "READ_ONLY",
        "verification_timer": 30,
    },
    resource_group_name="scgroup",
    storage_target_name="st1",
    target_type=azure_native.storagecache.StorageTargetType.NFS3)
package main

import (
	storagecache "github.com/pulumi/pulumi-azure-native-sdk/storagecache/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := storagecache.NewStorageTarget(ctx, "storageTarget", &storagecache.StorageTargetArgs{
			CacheName: pulumi.String("sc1"),
			Junctions: storagecache.NamespaceJunctionArray{
				&storagecache.NamespaceJunctionArgs{
					NamespacePath:   pulumi.String("/path/on/cache"),
					NfsAccessPolicy: pulumi.String("default"),
					NfsExport:       pulumi.String("exp1"),
					TargetPath:      pulumi.String("/path/on/exp1"),
				},
				&storagecache.NamespaceJunctionArgs{
					NamespacePath:   pulumi.String("/path2/on/cache"),
					NfsAccessPolicy: pulumi.String("rootSquash"),
					NfsExport:       pulumi.String("exp2"),
					TargetPath:      pulumi.String("/path2/on/exp2"),
				},
			},
			Nfs3: &storagecache.Nfs3TargetArgs{
				Target:            pulumi.String("10.0.44.44"),
				UsageModel:        pulumi.String("READ_ONLY"),
				VerificationTimer: pulumi.Int(30),
			},
			ResourceGroupName: pulumi.String("scgroup"),
			StorageTargetName: pulumi.String("st1"),
			TargetType:        pulumi.String(storagecache.StorageTargetTypeNfs3),
		})
		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 storageTarget = new AzureNative.StorageCache.StorageTarget("storageTarget", new()
    {
        CacheName = "sc1",
        Junctions = new[]
        {
            new AzureNative.StorageCache.Inputs.NamespaceJunctionArgs
            {
                NamespacePath = "/path/on/cache",
                NfsAccessPolicy = "default",
                NfsExport = "exp1",
                TargetPath = "/path/on/exp1",
            },
            new AzureNative.StorageCache.Inputs.NamespaceJunctionArgs
            {
                NamespacePath = "/path2/on/cache",
                NfsAccessPolicy = "rootSquash",
                NfsExport = "exp2",
                TargetPath = "/path2/on/exp2",
            },
        },
        Nfs3 = new AzureNative.StorageCache.Inputs.Nfs3TargetArgs
        {
            Target = "10.0.44.44",
            UsageModel = "READ_ONLY",
            VerificationTimer = 30,
        },
        ResourceGroupName = "scgroup",
        StorageTargetName = "st1",
        TargetType = AzureNative.StorageCache.StorageTargetType.Nfs3,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storagecache.StorageTarget;
import com.pulumi.azurenative.storagecache.StorageTargetArgs;
import com.pulumi.azurenative.storagecache.inputs.NamespaceJunctionArgs;
import com.pulumi.azurenative.storagecache.inputs.Nfs3TargetArgs;
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 storageTarget = new StorageTarget("storageTarget", StorageTargetArgs.builder()
            .cacheName("sc1")
            .junctions(            
                NamespaceJunctionArgs.builder()
                    .namespacePath("/path/on/cache")
                    .nfsAccessPolicy("default")
                    .nfsExport("exp1")
                    .targetPath("/path/on/exp1")
                    .build(),
                NamespaceJunctionArgs.builder()
                    .namespacePath("/path2/on/cache")
                    .nfsAccessPolicy("rootSquash")
                    .nfsExport("exp2")
                    .targetPath("/path2/on/exp2")
                    .build())
            .nfs3(Nfs3TargetArgs.builder()
                .target("10.0.44.44")
                .usageModel("READ_ONLY")
                .verificationTimer(30)
                .build())
            .resourceGroupName("scgroup")
            .storageTargetName("st1")
            .targetType("nfs3")
            .build());

    }
}
resources:
  storageTarget:
    type: azure-native:storagecache:StorageTarget
    properties:
      cacheName: sc1
      junctions:
        - namespacePath: /path/on/cache
          nfsAccessPolicy: default
          nfsExport: exp1
          targetPath: /path/on/exp1
        - namespacePath: /path2/on/cache
          nfsAccessPolicy: rootSquash
          nfsExport: exp2
          targetPath: /path2/on/exp2
      nfs3:
        target: 10.0.44.44
        usageModel: READ_ONLY
        verificationTimer: 30
      resourceGroupName: scgroup
      storageTargetName: st1
      targetType: nfs3

The nfs3 block specifies the NFS server IP and usage model. Each junction in the junctions array maps a cache namespace path to an NFS export and target path. The nfsAccessPolicy controls root squashing behavior: “default” preserves root access, while “rootSquash” maps root to anonymous user. Clients mount the cache and access /path/on/cache, which transparently routes to the NFS server’s /path/on/exp1.

Mount Azure Blob storage with NFS protocol

Azure HPC Cache can front Blob storage containers that support NFS 3.0, providing low-latency access to cloud object storage.

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

const storageTarget = new azure_native.storagecache.StorageTarget("storageTarget", {
    blobNfs: {
        target: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/scgroup/providers/Microsoft.Storage/storageAccounts/blofnfs/blobServices/default/containers/blobnfs",
        usageModel: "READ_WRITE",
        verificationTimer: 28800,
        writeBackTimer: 3600,
    },
    cacheName: "sc1",
    junctions: [{
        namespacePath: "/blobnfs",
    }],
    resourceGroupName: "scgroup",
    storageTargetName: "st1",
    targetType: azure_native.storagecache.StorageTargetType.BlobNfs,
});
import pulumi
import pulumi_azure_native as azure_native

storage_target = azure_native.storagecache.StorageTarget("storageTarget",
    blob_nfs={
        "target": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/scgroup/providers/Microsoft.Storage/storageAccounts/blofnfs/blobServices/default/containers/blobnfs",
        "usage_model": "READ_WRITE",
        "verification_timer": 28800,
        "write_back_timer": 3600,
    },
    cache_name="sc1",
    junctions=[{
        "namespace_path": "/blobnfs",
    }],
    resource_group_name="scgroup",
    storage_target_name="st1",
    target_type=azure_native.storagecache.StorageTargetType.BLOB_NFS)
package main

import (
	storagecache "github.com/pulumi/pulumi-azure-native-sdk/storagecache/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := storagecache.NewStorageTarget(ctx, "storageTarget", &storagecache.StorageTargetArgs{
			BlobNfs: &storagecache.BlobNfsTargetArgs{
				Target:            pulumi.String("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/scgroup/providers/Microsoft.Storage/storageAccounts/blofnfs/blobServices/default/containers/blobnfs"),
				UsageModel:        pulumi.String("READ_WRITE"),
				VerificationTimer: pulumi.Int(28800),
				WriteBackTimer:    pulumi.Int(3600),
			},
			CacheName: pulumi.String("sc1"),
			Junctions: storagecache.NamespaceJunctionArray{
				&storagecache.NamespaceJunctionArgs{
					NamespacePath: pulumi.String("/blobnfs"),
				},
			},
			ResourceGroupName: pulumi.String("scgroup"),
			StorageTargetName: pulumi.String("st1"),
			TargetType:        pulumi.String(storagecache.StorageTargetTypeBlobNfs),
		})
		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 storageTarget = new AzureNative.StorageCache.StorageTarget("storageTarget", new()
    {
        BlobNfs = new AzureNative.StorageCache.Inputs.BlobNfsTargetArgs
        {
            Target = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/scgroup/providers/Microsoft.Storage/storageAccounts/blofnfs/blobServices/default/containers/blobnfs",
            UsageModel = "READ_WRITE",
            VerificationTimer = 28800,
            WriteBackTimer = 3600,
        },
        CacheName = "sc1",
        Junctions = new[]
        {
            new AzureNative.StorageCache.Inputs.NamespaceJunctionArgs
            {
                NamespacePath = "/blobnfs",
            },
        },
        ResourceGroupName = "scgroup",
        StorageTargetName = "st1",
        TargetType = AzureNative.StorageCache.StorageTargetType.BlobNfs,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storagecache.StorageTarget;
import com.pulumi.azurenative.storagecache.StorageTargetArgs;
import com.pulumi.azurenative.storagecache.inputs.BlobNfsTargetArgs;
import com.pulumi.azurenative.storagecache.inputs.NamespaceJunctionArgs;
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 storageTarget = new StorageTarget("storageTarget", StorageTargetArgs.builder()
            .blobNfs(BlobNfsTargetArgs.builder()
                .target("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/scgroup/providers/Microsoft.Storage/storageAccounts/blofnfs/blobServices/default/containers/blobnfs")
                .usageModel("READ_WRITE")
                .verificationTimer(28800)
                .writeBackTimer(3600)
                .build())
            .cacheName("sc1")
            .junctions(NamespaceJunctionArgs.builder()
                .namespacePath("/blobnfs")
                .build())
            .resourceGroupName("scgroup")
            .storageTargetName("st1")
            .targetType("blobNfs")
            .build());

    }
}
resources:
  storageTarget:
    type: azure-native:storagecache:StorageTarget
    properties:
      blobNfs:
        target: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/scgroup/providers/Microsoft.Storage/storageAccounts/blofnfs/blobServices/default/containers/blobnfs
        usageModel: READ_WRITE
        verificationTimer: 28800
        writeBackTimer: 3600
      cacheName: sc1
      junctions:
        - namespacePath: /blobnfs
      resourceGroupName: scgroup
      storageTargetName: st1
      targetType: blobNfs

The blobNfs block points to a Blob container resource ID and sets cache behavior timers. The usageModel determines read/write patterns: “READ_WRITE” enables write-back caching. The verificationTimer (28800 seconds, or 8 hours) controls how often the cache checks for backend changes. The writeBackTimer (3600 seconds) sets how long the cache holds writes before flushing to Blob storage.

Attach NFS storage without namespace mapping

Some deployments defer namespace configuration, attaching storage targets first and defining junctions later.

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

const storageTarget = new azure_native.storagecache.StorageTarget("storageTarget", {
    cacheName: "sc1",
    nfs3: {
        target: "10.0.44.44",
        usageModel: "READ_ONLY",
        verificationTimer: 30,
    },
    resourceGroupName: "scgroup",
    storageTargetName: "st1",
    targetType: azure_native.storagecache.StorageTargetType.Nfs3,
});
import pulumi
import pulumi_azure_native as azure_native

storage_target = azure_native.storagecache.StorageTarget("storageTarget",
    cache_name="sc1",
    nfs3={
        "target": "10.0.44.44",
        "usage_model": "READ_ONLY",
        "verification_timer": 30,
    },
    resource_group_name="scgroup",
    storage_target_name="st1",
    target_type=azure_native.storagecache.StorageTargetType.NFS3)
package main

import (
	storagecache "github.com/pulumi/pulumi-azure-native-sdk/storagecache/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := storagecache.NewStorageTarget(ctx, "storageTarget", &storagecache.StorageTargetArgs{
			CacheName: pulumi.String("sc1"),
			Nfs3: &storagecache.Nfs3TargetArgs{
				Target:            pulumi.String("10.0.44.44"),
				UsageModel:        pulumi.String("READ_ONLY"),
				VerificationTimer: pulumi.Int(30),
			},
			ResourceGroupName: pulumi.String("scgroup"),
			StorageTargetName: pulumi.String("st1"),
			TargetType:        pulumi.String(storagecache.StorageTargetTypeNfs3),
		})
		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 storageTarget = new AzureNative.StorageCache.StorageTarget("storageTarget", new()
    {
        CacheName = "sc1",
        Nfs3 = new AzureNative.StorageCache.Inputs.Nfs3TargetArgs
        {
            Target = "10.0.44.44",
            UsageModel = "READ_ONLY",
            VerificationTimer = 30,
        },
        ResourceGroupName = "scgroup",
        StorageTargetName = "st1",
        TargetType = AzureNative.StorageCache.StorageTargetType.Nfs3,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storagecache.StorageTarget;
import com.pulumi.azurenative.storagecache.StorageTargetArgs;
import com.pulumi.azurenative.storagecache.inputs.Nfs3TargetArgs;
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 storageTarget = new StorageTarget("storageTarget", StorageTargetArgs.builder()
            .cacheName("sc1")
            .nfs3(Nfs3TargetArgs.builder()
                .target("10.0.44.44")
                .usageModel("READ_ONLY")
                .verificationTimer(30)
                .build())
            .resourceGroupName("scgroup")
            .storageTargetName("st1")
            .targetType("nfs3")
            .build());

    }
}
resources:
  storageTarget:
    type: azure-native:storagecache:StorageTarget
    properties:
      cacheName: sc1
      nfs3:
        target: 10.0.44.44
        usageModel: READ_ONLY
        verificationTimer: 30
      resourceGroupName: scgroup
      storageTargetName: st1
      targetType: nfs3

This minimal configuration registers the NFS server without exposing it through the cache namespace. The verificationTimer (30 seconds) sets a short interval for checking backend changes, suitable for frequently updated storage. You can add junctions later by updating the storage target resource.

Beyond these examples

These snippets focus on specific storage target features: NFS and Blob NFS target types, namespace junction mapping, and usage models and cache timers. They’re intentionally minimal rather than full HPC Cache deployments.

The examples reference pre-existing infrastructure such as Azure HPC Cache instances, NFS servers or NFS-enabled Blob containers, and resource groups. They focus on configuring the storage target rather than provisioning the cache or backend storage.

To keep things focused, common storage target patterns are omitted, including:

  • CLFS (Cloud Lustre File System) targets
  • State management (operational state transitions)
  • Allocation percentage tuning
  • Unknown target type handling

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

Let's configure Azure Storage Cache Targets

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Target Types
What storage target types are supported?
Azure HPC Cache supports nfs3, blobNfs, clfs, and unknown target types. The targetType property is required and immutable.
Can I change the target type or cache name after creation?
No, targetType, cacheName, storageTargetName, and resourceGroupName are all immutable. Changes require recreating the storage target.
How do I connect to an NFS3 storage backend?
Set targetType to nfs3 and configure the nfs3 object with target (IP address like “10.0.44.44”), usageModel, and verificationTimer.
How do I connect to Azure Blob storage with NFS?
Set targetType to blobNfs and provide the full Azure resource path in blobNfs.target (e.g., “/subscriptions/…/containers/blobnfs”). Configure usageModel, verificationTimer, and writeBackTimer.
What characters are allowed in cache names?
Cache names must be 80 characters or fewer, using only characters from the [-0-9a-zA-Z_] character class.
Namespace Junctions
Are namespace junctions required?
No, junctions are optional. You can create a storage target without the junctions array, as shown in the NoJunctions example.
How do I configure multiple namespace paths?
Provide an array of junction objects in junctions, each with namespacePath, nfsAccessPolicy, nfsExport, and targetPath.
What NFS access policies can I use for junctions?
Examples show default and rootSquash as nfsAccessPolicy values for namespace junctions.
Performance & Caching
What's the difference between verificationTimer and writeBackTimer?
verificationTimer (used by both NFS3 and BlobNfs) controls how often the cache verifies backend data freshness. writeBackTimer (BlobNfs only) controls how often cached writes are flushed to the backend. Examples show 30 seconds for verification and 3600 seconds for write-back.
What usage models are available?
Examples show READ_ONLY and READ_WRITE as usage model values for both NFS3 and BlobNfs targets.

Using a different cloud?

Explore storage guides for other cloud providers: