Deploy Azure Batch Pools

The azure-native:batch:Pool resource, part of the Pulumi Azure Native provider, defines a Batch pool: its compute nodes, VM configuration, scaling behavior, and network placement. This guide focuses on four capabilities: marketplace and custom image selection, autoscaling and fixed-scale configurations, network isolation and security, and storage and encryption.

Pools require a Batch account and may reference VNets, subnets, gallery images, or other Azure resources. The examples are intentionally small. Combine them with your own Batch accounts, networking, and application deployment strategies.

Create a pool with marketplace images and autoscaling

Most Batch pools start with a marketplace image, a VM size, and a scaling strategy to provision compute nodes for parallel workloads.

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

const pool = new azure_native.batch.Pool("pool", {
    accountName: "sampleacct",
    deploymentConfiguration: {
        virtualMachineConfiguration: {
            imageReference: {
                offer: "UbuntuServer",
                publisher: "Canonical",
                sku: "18.04-LTS",
                version: "latest",
            },
            nodeAgentSkuId: "batch.node.ubuntu 18.04",
        },
    },
    poolName: "testpool",
    resourceGroupName: "default-azurebatch-japaneast",
    scaleSettings: {
        autoScale: {
            evaluationInterval: "PT5M",
            formula: "$TargetDedicatedNodes=1",
        },
    },
    vmSize: "STANDARD_D4",
});
import pulumi
import pulumi_azure_native as azure_native

pool = azure_native.batch.Pool("pool",
    account_name="sampleacct",
    deployment_configuration={
        "virtual_machine_configuration": {
            "image_reference": {
                "offer": "UbuntuServer",
                "publisher": "Canonical",
                "sku": "18.04-LTS",
                "version": "latest",
            },
            "node_agent_sku_id": "batch.node.ubuntu 18.04",
        },
    },
    pool_name="testpool",
    resource_group_name="default-azurebatch-japaneast",
    scale_settings={
        "auto_scale": {
            "evaluation_interval": "PT5M",
            "formula": "$TargetDedicatedNodes=1",
        },
    },
    vm_size="STANDARD_D4")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := batch.NewPool(ctx, "pool", &batch.PoolArgs{
			AccountName: pulumi.String("sampleacct"),
			DeploymentConfiguration: &batch.DeploymentConfigurationArgs{
				VirtualMachineConfiguration: &batch.VirtualMachineConfigurationArgs{
					ImageReference: &batch.ImageReferenceArgs{
						Offer:     pulumi.String("UbuntuServer"),
						Publisher: pulumi.String("Canonical"),
						Sku:       pulumi.String("18.04-LTS"),
						Version:   pulumi.String("latest"),
					},
					NodeAgentSkuId: pulumi.String("batch.node.ubuntu 18.04"),
				},
			},
			PoolName:          pulumi.String("testpool"),
			ResourceGroupName: pulumi.String("default-azurebatch-japaneast"),
			ScaleSettings: &batch.ScaleSettingsArgs{
				AutoScale: &batch.AutoScaleSettingsArgs{
					EvaluationInterval: pulumi.String("PT5M"),
					Formula:            pulumi.String("$TargetDedicatedNodes=1"),
				},
			},
			VmSize: pulumi.String("STANDARD_D4"),
		})
		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 pool = new AzureNative.Batch.Pool("pool", new()
    {
        AccountName = "sampleacct",
        DeploymentConfiguration = new AzureNative.Batch.Inputs.DeploymentConfigurationArgs
        {
            VirtualMachineConfiguration = new AzureNative.Batch.Inputs.VirtualMachineConfigurationArgs
            {
                ImageReference = new AzureNative.Batch.Inputs.ImageReferenceArgs
                {
                    Offer = "UbuntuServer",
                    Publisher = "Canonical",
                    Sku = "18.04-LTS",
                    Version = "latest",
                },
                NodeAgentSkuId = "batch.node.ubuntu 18.04",
            },
        },
        PoolName = "testpool",
        ResourceGroupName = "default-azurebatch-japaneast",
        ScaleSettings = new AzureNative.Batch.Inputs.ScaleSettingsArgs
        {
            AutoScale = new AzureNative.Batch.Inputs.AutoScaleSettingsArgs
            {
                EvaluationInterval = "PT5M",
                Formula = "$TargetDedicatedNodes=1",
            },
        },
        VmSize = "STANDARD_D4",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.batch.Pool;
import com.pulumi.azurenative.batch.PoolArgs;
import com.pulumi.azurenative.batch.inputs.DeploymentConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.VirtualMachineConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.ImageReferenceArgs;
import com.pulumi.azurenative.batch.inputs.ScaleSettingsArgs;
import com.pulumi.azurenative.batch.inputs.AutoScaleSettingsArgs;
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 pool = new Pool("pool", PoolArgs.builder()
            .accountName("sampleacct")
            .deploymentConfiguration(DeploymentConfigurationArgs.builder()
                .virtualMachineConfiguration(VirtualMachineConfigurationArgs.builder()
                    .imageReference(ImageReferenceArgs.builder()
                        .offer("UbuntuServer")
                        .publisher("Canonical")
                        .sku("18.04-LTS")
                        .version("latest")
                        .build())
                    .nodeAgentSkuId("batch.node.ubuntu 18.04")
                    .build())
                .build())
            .poolName("testpool")
            .resourceGroupName("default-azurebatch-japaneast")
            .scaleSettings(ScaleSettingsArgs.builder()
                .autoScale(AutoScaleSettingsArgs.builder()
                    .evaluationInterval("PT5M")
                    .formula("$TargetDedicatedNodes=1")
                    .build())
                .build())
            .vmSize("STANDARD_D4")
            .build());

    }
}
resources:
  pool:
    type: azure-native:batch:Pool
    properties:
      accountName: sampleacct
      deploymentConfiguration:
        virtualMachineConfiguration:
          imageReference:
            offer: UbuntuServer
            publisher: Canonical
            sku: 18.04-LTS
            version: latest
          nodeAgentSkuId: batch.node.ubuntu 18.04
      poolName: testpool
      resourceGroupName: default-azurebatch-japaneast
      scaleSettings:
        autoScale:
          evaluationInterval: PT5M
          formula: $TargetDedicatedNodes=1
      vmSize: STANDARD_D4

The imageReference selects an Ubuntu image from the Azure Marketplace. The nodeAgentSkuId specifies the Batch agent version that runs on each node. The scaleSettings block defines autoscaling: the formula evaluates every 5 minutes and adjusts the pool size based on workload. Here, it maintains one dedicated node.

Teams with specialized software often build custom images in Azure Compute Gallery rather than starting from marketplace images.

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

const pool = new azure_native.batch.Pool("pool", {
    accountName: "sampleacct",
    deploymentConfiguration: {
        virtualMachineConfiguration: {
            imageReference: {
                id: "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1",
            },
            nodeAgentSkuId: "batch.node.ubuntu 18.04",
        },
    },
    poolName: "testpool",
    resourceGroupName: "default-azurebatch-japaneast",
    vmSize: "STANDARD_D4",
});
import pulumi
import pulumi_azure_native as azure_native

pool = azure_native.batch.Pool("pool",
    account_name="sampleacct",
    deployment_configuration={
        "virtual_machine_configuration": {
            "image_reference": {
                "id": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1",
            },
            "node_agent_sku_id": "batch.node.ubuntu 18.04",
        },
    },
    pool_name="testpool",
    resource_group_name="default-azurebatch-japaneast",
    vm_size="STANDARD_D4")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := batch.NewPool(ctx, "pool", &batch.PoolArgs{
			AccountName: pulumi.String("sampleacct"),
			DeploymentConfiguration: &batch.DeploymentConfigurationArgs{
				VirtualMachineConfiguration: &batch.VirtualMachineConfigurationArgs{
					ImageReference: &batch.ImageReferenceArgs{
						Id: pulumi.String("/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1"),
					},
					NodeAgentSkuId: pulumi.String("batch.node.ubuntu 18.04"),
				},
			},
			PoolName:          pulumi.String("testpool"),
			ResourceGroupName: pulumi.String("default-azurebatch-japaneast"),
			VmSize:            pulumi.String("STANDARD_D4"),
		})
		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 pool = new AzureNative.Batch.Pool("pool", new()
    {
        AccountName = "sampleacct",
        DeploymentConfiguration = new AzureNative.Batch.Inputs.DeploymentConfigurationArgs
        {
            VirtualMachineConfiguration = new AzureNative.Batch.Inputs.VirtualMachineConfigurationArgs
            {
                ImageReference = new AzureNative.Batch.Inputs.ImageReferenceArgs
                {
                    Id = "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1",
                },
                NodeAgentSkuId = "batch.node.ubuntu 18.04",
            },
        },
        PoolName = "testpool",
        ResourceGroupName = "default-azurebatch-japaneast",
        VmSize = "STANDARD_D4",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.batch.Pool;
import com.pulumi.azurenative.batch.PoolArgs;
import com.pulumi.azurenative.batch.inputs.DeploymentConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.VirtualMachineConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.ImageReferenceArgs;
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 pool = new Pool("pool", PoolArgs.builder()
            .accountName("sampleacct")
            .deploymentConfiguration(DeploymentConfigurationArgs.builder()
                .virtualMachineConfiguration(VirtualMachineConfigurationArgs.builder()
                    .imageReference(ImageReferenceArgs.builder()
                        .id("/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1")
                        .build())
                    .nodeAgentSkuId("batch.node.ubuntu 18.04")
                    .build())
                .build())
            .poolName("testpool")
            .resourceGroupName("default-azurebatch-japaneast")
            .vmSize("STANDARD_D4")
            .build());

    }
}
resources:
  pool:
    type: azure-native:batch:Pool
    properties:
      accountName: sampleacct
      deploymentConfiguration:
        virtualMachineConfiguration:
          imageReference:
            id: /subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1
          nodeAgentSkuId: batch.node.ubuntu 18.04
      poolName: testpool
      resourceGroupName: default-azurebatch-japaneast
      vmSize: STANDARD_D4

The imageReference.id points to a specific gallery image version. This allows you to deploy nodes with pre-installed software, configurations, or security hardening. The nodeAgentSkuId must match the OS family of your custom image.

Tag pool resources for cost tracking

When pools are created in UserSubscription mode, Batch provisions backing Azure resources that can be tagged for cost allocation.

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

const pool = new azure_native.batch.Pool("pool", {
    accountName: "sampleacct",
    deploymentConfiguration: {
        virtualMachineConfiguration: {
            imageReference: {
                offer: "UbuntuServer",
                publisher: "Canonical",
                sku: "18_04-lts-gen2",
                version: "latest",
            },
            nodeAgentSkuId: "batch.node.ubuntu 18.04",
        },
    },
    poolName: "testpool",
    resourceGroupName: "default-azurebatch-japaneast",
    resourceTags: {
        TagName1: "TagValue1",
        TagName2: "TagValue2",
    },
    scaleSettings: {
        fixedScale: {
            targetDedicatedNodes: 1,
            targetLowPriorityNodes: 0,
        },
    },
    vmSize: "Standard_d4s_v3",
});
import pulumi
import pulumi_azure_native as azure_native

pool = azure_native.batch.Pool("pool",
    account_name="sampleacct",
    deployment_configuration={
        "virtual_machine_configuration": {
            "image_reference": {
                "offer": "UbuntuServer",
                "publisher": "Canonical",
                "sku": "18_04-lts-gen2",
                "version": "latest",
            },
            "node_agent_sku_id": "batch.node.ubuntu 18.04",
        },
    },
    pool_name="testpool",
    resource_group_name="default-azurebatch-japaneast",
    resource_tags={
        "TagName1": "TagValue1",
        "TagName2": "TagValue2",
    },
    scale_settings={
        "fixed_scale": {
            "target_dedicated_nodes": 1,
            "target_low_priority_nodes": 0,
        },
    },
    vm_size="Standard_d4s_v3")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := batch.NewPool(ctx, "pool", &batch.PoolArgs{
			AccountName: pulumi.String("sampleacct"),
			DeploymentConfiguration: &batch.DeploymentConfigurationArgs{
				VirtualMachineConfiguration: &batch.VirtualMachineConfigurationArgs{
					ImageReference: &batch.ImageReferenceArgs{
						Offer:     pulumi.String("UbuntuServer"),
						Publisher: pulumi.String("Canonical"),
						Sku:       pulumi.String("18_04-lts-gen2"),
						Version:   pulumi.String("latest"),
					},
					NodeAgentSkuId: pulumi.String("batch.node.ubuntu 18.04"),
				},
			},
			PoolName:          pulumi.String("testpool"),
			ResourceGroupName: pulumi.String("default-azurebatch-japaneast"),
			ResourceTags: pulumi.StringMap{
				"TagName1": pulumi.String("TagValue1"),
				"TagName2": pulumi.String("TagValue2"),
			},
			ScaleSettings: &batch.ScaleSettingsArgs{
				FixedScale: &batch.FixedScaleSettingsArgs{
					TargetDedicatedNodes:   pulumi.Int(1),
					TargetLowPriorityNodes: pulumi.Int(0),
				},
			},
			VmSize: pulumi.String("Standard_d4s_v3"),
		})
		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 pool = new AzureNative.Batch.Pool("pool", new()
    {
        AccountName = "sampleacct",
        DeploymentConfiguration = new AzureNative.Batch.Inputs.DeploymentConfigurationArgs
        {
            VirtualMachineConfiguration = new AzureNative.Batch.Inputs.VirtualMachineConfigurationArgs
            {
                ImageReference = new AzureNative.Batch.Inputs.ImageReferenceArgs
                {
                    Offer = "UbuntuServer",
                    Publisher = "Canonical",
                    Sku = "18_04-lts-gen2",
                    Version = "latest",
                },
                NodeAgentSkuId = "batch.node.ubuntu 18.04",
            },
        },
        PoolName = "testpool",
        ResourceGroupName = "default-azurebatch-japaneast",
        ResourceTags = 
        {
            { "TagName1", "TagValue1" },
            { "TagName2", "TagValue2" },
        },
        ScaleSettings = new AzureNative.Batch.Inputs.ScaleSettingsArgs
        {
            FixedScale = new AzureNative.Batch.Inputs.FixedScaleSettingsArgs
            {
                TargetDedicatedNodes = 1,
                TargetLowPriorityNodes = 0,
            },
        },
        VmSize = "Standard_d4s_v3",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.batch.Pool;
import com.pulumi.azurenative.batch.PoolArgs;
import com.pulumi.azurenative.batch.inputs.DeploymentConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.VirtualMachineConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.ImageReferenceArgs;
import com.pulumi.azurenative.batch.inputs.ScaleSettingsArgs;
import com.pulumi.azurenative.batch.inputs.FixedScaleSettingsArgs;
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 pool = new Pool("pool", PoolArgs.builder()
            .accountName("sampleacct")
            .deploymentConfiguration(DeploymentConfigurationArgs.builder()
                .virtualMachineConfiguration(VirtualMachineConfigurationArgs.builder()
                    .imageReference(ImageReferenceArgs.builder()
                        .offer("UbuntuServer")
                        .publisher("Canonical")
                        .sku("18_04-lts-gen2")
                        .version("latest")
                        .build())
                    .nodeAgentSkuId("batch.node.ubuntu 18.04")
                    .build())
                .build())
            .poolName("testpool")
            .resourceGroupName("default-azurebatch-japaneast")
            .resourceTags(Map.ofEntries(
                Map.entry("TagName1", "TagValue1"),
                Map.entry("TagName2", "TagValue2")
            ))
            .scaleSettings(ScaleSettingsArgs.builder()
                .fixedScale(FixedScaleSettingsArgs.builder()
                    .targetDedicatedNodes(1)
                    .targetLowPriorityNodes(0)
                    .build())
                .build())
            .vmSize("Standard_d4s_v3")
            .build());

    }
}
resources:
  pool:
    type: azure-native:batch:Pool
    properties:
      accountName: sampleacct
      deploymentConfiguration:
        virtualMachineConfiguration:
          imageReference:
            offer: UbuntuServer
            publisher: Canonical
            sku: 18_04-lts-gen2
            version: latest
          nodeAgentSkuId: batch.node.ubuntu 18.04
      poolName: testpool
      resourceGroupName: default-azurebatch-japaneast
      resourceTags:
        TagName1: TagValue1
        TagName2: TagValue2
      scaleSettings:
        fixedScale:
          targetDedicatedNodes: 1
          targetLowPriorityNodes: 0
      vmSize: Standard_d4s_v3

The resourceTags property applies key-value pairs to VMs and storage created by the pool. These tags propagate to Azure billing and cost management tools. The fixedScale block sets a static node count rather than autoscaling.

Deploy nodes without public IP addresses

Pools in private networks often disable public IPs to reduce attack surface and enforce connectivity through private endpoints.

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

const pool = new azure_native.batch.Pool("pool", {
    accountName: "sampleacct",
    deploymentConfiguration: {
        virtualMachineConfiguration: {
            imageReference: {
                id: "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1",
            },
            nodeAgentSkuId: "batch.node.ubuntu 18.04",
        },
    },
    networkConfiguration: {
        publicIPAddressConfiguration: {
            provision: azure_native.batch.IPAddressProvisioningType.NoPublicIPAddresses,
        },
        subnetId: "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123",
    },
    poolName: "testpool",
    resourceGroupName: "default-azurebatch-japaneast",
    vmSize: "STANDARD_D4",
});
import pulumi
import pulumi_azure_native as azure_native

pool = azure_native.batch.Pool("pool",
    account_name="sampleacct",
    deployment_configuration={
        "virtual_machine_configuration": {
            "image_reference": {
                "id": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1",
            },
            "node_agent_sku_id": "batch.node.ubuntu 18.04",
        },
    },
    network_configuration={
        "public_ip_address_configuration": {
            "provision": azure_native.batch.IPAddressProvisioningType.NO_PUBLIC_IP_ADDRESSES,
        },
        "subnet_id": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123",
    },
    pool_name="testpool",
    resource_group_name="default-azurebatch-japaneast",
    vm_size="STANDARD_D4")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := batch.NewPool(ctx, "pool", &batch.PoolArgs{
			AccountName: pulumi.String("sampleacct"),
			DeploymentConfiguration: &batch.DeploymentConfigurationArgs{
				VirtualMachineConfiguration: &batch.VirtualMachineConfigurationArgs{
					ImageReference: &batch.ImageReferenceArgs{
						Id: pulumi.String("/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1"),
					},
					NodeAgentSkuId: pulumi.String("batch.node.ubuntu 18.04"),
				},
			},
			NetworkConfiguration: &batch.NetworkConfigurationArgs{
				PublicIPAddressConfiguration: &batch.PublicIPAddressConfigurationArgs{
					Provision: batch.IPAddressProvisioningTypeNoPublicIPAddresses,
				},
				SubnetId: pulumi.String("/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123"),
			},
			PoolName:          pulumi.String("testpool"),
			ResourceGroupName: pulumi.String("default-azurebatch-japaneast"),
			VmSize:            pulumi.String("STANDARD_D4"),
		})
		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 pool = new AzureNative.Batch.Pool("pool", new()
    {
        AccountName = "sampleacct",
        DeploymentConfiguration = new AzureNative.Batch.Inputs.DeploymentConfigurationArgs
        {
            VirtualMachineConfiguration = new AzureNative.Batch.Inputs.VirtualMachineConfigurationArgs
            {
                ImageReference = new AzureNative.Batch.Inputs.ImageReferenceArgs
                {
                    Id = "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1",
                },
                NodeAgentSkuId = "batch.node.ubuntu 18.04",
            },
        },
        NetworkConfiguration = new AzureNative.Batch.Inputs.NetworkConfigurationArgs
        {
            PublicIPAddressConfiguration = new AzureNative.Batch.Inputs.PublicIPAddressConfigurationArgs
            {
                Provision = AzureNative.Batch.IPAddressProvisioningType.NoPublicIPAddresses,
            },
            SubnetId = "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123",
        },
        PoolName = "testpool",
        ResourceGroupName = "default-azurebatch-japaneast",
        VmSize = "STANDARD_D4",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.batch.Pool;
import com.pulumi.azurenative.batch.PoolArgs;
import com.pulumi.azurenative.batch.inputs.DeploymentConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.VirtualMachineConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.ImageReferenceArgs;
import com.pulumi.azurenative.batch.inputs.NetworkConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.PublicIPAddressConfigurationArgs;
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 pool = new Pool("pool", PoolArgs.builder()
            .accountName("sampleacct")
            .deploymentConfiguration(DeploymentConfigurationArgs.builder()
                .virtualMachineConfiguration(VirtualMachineConfigurationArgs.builder()
                    .imageReference(ImageReferenceArgs.builder()
                        .id("/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1")
                        .build())
                    .nodeAgentSkuId("batch.node.ubuntu 18.04")
                    .build())
                .build())
            .networkConfiguration(NetworkConfigurationArgs.builder()
                .publicIPAddressConfiguration(PublicIPAddressConfigurationArgs.builder()
                    .provision("NoPublicIPAddresses")
                    .build())
                .subnetId("/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123")
                .build())
            .poolName("testpool")
            .resourceGroupName("default-azurebatch-japaneast")
            .vmSize("STANDARD_D4")
            .build());

    }
}
resources:
  pool:
    type: azure-native:batch:Pool
    properties:
      accountName: sampleacct
      deploymentConfiguration:
        virtualMachineConfiguration:
          imageReference:
            id: /subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/networking-group/providers/Microsoft.Compute/galleries/testgallery/images/testimagedef/versions/0.0.1
          nodeAgentSkuId: batch.node.ubuntu 18.04
      networkConfiguration:
        publicIPAddressConfiguration:
          provision: NoPublicIPAddresses
        subnetId: /subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123
      poolName: testpool
      resourceGroupName: default-azurebatch-japaneast
      vmSize: STANDARD_D4

The publicIPAddressConfiguration.provision property controls IP assignment. Setting it to NoPublicIPAddresses prevents nodes from receiving public IPs. The subnetId places nodes in a specific VNet subnet. This configuration requires private connectivity to the Batch service endpoint.

Configure storage, encryption, and network security

Production pools often require data disks, disk encryption, and network security rules to meet compliance requirements.

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

const pool = new azure_native.batch.Pool("pool", {
    accountName: "sampleacct",
    deploymentConfiguration: {
        virtualMachineConfiguration: {
            dataDisks: [
                {
                    caching: azure_native.batch.CachingType.ReadWrite,
                    diskSizeGB: 30,
                    lun: 0,
                    storageAccountType: azure_native.batch.StorageAccountType.Premium_LRS,
                },
                {
                    caching: azure_native.batch.CachingType.None,
                    diskSizeGB: 200,
                    lun: 1,
                    storageAccountType: azure_native.batch.StorageAccountType.Standard_LRS,
                },
            ],
            diskEncryptionConfiguration: {
                targets: [
                    azure_native.batch.DiskEncryptionTarget.OsDisk,
                    azure_native.batch.DiskEncryptionTarget.TemporaryDisk,
                ],
            },
            imageReference: {
                offer: "WindowsServer",
                publisher: "MicrosoftWindowsServer",
                sku: "2016-Datacenter-SmallDisk",
                version: "latest",
            },
            licenseType: "Windows_Server",
            nodeAgentSkuId: "batch.node.windows amd64",
            nodePlacementConfiguration: {
                policy: azure_native.batch.NodePlacementPolicyType.Zonal,
            },
            osDisk: {
                ephemeralOSDiskSettings: {
                    placement: azure_native.batch.DiffDiskPlacement.CacheDisk,
                },
            },
            windowsConfiguration: {
                enableAutomaticUpdates: false,
            },
        },
    },
    networkConfiguration: {
        endpointConfiguration: {
            inboundNatPools: [{
                backendPort: 12001,
                frontendPortRangeEnd: 15100,
                frontendPortRangeStart: 15000,
                name: "testnat",
                networkSecurityGroupRules: [
                    {
                        access: azure_native.batch.NetworkSecurityGroupRuleAccess.Allow,
                        priority: 150,
                        sourceAddressPrefix: "192.100.12.45",
                        sourcePortRanges: [
                            "1",
                            "2",
                        ],
                    },
                    {
                        access: azure_native.batch.NetworkSecurityGroupRuleAccess.Deny,
                        priority: 3500,
                        sourceAddressPrefix: "*",
                        sourcePortRanges: ["*"],
                    },
                ],
                protocol: azure_native.batch.InboundEndpointProtocol.TCP,
            }],
        },
    },
    poolName: "testpool",
    resourceGroupName: "default-azurebatch-japaneast",
    scaleSettings: {
        autoScale: {
            evaluationInterval: "PT5M",
            formula: "$TargetDedicatedNodes=1",
        },
    },
    vmSize: "STANDARD_D4",
});
import pulumi
import pulumi_azure_native as azure_native

pool = azure_native.batch.Pool("pool",
    account_name="sampleacct",
    deployment_configuration={
        "virtual_machine_configuration": {
            "data_disks": [
                {
                    "caching": azure_native.batch.CachingType.READ_WRITE,
                    "disk_size_gb": 30,
                    "lun": 0,
                    "storage_account_type": azure_native.batch.StorageAccountType.PREMIUM_LRS,
                },
                {
                    "caching": azure_native.batch.CachingType.NONE,
                    "disk_size_gb": 200,
                    "lun": 1,
                    "storage_account_type": azure_native.batch.StorageAccountType.STANDARD_LRS,
                },
            ],
            "disk_encryption_configuration": {
                "targets": [
                    azure_native.batch.DiskEncryptionTarget.OS_DISK,
                    azure_native.batch.DiskEncryptionTarget.TEMPORARY_DISK,
                ],
            },
            "image_reference": {
                "offer": "WindowsServer",
                "publisher": "MicrosoftWindowsServer",
                "sku": "2016-Datacenter-SmallDisk",
                "version": "latest",
            },
            "license_type": "Windows_Server",
            "node_agent_sku_id": "batch.node.windows amd64",
            "node_placement_configuration": {
                "policy": azure_native.batch.NodePlacementPolicyType.ZONAL,
            },
            "os_disk": {
                "ephemeral_os_disk_settings": {
                    "placement": azure_native.batch.DiffDiskPlacement.CACHE_DISK,
                },
            },
            "windows_configuration": {
                "enable_automatic_updates": False,
            },
        },
    },
    network_configuration={
        "endpoint_configuration": {
            "inbound_nat_pools": [{
                "backend_port": 12001,
                "frontend_port_range_end": 15100,
                "frontend_port_range_start": 15000,
                "name": "testnat",
                "network_security_group_rules": [
                    {
                        "access": azure_native.batch.NetworkSecurityGroupRuleAccess.ALLOW,
                        "priority": 150,
                        "source_address_prefix": "192.100.12.45",
                        "source_port_ranges": [
                            "1",
                            "2",
                        ],
                    },
                    {
                        "access": azure_native.batch.NetworkSecurityGroupRuleAccess.DENY,
                        "priority": 3500,
                        "source_address_prefix": "*",
                        "source_port_ranges": ["*"],
                    },
                ],
                "protocol": azure_native.batch.InboundEndpointProtocol.TCP,
            }],
        },
    },
    pool_name="testpool",
    resource_group_name="default-azurebatch-japaneast",
    scale_settings={
        "auto_scale": {
            "evaluation_interval": "PT5M",
            "formula": "$TargetDedicatedNodes=1",
        },
    },
    vm_size="STANDARD_D4")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := batch.NewPool(ctx, "pool", &batch.PoolArgs{
			AccountName: pulumi.String("sampleacct"),
			DeploymentConfiguration: &batch.DeploymentConfigurationArgs{
				VirtualMachineConfiguration: &batch.VirtualMachineConfigurationArgs{
					DataDisks: batch.DataDiskArray{
						&batch.DataDiskArgs{
							Caching:            batch.CachingTypeReadWrite,
							DiskSizeGB:         pulumi.Int(30),
							Lun:                pulumi.Int(0),
							StorageAccountType: batch.StorageAccountType_Premium_LRS,
						},
						&batch.DataDiskArgs{
							Caching:            batch.CachingTypeNone,
							DiskSizeGB:         pulumi.Int(200),
							Lun:                pulumi.Int(1),
							StorageAccountType: batch.StorageAccountType_Standard_LRS,
						},
					},
					DiskEncryptionConfiguration: &batch.DiskEncryptionConfigurationArgs{
						Targets: batch.DiskEncryptionTargetArray{
							batch.DiskEncryptionTargetOsDisk,
							batch.DiskEncryptionTargetTemporaryDisk,
						},
					},
					ImageReference: &batch.ImageReferenceArgs{
						Offer:     pulumi.String("WindowsServer"),
						Publisher: pulumi.String("MicrosoftWindowsServer"),
						Sku:       pulumi.String("2016-Datacenter-SmallDisk"),
						Version:   pulumi.String("latest"),
					},
					LicenseType:    pulumi.String("Windows_Server"),
					NodeAgentSkuId: pulumi.String("batch.node.windows amd64"),
					NodePlacementConfiguration: &batch.NodePlacementConfigurationArgs{
						Policy: batch.NodePlacementPolicyTypeZonal,
					},
					OsDisk: &batch.OSDiskArgs{
						EphemeralOSDiskSettings: &batch.DiffDiskSettingsArgs{
							Placement: batch.DiffDiskPlacementCacheDisk,
						},
					},
					WindowsConfiguration: &batch.WindowsConfigurationArgs{
						EnableAutomaticUpdates: pulumi.Bool(false),
					},
				},
			},
			NetworkConfiguration: &batch.NetworkConfigurationArgs{
				EndpointConfiguration: &batch.PoolEndpointConfigurationArgs{
					InboundNatPools: batch.InboundNatPoolArray{
						&batch.InboundNatPoolArgs{
							BackendPort:            pulumi.Int(12001),
							FrontendPortRangeEnd:   pulumi.Int(15100),
							FrontendPortRangeStart: pulumi.Int(15000),
							Name:                   pulumi.String("testnat"),
							NetworkSecurityGroupRules: batch.NetworkSecurityGroupRuleArray{
								&batch.NetworkSecurityGroupRuleArgs{
									Access:              batch.NetworkSecurityGroupRuleAccessAllow,
									Priority:            pulumi.Int(150),
									SourceAddressPrefix: pulumi.String("192.100.12.45"),
									SourcePortRanges: pulumi.StringArray{
										pulumi.String("1"),
										pulumi.String("2"),
									},
								},
								&batch.NetworkSecurityGroupRuleArgs{
									Access:              batch.NetworkSecurityGroupRuleAccessDeny,
									Priority:            pulumi.Int(3500),
									SourceAddressPrefix: pulumi.String("*"),
									SourcePortRanges: pulumi.StringArray{
										pulumi.String("*"),
									},
								},
							},
							Protocol: batch.InboundEndpointProtocolTCP,
						},
					},
				},
			},
			PoolName:          pulumi.String("testpool"),
			ResourceGroupName: pulumi.String("default-azurebatch-japaneast"),
			ScaleSettings: &batch.ScaleSettingsArgs{
				AutoScale: &batch.AutoScaleSettingsArgs{
					EvaluationInterval: pulumi.String("PT5M"),
					Formula:            pulumi.String("$TargetDedicatedNodes=1"),
				},
			},
			VmSize: pulumi.String("STANDARD_D4"),
		})
		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 pool = new AzureNative.Batch.Pool("pool", new()
    {
        AccountName = "sampleacct",
        DeploymentConfiguration = new AzureNative.Batch.Inputs.DeploymentConfigurationArgs
        {
            VirtualMachineConfiguration = new AzureNative.Batch.Inputs.VirtualMachineConfigurationArgs
            {
                DataDisks = new[]
                {
                    new AzureNative.Batch.Inputs.DataDiskArgs
                    {
                        Caching = AzureNative.Batch.CachingType.ReadWrite,
                        DiskSizeGB = 30,
                        Lun = 0,
                        StorageAccountType = AzureNative.Batch.StorageAccountType.Premium_LRS,
                    },
                    new AzureNative.Batch.Inputs.DataDiskArgs
                    {
                        Caching = AzureNative.Batch.CachingType.None,
                        DiskSizeGB = 200,
                        Lun = 1,
                        StorageAccountType = AzureNative.Batch.StorageAccountType.Standard_LRS,
                    },
                },
                DiskEncryptionConfiguration = new AzureNative.Batch.Inputs.DiskEncryptionConfigurationArgs
                {
                    Targets = new[]
                    {
                        AzureNative.Batch.DiskEncryptionTarget.OsDisk,
                        AzureNative.Batch.DiskEncryptionTarget.TemporaryDisk,
                    },
                },
                ImageReference = new AzureNative.Batch.Inputs.ImageReferenceArgs
                {
                    Offer = "WindowsServer",
                    Publisher = "MicrosoftWindowsServer",
                    Sku = "2016-Datacenter-SmallDisk",
                    Version = "latest",
                },
                LicenseType = "Windows_Server",
                NodeAgentSkuId = "batch.node.windows amd64",
                NodePlacementConfiguration = new AzureNative.Batch.Inputs.NodePlacementConfigurationArgs
                {
                    Policy = AzureNative.Batch.NodePlacementPolicyType.Zonal,
                },
                OsDisk = new AzureNative.Batch.Inputs.OSDiskArgs
                {
                    EphemeralOSDiskSettings = new AzureNative.Batch.Inputs.DiffDiskSettingsArgs
                    {
                        Placement = AzureNative.Batch.DiffDiskPlacement.CacheDisk,
                    },
                },
                WindowsConfiguration = new AzureNative.Batch.Inputs.WindowsConfigurationArgs
                {
                    EnableAutomaticUpdates = false,
                },
            },
        },
        NetworkConfiguration = new AzureNative.Batch.Inputs.NetworkConfigurationArgs
        {
            EndpointConfiguration = new AzureNative.Batch.Inputs.PoolEndpointConfigurationArgs
            {
                InboundNatPools = new[]
                {
                    new AzureNative.Batch.Inputs.InboundNatPoolArgs
                    {
                        BackendPort = 12001,
                        FrontendPortRangeEnd = 15100,
                        FrontendPortRangeStart = 15000,
                        Name = "testnat",
                        NetworkSecurityGroupRules = new[]
                        {
                            new AzureNative.Batch.Inputs.NetworkSecurityGroupRuleArgs
                            {
                                Access = AzureNative.Batch.NetworkSecurityGroupRuleAccess.Allow,
                                Priority = 150,
                                SourceAddressPrefix = "192.100.12.45",
                                SourcePortRanges = new[]
                                {
                                    "1",
                                    "2",
                                },
                            },
                            new AzureNative.Batch.Inputs.NetworkSecurityGroupRuleArgs
                            {
                                Access = AzureNative.Batch.NetworkSecurityGroupRuleAccess.Deny,
                                Priority = 3500,
                                SourceAddressPrefix = "*",
                                SourcePortRanges = new[]
                                {
                                    "*",
                                },
                            },
                        },
                        Protocol = AzureNative.Batch.InboundEndpointProtocol.TCP,
                    },
                },
            },
        },
        PoolName = "testpool",
        ResourceGroupName = "default-azurebatch-japaneast",
        ScaleSettings = new AzureNative.Batch.Inputs.ScaleSettingsArgs
        {
            AutoScale = new AzureNative.Batch.Inputs.AutoScaleSettingsArgs
            {
                EvaluationInterval = "PT5M",
                Formula = "$TargetDedicatedNodes=1",
            },
        },
        VmSize = "STANDARD_D4",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.batch.Pool;
import com.pulumi.azurenative.batch.PoolArgs;
import com.pulumi.azurenative.batch.inputs.DeploymentConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.VirtualMachineConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.DiskEncryptionConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.ImageReferenceArgs;
import com.pulumi.azurenative.batch.inputs.NodePlacementConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.OSDiskArgs;
import com.pulumi.azurenative.batch.inputs.DiffDiskSettingsArgs;
import com.pulumi.azurenative.batch.inputs.WindowsConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.NetworkConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.PoolEndpointConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.ScaleSettingsArgs;
import com.pulumi.azurenative.batch.inputs.AutoScaleSettingsArgs;
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 pool = new Pool("pool", PoolArgs.builder()
            .accountName("sampleacct")
            .deploymentConfiguration(DeploymentConfigurationArgs.builder()
                .virtualMachineConfiguration(VirtualMachineConfigurationArgs.builder()
                    .dataDisks(                    
                        DataDiskArgs.builder()
                            .caching("ReadWrite")
                            .diskSizeGB(30)
                            .lun(0)
                            .storageAccountType("Premium_LRS")
                            .build(),
                        DataDiskArgs.builder()
                            .caching("None")
                            .diskSizeGB(200)
                            .lun(1)
                            .storageAccountType("Standard_LRS")
                            .build())
                    .diskEncryptionConfiguration(DiskEncryptionConfigurationArgs.builder()
                        .targets(                        
                            "OsDisk",
                            "TemporaryDisk")
                        .build())
                    .imageReference(ImageReferenceArgs.builder()
                        .offer("WindowsServer")
                        .publisher("MicrosoftWindowsServer")
                        .sku("2016-Datacenter-SmallDisk")
                        .version("latest")
                        .build())
                    .licenseType("Windows_Server")
                    .nodeAgentSkuId("batch.node.windows amd64")
                    .nodePlacementConfiguration(NodePlacementConfigurationArgs.builder()
                        .policy("Zonal")
                        .build())
                    .osDisk(OSDiskArgs.builder()
                        .ephemeralOSDiskSettings(DiffDiskSettingsArgs.builder()
                            .placement("CacheDisk")
                            .build())
                        .build())
                    .windowsConfiguration(WindowsConfigurationArgs.builder()
                        .enableAutomaticUpdates(false)
                        .build())
                    .build())
                .build())
            .networkConfiguration(NetworkConfigurationArgs.builder()
                .endpointConfiguration(PoolEndpointConfigurationArgs.builder()
                    .inboundNatPools(InboundNatPoolArgs.builder()
                        .backendPort(12001)
                        .frontendPortRangeEnd(15100)
                        .frontendPortRangeStart(15000)
                        .name("testnat")
                        .networkSecurityGroupRules(                        
                            NetworkSecurityGroupRuleArgs.builder()
                                .access("Allow")
                                .priority(150)
                                .sourceAddressPrefix("192.100.12.45")
                                .sourcePortRanges(                                
                                    "1",
                                    "2")
                                .build(),
                            NetworkSecurityGroupRuleArgs.builder()
                                .access("Deny")
                                .priority(3500)
                                .sourceAddressPrefix("*")
                                .sourcePortRanges("*")
                                .build())
                        .protocol("TCP")
                        .build())
                    .build())
                .build())
            .poolName("testpool")
            .resourceGroupName("default-azurebatch-japaneast")
            .scaleSettings(ScaleSettingsArgs.builder()
                .autoScale(AutoScaleSettingsArgs.builder()
                    .evaluationInterval("PT5M")
                    .formula("$TargetDedicatedNodes=1")
                    .build())
                .build())
            .vmSize("STANDARD_D4")
            .build());

    }
}
resources:
  pool:
    type: azure-native:batch:Pool
    properties:
      accountName: sampleacct
      deploymentConfiguration:
        virtualMachineConfiguration:
          dataDisks:
            - caching: ReadWrite
              diskSizeGB: 30
              lun: 0
              storageAccountType: Premium_LRS
            - caching: None
              diskSizeGB: 200
              lun: 1
              storageAccountType: Standard_LRS
          diskEncryptionConfiguration:
            targets:
              - OsDisk
              - TemporaryDisk
          imageReference:
            offer: WindowsServer
            publisher: MicrosoftWindowsServer
            sku: 2016-Datacenter-SmallDisk
            version: latest
          licenseType: Windows_Server
          nodeAgentSkuId: batch.node.windows amd64
          nodePlacementConfiguration:
            policy: Zonal
          osDisk:
            ephemeralOSDiskSettings:
              placement: CacheDisk
          windowsConfiguration:
            enableAutomaticUpdates: false
      networkConfiguration:
        endpointConfiguration:
          inboundNatPools:
            - backendPort: 12001
              frontendPortRangeEnd: 15100
              frontendPortRangeStart: 15000
              name: testnat
              networkSecurityGroupRules:
                - access: Allow
                  priority: 150
                  sourceAddressPrefix: 192.100.12.45
                  sourcePortRanges:
                    - '1'
                    - '2'
                - access: Deny
                  priority: 3500
                  sourceAddressPrefix: '*'
                  sourcePortRanges:
                    - '*'
              protocol: TCP
      poolName: testpool
      resourceGroupName: default-azurebatch-japaneast
      scaleSettings:
        autoScale:
          evaluationInterval: PT5M
          formula: $TargetDedicatedNodes=1
      vmSize: STANDARD_D4

The dataDisks array attaches persistent storage to each node. The diskEncryptionConfiguration encrypts OS and temporary disks. The endpointConfiguration defines inbound NAT pools with network security group rules that control which ports and source IPs can reach pool nodes.

Enable accelerated networking for high throughput

Workloads with high network throughput benefit from SR-IOV acceleration, which bypasses the host networking stack.

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

const pool = new azure_native.batch.Pool("pool", {
    accountName: "sampleacct",
    deploymentConfiguration: {
        virtualMachineConfiguration: {
            imageReference: {
                offer: "WindowsServer",
                publisher: "MicrosoftWindowsServer",
                sku: "2016-datacenter-smalldisk",
                version: "latest",
            },
            nodeAgentSkuId: "batch.node.windows amd64",
        },
    },
    networkConfiguration: {
        enableAcceleratedNetworking: true,
        subnetId: "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123",
    },
    poolName: "testpool",
    resourceGroupName: "default-azurebatch-japaneast",
    scaleSettings: {
        fixedScale: {
            targetDedicatedNodes: 1,
            targetLowPriorityNodes: 0,
        },
    },
    vmSize: "STANDARD_D1_V2",
});
import pulumi
import pulumi_azure_native as azure_native

pool = azure_native.batch.Pool("pool",
    account_name="sampleacct",
    deployment_configuration={
        "virtual_machine_configuration": {
            "image_reference": {
                "offer": "WindowsServer",
                "publisher": "MicrosoftWindowsServer",
                "sku": "2016-datacenter-smalldisk",
                "version": "latest",
            },
            "node_agent_sku_id": "batch.node.windows amd64",
        },
    },
    network_configuration={
        "enable_accelerated_networking": True,
        "subnet_id": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123",
    },
    pool_name="testpool",
    resource_group_name="default-azurebatch-japaneast",
    scale_settings={
        "fixed_scale": {
            "target_dedicated_nodes": 1,
            "target_low_priority_nodes": 0,
        },
    },
    vm_size="STANDARD_D1_V2")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := batch.NewPool(ctx, "pool", &batch.PoolArgs{
			AccountName: pulumi.String("sampleacct"),
			DeploymentConfiguration: &batch.DeploymentConfigurationArgs{
				VirtualMachineConfiguration: &batch.VirtualMachineConfigurationArgs{
					ImageReference: &batch.ImageReferenceArgs{
						Offer:     pulumi.String("WindowsServer"),
						Publisher: pulumi.String("MicrosoftWindowsServer"),
						Sku:       pulumi.String("2016-datacenter-smalldisk"),
						Version:   pulumi.String("latest"),
					},
					NodeAgentSkuId: pulumi.String("batch.node.windows amd64"),
				},
			},
			NetworkConfiguration: &batch.NetworkConfigurationArgs{
				EnableAcceleratedNetworking: pulumi.Bool(true),
				SubnetId:                    pulumi.String("/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123"),
			},
			PoolName:          pulumi.String("testpool"),
			ResourceGroupName: pulumi.String("default-azurebatch-japaneast"),
			ScaleSettings: &batch.ScaleSettingsArgs{
				FixedScale: &batch.FixedScaleSettingsArgs{
					TargetDedicatedNodes:   pulumi.Int(1),
					TargetLowPriorityNodes: pulumi.Int(0),
				},
			},
			VmSize: pulumi.String("STANDARD_D1_V2"),
		})
		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 pool = new AzureNative.Batch.Pool("pool", new()
    {
        AccountName = "sampleacct",
        DeploymentConfiguration = new AzureNative.Batch.Inputs.DeploymentConfigurationArgs
        {
            VirtualMachineConfiguration = new AzureNative.Batch.Inputs.VirtualMachineConfigurationArgs
            {
                ImageReference = new AzureNative.Batch.Inputs.ImageReferenceArgs
                {
                    Offer = "WindowsServer",
                    Publisher = "MicrosoftWindowsServer",
                    Sku = "2016-datacenter-smalldisk",
                    Version = "latest",
                },
                NodeAgentSkuId = "batch.node.windows amd64",
            },
        },
        NetworkConfiguration = new AzureNative.Batch.Inputs.NetworkConfigurationArgs
        {
            EnableAcceleratedNetworking = true,
            SubnetId = "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123",
        },
        PoolName = "testpool",
        ResourceGroupName = "default-azurebatch-japaneast",
        ScaleSettings = new AzureNative.Batch.Inputs.ScaleSettingsArgs
        {
            FixedScale = new AzureNative.Batch.Inputs.FixedScaleSettingsArgs
            {
                TargetDedicatedNodes = 1,
                TargetLowPriorityNodes = 0,
            },
        },
        VmSize = "STANDARD_D1_V2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.batch.Pool;
import com.pulumi.azurenative.batch.PoolArgs;
import com.pulumi.azurenative.batch.inputs.DeploymentConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.VirtualMachineConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.ImageReferenceArgs;
import com.pulumi.azurenative.batch.inputs.NetworkConfigurationArgs;
import com.pulumi.azurenative.batch.inputs.ScaleSettingsArgs;
import com.pulumi.azurenative.batch.inputs.FixedScaleSettingsArgs;
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 pool = new Pool("pool", PoolArgs.builder()
            .accountName("sampleacct")
            .deploymentConfiguration(DeploymentConfigurationArgs.builder()
                .virtualMachineConfiguration(VirtualMachineConfigurationArgs.builder()
                    .imageReference(ImageReferenceArgs.builder()
                        .offer("WindowsServer")
                        .publisher("MicrosoftWindowsServer")
                        .sku("2016-datacenter-smalldisk")
                        .version("latest")
                        .build())
                    .nodeAgentSkuId("batch.node.windows amd64")
                    .build())
                .build())
            .networkConfiguration(NetworkConfigurationArgs.builder()
                .enableAcceleratedNetworking(true)
                .subnetId("/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123")
                .build())
            .poolName("testpool")
            .resourceGroupName("default-azurebatch-japaneast")
            .scaleSettings(ScaleSettingsArgs.builder()
                .fixedScale(FixedScaleSettingsArgs.builder()
                    .targetDedicatedNodes(1)
                    .targetLowPriorityNodes(0)
                    .build())
                .build())
            .vmSize("STANDARD_D1_V2")
            .build());

    }
}
resources:
  pool:
    type: azure-native:batch:Pool
    properties:
      accountName: sampleacct
      deploymentConfiguration:
        virtualMachineConfiguration:
          imageReference:
            offer: WindowsServer
            publisher: MicrosoftWindowsServer
            sku: 2016-datacenter-smalldisk
            version: latest
          nodeAgentSkuId: batch.node.windows amd64
      networkConfiguration:
        enableAcceleratedNetworking: true
        subnetId: /subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg1234/providers/Microsoft.Network/virtualNetworks/network1234/subnets/subnet123
      poolName: testpool
      resourceGroupName: default-azurebatch-japaneast
      scaleSettings:
        fixedScale:
          targetDedicatedNodes: 1
          targetLowPriorityNodes: 0
      vmSize: STANDARD_D1_V2

The enableAcceleratedNetworking property enables SR-IOV on supported VM sizes. This reduces latency and increases bandwidth for network-intensive tasks. The VM size must support accelerated networking, and nodes must be placed in a VNet subnet.

Beyond these examples

These snippets focus on specific pool-level features: image selection and node agent configuration, scaling strategies and resource tagging, network isolation and security, and storage and encryption. They’re intentionally minimal rather than full Batch deployments.

The examples may reference pre-existing infrastructure such as Batch accounts and resource groups, VNets, subnets, and public IP addresses, and Azure Compute Gallery images. They focus on configuring the pool rather than provisioning everything around it.

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

  • Start tasks and application packages
  • User accounts and certificates
  • Mount configurations (Azure Files, NFS, Blobfuse)
  • VM extensions and service artifacts
  • Upgrade policies and OS update controls
  • Task scheduling policies and inter-node communication

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

Let's deploy Azure Batch Pools

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Image & VM Configuration
What are the two ways to specify a VM image for my pool?
You can use a custom image by setting imageReference.id to a full Azure Compute Gallery image resource ID, or use a marketplace image by specifying publisher, offer, sku, and version fields.
What's the purpose of nodeAgentSkuId?
The nodeAgentSkuId identifies the Batch node agent SKU that matches your OS (e.g., batch.node.ubuntu 18.04 or batch.node.windows amd64). It’s required for all VM configurations.
Scaling & Node Management
What are the scaling options for pools?
You can use fixedScale for static sizing with targetDedicatedNodes and targetLowPriorityNodes, or autoScale for dynamic sizing with a formula and evaluationInterval (e.g., PT5M for 5 minutes).
What's the default and maximum for taskSlotsPerNode?
The default is 1. The maximum is the smaller of 4 times the number of VM cores or 256.
Networking & Connectivity
What are my options for public IP addresses on pool nodes?
You can disable public IPs by setting publicIPAddressConfiguration.provision to NoPublicIPAddresses, or use your own by setting it to UserManaged and providing ipAddressIds.
How do I enable accelerated networking for my pool?
Set networkConfiguration.enableAcceleratedNetworking to true and provide a subnetId for VNet integration.
What does interNodeCommunication control?
Setting interNodeCommunication to Enabled allows direct communication between nodes but may reduce node allocation chances. The default is Disabled.
Security & Compliance
Why shouldn't I use the certificates property?
The certificates property is deprecated and will be removed after February 2024. Use the Azure KeyVault Extension instead for certificate management.
How do I enable disk encryption for pool nodes?
Configure diskEncryptionConfiguration.targets with values like OsDisk and TemporaryDisk in the virtualMachineConfiguration.
Upgrades & Maintenance
How do I configure automatic OS upgrades?
Set upgradePolicy.mode to Automatic and configure automaticOSUpgradePolicy with options like enableAutomaticOSUpgrade and useRollingUpgradePolicy.
Can I control Windows automatic updates separately?
Yes, use windowsConfiguration.enableAutomaticUpdates to control Windows Update behavior independently of the pool’s upgrade policy.
Advanced Features
How do I add VM extensions to pool nodes?
Configure virtualMachineConfiguration.extensions with extension details like name, publisher, type, and settings (e.g., KeyVault extension).
When can I use resourceTags to tag backing Azure resources?
You can only use resourceTags when the Batch account was created with poolAllocationMode set to UserSubscription.

Using a different cloud?

Explore compute guides for other cloud providers: