Configure Azure Kusto Sandbox Custom Images

The azure-native:kusto:SandboxCustomImage resource, part of the Pulumi Azure Native provider, defines custom sandbox images for Azure Data Explorer clusters: the language runtime, base image, and package dependencies. This guide focuses on three capabilities: language version specification, custom and managed base image selection, and package installation via requirements files.

Custom images belong to Kusto clusters and may reference existing custom images as base layers. The examples are intentionally small. Combine them with your own cluster infrastructure and package requirements.

Create a custom image with a specific language version

Data exploration workloads often require specific Python versions and packages that aren’t available in the default Kusto sandbox environment. Custom images let you define the exact runtime environment your queries will execute in.

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

const sandboxCustomImage = new azure_native.kusto.SandboxCustomImage("sandboxCustomImage", {
    clusterName: "kustoCluster",
    language: azure_native.kusto.Language.Python,
    languageVersion: "3.10.8",
    requirementsFileContent: "Requests",
    resourceGroupName: "kustorptest",
    sandboxCustomImageName: "customImage8",
});
import pulumi
import pulumi_azure_native as azure_native

sandbox_custom_image = azure_native.kusto.SandboxCustomImage("sandboxCustomImage",
    cluster_name="kustoCluster",
    language=azure_native.kusto.Language.PYTHON,
    language_version="3.10.8",
    requirements_file_content="Requests",
    resource_group_name="kustorptest",
    sandbox_custom_image_name="customImage8")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := kusto.NewSandboxCustomImage(ctx, "sandboxCustomImage", &kusto.SandboxCustomImageArgs{
			ClusterName:             pulumi.String("kustoCluster"),
			Language:                pulumi.String(kusto.LanguagePython),
			LanguageVersion:         pulumi.String("3.10.8"),
			RequirementsFileContent: pulumi.String("Requests"),
			ResourceGroupName:       pulumi.String("kustorptest"),
			SandboxCustomImageName:  pulumi.String("customImage8"),
		})
		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 sandboxCustomImage = new AzureNative.Kusto.SandboxCustomImage("sandboxCustomImage", new()
    {
        ClusterName = "kustoCluster",
        Language = AzureNative.Kusto.Language.Python,
        LanguageVersion = "3.10.8",
        RequirementsFileContent = "Requests",
        ResourceGroupName = "kustorptest",
        SandboxCustomImageName = "customImage8",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.kusto.SandboxCustomImage;
import com.pulumi.azurenative.kusto.SandboxCustomImageArgs;
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 sandboxCustomImage = new SandboxCustomImage("sandboxCustomImage", SandboxCustomImageArgs.builder()
            .clusterName("kustoCluster")
            .language("Python")
            .languageVersion("3.10.8")
            .requirementsFileContent("Requests")
            .resourceGroupName("kustorptest")
            .sandboxCustomImageName("customImage8")
            .build());

    }
}
resources:
  sandboxCustomImage:
    type: azure-native:kusto:SandboxCustomImage
    properties:
      clusterName: kustoCluster
      language: Python
      languageVersion: 3.10.8
      requirementsFileContent: Requests
      resourceGroupName: kustorptest
      sandboxCustomImageName: customImage8

When you specify languageVersion, Kusto builds the image from that exact Python release. The requirementsFileContent property accepts pip requirements syntax (here, just “Requests”), which Kusto installs during image creation. The image becomes available for queries running in the specified cluster’s sandbox.

Layer packages on top of an existing custom image

Teams building multiple related environments can create a base custom image with common dependencies, then derive specialized images that add incremental packages.

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

const sandboxCustomImage = new azure_native.kusto.SandboxCustomImage("sandboxCustomImage", {
    baseImageName: "customImage1",
    clusterName: "kustoCluster",
    language: azure_native.kusto.Language.Python,
    requirementsFileContent: "Requests",
    resourceGroupName: "kustorptest",
    sandboxCustomImageName: "customImage2",
});
import pulumi
import pulumi_azure_native as azure_native

sandbox_custom_image = azure_native.kusto.SandboxCustomImage("sandboxCustomImage",
    base_image_name="customImage1",
    cluster_name="kustoCluster",
    language=azure_native.kusto.Language.PYTHON,
    requirements_file_content="Requests",
    resource_group_name="kustorptest",
    sandbox_custom_image_name="customImage2")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := kusto.NewSandboxCustomImage(ctx, "sandboxCustomImage", &kusto.SandboxCustomImageArgs{
			BaseImageName:           pulumi.String("customImage1"),
			ClusterName:             pulumi.String("kustoCluster"),
			Language:                pulumi.String(kusto.LanguagePython),
			RequirementsFileContent: pulumi.String("Requests"),
			ResourceGroupName:       pulumi.String("kustorptest"),
			SandboxCustomImageName:  pulumi.String("customImage2"),
		})
		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 sandboxCustomImage = new AzureNative.Kusto.SandboxCustomImage("sandboxCustomImage", new()
    {
        BaseImageName = "customImage1",
        ClusterName = "kustoCluster",
        Language = AzureNative.Kusto.Language.Python,
        RequirementsFileContent = "Requests",
        ResourceGroupName = "kustorptest",
        SandboxCustomImageName = "customImage2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.kusto.SandboxCustomImage;
import com.pulumi.azurenative.kusto.SandboxCustomImageArgs;
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 sandboxCustomImage = new SandboxCustomImage("sandboxCustomImage", SandboxCustomImageArgs.builder()
            .baseImageName("customImage1")
            .clusterName("kustoCluster")
            .language("Python")
            .requirementsFileContent("Requests")
            .resourceGroupName("kustorptest")
            .sandboxCustomImageName("customImage2")
            .build());

    }
}
resources:
  sandboxCustomImage:
    type: azure-native:kusto:SandboxCustomImage
    properties:
      baseImageName: customImage1
      clusterName: kustoCluster
      language: Python
      requirementsFileContent: Requests
      resourceGroupName: kustorptest
      sandboxCustomImageName: customImage2

The baseImageName property references an existing custom image rather than a language version. Kusto layers the new requirements on top of the base image’s environment. This approach reduces build time and ensures consistency across related images.

Start from a managed base image

Azure Data Explorer provides managed base images with pre-configured language versions. These images serve as stable starting points for custom environments.

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

const sandboxCustomImage = new azure_native.kusto.SandboxCustomImage("sandboxCustomImage", {
    baseImageName: "Python3_10_8",
    clusterName: "kustoCluster",
    language: azure_native.kusto.Language.Python,
    requirementsFileContent: "Requests",
    resourceGroupName: "kustorptest",
    sandboxCustomImageName: "customImage2",
});
import pulumi
import pulumi_azure_native as azure_native

sandbox_custom_image = azure_native.kusto.SandboxCustomImage("sandboxCustomImage",
    base_image_name="Python3_10_8",
    cluster_name="kustoCluster",
    language=azure_native.kusto.Language.PYTHON,
    requirements_file_content="Requests",
    resource_group_name="kustorptest",
    sandbox_custom_image_name="customImage2")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := kusto.NewSandboxCustomImage(ctx, "sandboxCustomImage", &kusto.SandboxCustomImageArgs{
			BaseImageName:           pulumi.String("Python3_10_8"),
			ClusterName:             pulumi.String("kustoCluster"),
			Language:                pulumi.String(kusto.LanguagePython),
			RequirementsFileContent: pulumi.String("Requests"),
			ResourceGroupName:       pulumi.String("kustorptest"),
			SandboxCustomImageName:  pulumi.String("customImage2"),
		})
		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 sandboxCustomImage = new AzureNative.Kusto.SandboxCustomImage("sandboxCustomImage", new()
    {
        BaseImageName = "Python3_10_8",
        ClusterName = "kustoCluster",
        Language = AzureNative.Kusto.Language.Python,
        RequirementsFileContent = "Requests",
        ResourceGroupName = "kustorptest",
        SandboxCustomImageName = "customImage2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.kusto.SandboxCustomImage;
import com.pulumi.azurenative.kusto.SandboxCustomImageArgs;
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 sandboxCustomImage = new SandboxCustomImage("sandboxCustomImage", SandboxCustomImageArgs.builder()
            .baseImageName("Python3_10_8")
            .clusterName("kustoCluster")
            .language("Python")
            .requirementsFileContent("Requests")
            .resourceGroupName("kustorptest")
            .sandboxCustomImageName("customImage2")
            .build());

    }
}
resources:
  sandboxCustomImage:
    type: azure-native:kusto:SandboxCustomImage
    properties:
      baseImageName: Python3_10_8
      clusterName: kustoCluster
      language: Python
      requirementsFileContent: Requests
      resourceGroupName: kustorptest
      sandboxCustomImageName: customImage2

Managed base images like “Python3_10_8” are maintained by Azure and include common data science libraries. You reference them by name in baseImageName, then add your own packages via requirementsFileContent. This combines Azure’s curated environments with your specific dependencies.

Beyond these examples

These snippets focus on specific custom image features: language version specification, custom and managed base images, and requirements file content for package installation. They’re intentionally minimal rather than full data exploration environments.

The examples may reference pre-existing infrastructure such as Kusto clusters, resource groups, and existing custom images for layering scenarios. They focus on configuring the custom image rather than provisioning the cluster infrastructure.

To keep things focused, common custom image patterns are omitted, including:

  • Image lifecycle management and updates
  • Multi-language image configurations
  • Image validation and testing workflows
  • Resource tagging and metadata

These omissions are intentional: the goal is to illustrate how each custom image feature is wired, not provide drop-in data exploration modules. See the SandboxCustomImage resource reference for all available configuration options.

Let's configure Azure Kusto Sandbox Custom Images

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Image Configuration
Should I use baseImageName or languageVersion to configure my custom image?
You must specify exactly one of these properties, not both. Use baseImageName to build on an existing image (either a managed base image like Python3_10_8 or another custom image), or use languageVersion (e.g., 3.10.8) to specify the language version directly.
What values can I use for baseImageName?
You can use either a LanguageExtensionImageName (managed base images like Python3_10_8 or Python3_10_8_DL) or the name of an existing custom image you’ve already created.
What's the difference between building on a managed base image versus a custom image?
Managed base images (like Python3_10_8) are predefined by Azure Kusto, while custom images are ones you’ve created previously. Both are specified using baseImageName, just with different values.
Dependencies & Packages
How do I add Python packages to my custom image?
Use the requirementsFileContent property to specify your dependencies (e.g., Requests as shown in the examples).
Resource Properties
What properties can't be changed after creating the custom image?
The clusterName, resourceGroupName, and sandboxCustomImageName properties are immutable and cannot be changed after creation.

Using a different cloud?

Explore analytics guides for other cloud providers: