Deploy GCP Notebook Instances

The gcp:notebooks/instance:Instance resource, part of the Pulumi GCP provider, provisions AI Platform Notebook instances for interactive data science and ML development. This resource is maintained for backwards compatibility; for new projects, use gcp.workbench.Instance. This guide focuses on three capabilities: VM and container image deployment, GPU acceleration, and private networking with encryption.

Notebook instances run in VPC networks and may reference service accounts, KMS keys, and GPU quotas that must exist separately. The examples are intentionally small. Combine them with your own VPC, IAM, and encryption infrastructure.

Launch a notebook with VM image and machine type

Most deployments start with a managed VM image, a machine type, and a zone to create a running instance.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const instance = new gcp.notebooks.Instance("instance", {
    name: "notebooks-instance",
    location: "us-west1-a",
    machineType: "e2-medium",
    vmImage: {
        project: "cloud-notebooks-managed",
        imageFamily: "workbench-instances",
    },
});
import pulumi
import pulumi_gcp as gcp

instance = gcp.notebooks.Instance("instance",
    name="notebooks-instance",
    location="us-west1-a",
    machine_type="e2-medium",
    vm_image={
        "project": "cloud-notebooks-managed",
        "image_family": "workbench-instances",
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/notebooks"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := notebooks.NewInstance(ctx, "instance", &notebooks.InstanceArgs{
			Name:        pulumi.String("notebooks-instance"),
			Location:    pulumi.String("us-west1-a"),
			MachineType: pulumi.String("e2-medium"),
			VmImage: &notebooks.InstanceVmImageArgs{
				Project:     pulumi.String("cloud-notebooks-managed"),
				ImageFamily: pulumi.String("workbench-instances"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var instance = new Gcp.Notebooks.Instance("instance", new()
    {
        Name = "notebooks-instance",
        Location = "us-west1-a",
        MachineType = "e2-medium",
        VmImage = new Gcp.Notebooks.Inputs.InstanceVmImageArgs
        {
            Project = "cloud-notebooks-managed",
            ImageFamily = "workbench-instances",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.notebooks.Instance;
import com.pulumi.gcp.notebooks.InstanceArgs;
import com.pulumi.gcp.notebooks.inputs.InstanceVmImageArgs;
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 instance = new Instance("instance", InstanceArgs.builder()
            .name("notebooks-instance")
            .location("us-west1-a")
            .machineType("e2-medium")
            .vmImage(InstanceVmImageArgs.builder()
                .project("cloud-notebooks-managed")
                .imageFamily("workbench-instances")
                .build())
            .build());

    }
}
resources:
  instance:
    type: gcp:notebooks:Instance
    properties:
      name: notebooks-instance
      location: us-west1-a
      machineType: e2-medium
      vmImage:
        project: cloud-notebooks-managed
        imageFamily: workbench-instances

The vmImage property specifies the base environment using a project and imageFamily. The machineType determines CPU and memory resources. The location places the instance in a specific zone. Without explicit networking configuration, the instance uses the default VPC.

Control instance state at creation time

Teams provisioning notebooks for scheduled workloads often create instances in a stopped state to avoid immediate compute charges.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const instance = new gcp.notebooks.Instance("instance", {
    name: "notebooks-instance",
    location: "us-west1-a",
    machineType: "e2-medium",
    vmImage: {
        project: "cloud-notebooks-managed",
        imageFamily: "workbench-instances",
    },
    desiredState: "STOPPED",
});
import pulumi
import pulumi_gcp as gcp

instance = gcp.notebooks.Instance("instance",
    name="notebooks-instance",
    location="us-west1-a",
    machine_type="e2-medium",
    vm_image={
        "project": "cloud-notebooks-managed",
        "image_family": "workbench-instances",
    },
    desired_state="STOPPED")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/notebooks"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := notebooks.NewInstance(ctx, "instance", &notebooks.InstanceArgs{
			Name:        pulumi.String("notebooks-instance"),
			Location:    pulumi.String("us-west1-a"),
			MachineType: pulumi.String("e2-medium"),
			VmImage: &notebooks.InstanceVmImageArgs{
				Project:     pulumi.String("cloud-notebooks-managed"),
				ImageFamily: pulumi.String("workbench-instances"),
			},
			DesiredState: pulumi.String("STOPPED"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var instance = new Gcp.Notebooks.Instance("instance", new()
    {
        Name = "notebooks-instance",
        Location = "us-west1-a",
        MachineType = "e2-medium",
        VmImage = new Gcp.Notebooks.Inputs.InstanceVmImageArgs
        {
            Project = "cloud-notebooks-managed",
            ImageFamily = "workbench-instances",
        },
        DesiredState = "STOPPED",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.notebooks.Instance;
import com.pulumi.gcp.notebooks.InstanceArgs;
import com.pulumi.gcp.notebooks.inputs.InstanceVmImageArgs;
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 instance = new Instance("instance", InstanceArgs.builder()
            .name("notebooks-instance")
            .location("us-west1-a")
            .machineType("e2-medium")
            .vmImage(InstanceVmImageArgs.builder()
                .project("cloud-notebooks-managed")
                .imageFamily("workbench-instances")
                .build())
            .desiredState("STOPPED")
            .build());

    }
}
resources:
  instance:
    type: gcp:notebooks:Instance
    properties:
      name: notebooks-instance
      location: us-west1-a
      machineType: e2-medium
      vmImage:
        project: cloud-notebooks-managed
        imageFamily: workbench-instances
      desiredState: STOPPED

The desiredState property controls whether the instance starts immediately. Set it to STOPPED to provision without starting, or ACTIVE to launch. This extends the basic configuration with lifecycle control.

Deploy from a container image repository

Custom environments with specific libraries often use container images rather than VM images.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const instance = new gcp.notebooks.Instance("instance", {
    name: "notebooks-instance",
    location: "us-west1-a",
    machineType: "e2-medium",
    metadata: {
        "proxy-mode": "service_account",
    },
    containerImage: {
        repository: "gcr.io/deeplearning-platform-release/base-cpu",
        tag: "latest",
    },
});
import pulumi
import pulumi_gcp as gcp

instance = gcp.notebooks.Instance("instance",
    name="notebooks-instance",
    location="us-west1-a",
    machine_type="e2-medium",
    metadata={
        "proxy-mode": "service_account",
    },
    container_image={
        "repository": "gcr.io/deeplearning-platform-release/base-cpu",
        "tag": "latest",
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/notebooks"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := notebooks.NewInstance(ctx, "instance", &notebooks.InstanceArgs{
			Name:        pulumi.String("notebooks-instance"),
			Location:    pulumi.String("us-west1-a"),
			MachineType: pulumi.String("e2-medium"),
			Metadata: pulumi.StringMap{
				"proxy-mode": pulumi.String("service_account"),
			},
			ContainerImage: &notebooks.InstanceContainerImageArgs{
				Repository: pulumi.String("gcr.io/deeplearning-platform-release/base-cpu"),
				Tag:        pulumi.String("latest"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var instance = new Gcp.Notebooks.Instance("instance", new()
    {
        Name = "notebooks-instance",
        Location = "us-west1-a",
        MachineType = "e2-medium",
        Metadata = 
        {
            { "proxy-mode", "service_account" },
        },
        ContainerImage = new Gcp.Notebooks.Inputs.InstanceContainerImageArgs
        {
            Repository = "gcr.io/deeplearning-platform-release/base-cpu",
            Tag = "latest",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.notebooks.Instance;
import com.pulumi.gcp.notebooks.InstanceArgs;
import com.pulumi.gcp.notebooks.inputs.InstanceContainerImageArgs;
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 instance = new Instance("instance", InstanceArgs.builder()
            .name("notebooks-instance")
            .location("us-west1-a")
            .machineType("e2-medium")
            .metadata(Map.of("proxy-mode", "service_account"))
            .containerImage(InstanceContainerImageArgs.builder()
                .repository("gcr.io/deeplearning-platform-release/base-cpu")
                .tag("latest")
                .build())
            .build());

    }
}
resources:
  instance:
    type: gcp:notebooks:Instance
    properties:
      name: notebooks-instance
      location: us-west1-a
      machineType: e2-medium
      metadata:
        proxy-mode: service_account
      containerImage:
        repository: gcr.io/deeplearning-platform-release/base-cpu
        tag: latest

The containerImage property replaces vmImage, pointing to a container repository and tag. The metadata property configures proxy mode for authentication. This approach gives you full control over the runtime environment through Docker images.

Attach GPU accelerators for ML workloads

Machine learning training benefits from GPU acceleration, which notebooks enable through accelerator configuration.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const instance = new gcp.notebooks.Instance("instance", {
    name: "notebooks-instance",
    location: "us-west1-a",
    machineType: "n1-standard-1",
    installGpuDriver: true,
    acceleratorConfig: {
        type: "NVIDIA_TESLA_T4",
        coreCount: 1,
    },
    vmImage: {
        project: "cloud-notebooks-managed",
        imageFamily: "workbench-instances",
    },
});
import pulumi
import pulumi_gcp as gcp

instance = gcp.notebooks.Instance("instance",
    name="notebooks-instance",
    location="us-west1-a",
    machine_type="n1-standard-1",
    install_gpu_driver=True,
    accelerator_config={
        "type": "NVIDIA_TESLA_T4",
        "core_count": 1,
    },
    vm_image={
        "project": "cloud-notebooks-managed",
        "image_family": "workbench-instances",
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/notebooks"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := notebooks.NewInstance(ctx, "instance", &notebooks.InstanceArgs{
			Name:             pulumi.String("notebooks-instance"),
			Location:         pulumi.String("us-west1-a"),
			MachineType:      pulumi.String("n1-standard-1"),
			InstallGpuDriver: pulumi.Bool(true),
			AcceleratorConfig: &notebooks.InstanceAcceleratorConfigArgs{
				Type:      pulumi.String("NVIDIA_TESLA_T4"),
				CoreCount: pulumi.Int(1),
			},
			VmImage: &notebooks.InstanceVmImageArgs{
				Project:     pulumi.String("cloud-notebooks-managed"),
				ImageFamily: pulumi.String("workbench-instances"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var instance = new Gcp.Notebooks.Instance("instance", new()
    {
        Name = "notebooks-instance",
        Location = "us-west1-a",
        MachineType = "n1-standard-1",
        InstallGpuDriver = true,
        AcceleratorConfig = new Gcp.Notebooks.Inputs.InstanceAcceleratorConfigArgs
        {
            Type = "NVIDIA_TESLA_T4",
            CoreCount = 1,
        },
        VmImage = new Gcp.Notebooks.Inputs.InstanceVmImageArgs
        {
            Project = "cloud-notebooks-managed",
            ImageFamily = "workbench-instances",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.notebooks.Instance;
import com.pulumi.gcp.notebooks.InstanceArgs;
import com.pulumi.gcp.notebooks.inputs.InstanceAcceleratorConfigArgs;
import com.pulumi.gcp.notebooks.inputs.InstanceVmImageArgs;
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 instance = new Instance("instance", InstanceArgs.builder()
            .name("notebooks-instance")
            .location("us-west1-a")
            .machineType("n1-standard-1")
            .installGpuDriver(true)
            .acceleratorConfig(InstanceAcceleratorConfigArgs.builder()
                .type("NVIDIA_TESLA_T4")
                .coreCount(1)
                .build())
            .vmImage(InstanceVmImageArgs.builder()
                .project("cloud-notebooks-managed")
                .imageFamily("workbench-instances")
                .build())
            .build());

    }
}
resources:
  instance:
    type: gcp:notebooks:Instance
    properties:
      name: notebooks-instance
      location: us-west1-a
      machineType: n1-standard-1
      installGpuDriver: true
      acceleratorConfig:
        type: NVIDIA_TESLA_T4
        coreCount: 1
      vmImage:
        project: cloud-notebooks-managed
        imageFamily: workbench-instances

The acceleratorConfig property specifies the GPU type and count. The installGpuDriver property authorizes automatic driver installation. The machineType must support the chosen accelerator; not all machine types work with all GPU types.

Configure networking, encryption, and access controls

Production deployments require private networking, customer-managed encryption, and explicit service account configuration.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const myNetwork = gcp.compute.getNetwork({
    name: "default",
});
const mySubnetwork = gcp.compute.getSubnetwork({
    name: "default",
    region: "us-central1",
});
const instance = new gcp.notebooks.Instance("instance", {
    name: "notebooks-instance",
    location: "us-central1-a",
    machineType: "e2-medium",
    vmImage: {
        project: "cloud-notebooks-managed",
        imageFamily: "workbench-instances",
    },
    instanceOwners: ["my@service-account.com"],
    serviceAccount: "my@service-account.com",
    installGpuDriver: true,
    bootDiskType: "PD_SSD",
    bootDiskSizeGb: 150,
    noPublicIp: true,
    noProxyAccess: true,
    network: myNetwork.then(myNetwork => myNetwork.id),
    subnet: mySubnetwork.then(mySubnetwork => mySubnetwork.id),
    labels: {
        k: "val",
    },
    metadata: {
        terraform: "true",
    },
    serviceAccountScopes: [
        "https://www.googleapis.com/auth/bigquery",
        "https://www.googleapis.com/auth/devstorage.read_write",
        "https://www.googleapis.com/auth/cloud-platform",
        "https://www.googleapis.com/auth/userinfo.email",
    ],
    tags: [
        "foo",
        "bar",
    ],
    diskEncryption: "CMEK",
    kmsKey: "my-crypto-key",
    desiredState: "ACTIVE",
});
import pulumi
import pulumi_gcp as gcp

my_network = gcp.compute.get_network(name="default")
my_subnetwork = gcp.compute.get_subnetwork(name="default",
    region="us-central1")
instance = gcp.notebooks.Instance("instance",
    name="notebooks-instance",
    location="us-central1-a",
    machine_type="e2-medium",
    vm_image={
        "project": "cloud-notebooks-managed",
        "image_family": "workbench-instances",
    },
    instance_owners=["my@service-account.com"],
    service_account="my@service-account.com",
    install_gpu_driver=True,
    boot_disk_type="PD_SSD",
    boot_disk_size_gb=150,
    no_public_ip=True,
    no_proxy_access=True,
    network=my_network.id,
    subnet=my_subnetwork.id,
    labels={
        "k": "val",
    },
    metadata={
        "terraform": "true",
    },
    service_account_scopes=[
        "https://www.googleapis.com/auth/bigquery",
        "https://www.googleapis.com/auth/devstorage.read_write",
        "https://www.googleapis.com/auth/cloud-platform",
        "https://www.googleapis.com/auth/userinfo.email",
    ],
    tags=[
        "foo",
        "bar",
    ],
    disk_encryption="CMEK",
    kms_key="my-crypto-key",
    desired_state="ACTIVE")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/notebooks"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		myNetwork, err := compute.LookupNetwork(ctx, &compute.LookupNetworkArgs{
			Name: "default",
		}, nil)
		if err != nil {
			return err
		}
		mySubnetwork, err := compute.LookupSubnetwork(ctx, &compute.LookupSubnetworkArgs{
			Name:   pulumi.StringRef("default"),
			Region: pulumi.StringRef("us-central1"),
		}, nil)
		if err != nil {
			return err
		}
		_, err = notebooks.NewInstance(ctx, "instance", &notebooks.InstanceArgs{
			Name:        pulumi.String("notebooks-instance"),
			Location:    pulumi.String("us-central1-a"),
			MachineType: pulumi.String("e2-medium"),
			VmImage: &notebooks.InstanceVmImageArgs{
				Project:     pulumi.String("cloud-notebooks-managed"),
				ImageFamily: pulumi.String("workbench-instances"),
			},
			InstanceOwners: pulumi.StringArray{
				pulumi.String("my@service-account.com"),
			},
			ServiceAccount:   pulumi.String("my@service-account.com"),
			InstallGpuDriver: pulumi.Bool(true),
			BootDiskType:     pulumi.String("PD_SSD"),
			BootDiskSizeGb:   pulumi.Int(150),
			NoPublicIp:       pulumi.Bool(true),
			NoProxyAccess:    pulumi.Bool(true),
			Network:          pulumi.String(myNetwork.Id),
			Subnet:           pulumi.String(mySubnetwork.Id),
			Labels: pulumi.StringMap{
				"k": pulumi.String("val"),
			},
			Metadata: pulumi.StringMap{
				"terraform": pulumi.String("true"),
			},
			ServiceAccountScopes: pulumi.StringArray{
				pulumi.String("https://www.googleapis.com/auth/bigquery"),
				pulumi.String("https://www.googleapis.com/auth/devstorage.read_write"),
				pulumi.String("https://www.googleapis.com/auth/cloud-platform"),
				pulumi.String("https://www.googleapis.com/auth/userinfo.email"),
			},
			Tags: pulumi.StringArray{
				pulumi.String("foo"),
				pulumi.String("bar"),
			},
			DiskEncryption: pulumi.String("CMEK"),
			KmsKey:         pulumi.String("my-crypto-key"),
			DesiredState:   pulumi.String("ACTIVE"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var myNetwork = Gcp.Compute.GetNetwork.Invoke(new()
    {
        Name = "default",
    });

    var mySubnetwork = Gcp.Compute.GetSubnetwork.Invoke(new()
    {
        Name = "default",
        Region = "us-central1",
    });

    var instance = new Gcp.Notebooks.Instance("instance", new()
    {
        Name = "notebooks-instance",
        Location = "us-central1-a",
        MachineType = "e2-medium",
        VmImage = new Gcp.Notebooks.Inputs.InstanceVmImageArgs
        {
            Project = "cloud-notebooks-managed",
            ImageFamily = "workbench-instances",
        },
        InstanceOwners = new[]
        {
            "my@service-account.com",
        },
        ServiceAccount = "my@service-account.com",
        InstallGpuDriver = true,
        BootDiskType = "PD_SSD",
        BootDiskSizeGb = 150,
        NoPublicIp = true,
        NoProxyAccess = true,
        Network = myNetwork.Apply(getNetworkResult => getNetworkResult.Id),
        Subnet = mySubnetwork.Apply(getSubnetworkResult => getSubnetworkResult.Id),
        Labels = 
        {
            { "k", "val" },
        },
        Metadata = 
        {
            { "terraform", "true" },
        },
        ServiceAccountScopes = new[]
        {
            "https://www.googleapis.com/auth/bigquery",
            "https://www.googleapis.com/auth/devstorage.read_write",
            "https://www.googleapis.com/auth/cloud-platform",
            "https://www.googleapis.com/auth/userinfo.email",
        },
        Tags = new[]
        {
            "foo",
            "bar",
        },
        DiskEncryption = "CMEK",
        KmsKey = "my-crypto-key",
        DesiredState = "ACTIVE",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.ComputeFunctions;
import com.pulumi.gcp.compute.inputs.GetNetworkArgs;
import com.pulumi.gcp.compute.inputs.GetSubnetworkArgs;
import com.pulumi.gcp.notebooks.Instance;
import com.pulumi.gcp.notebooks.InstanceArgs;
import com.pulumi.gcp.notebooks.inputs.InstanceVmImageArgs;
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) {
        final var myNetwork = ComputeFunctions.getNetwork(GetNetworkArgs.builder()
            .name("default")
            .build());

        final var mySubnetwork = ComputeFunctions.getSubnetwork(GetSubnetworkArgs.builder()
            .name("default")
            .region("us-central1")
            .build());

        var instance = new Instance("instance", InstanceArgs.builder()
            .name("notebooks-instance")
            .location("us-central1-a")
            .machineType("e2-medium")
            .vmImage(InstanceVmImageArgs.builder()
                .project("cloud-notebooks-managed")
                .imageFamily("workbench-instances")
                .build())
            .instanceOwners("my@service-account.com")
            .serviceAccount("my@service-account.com")
            .installGpuDriver(true)
            .bootDiskType("PD_SSD")
            .bootDiskSizeGb(150)
            .noPublicIp(true)
            .noProxyAccess(true)
            .network(myNetwork.id())
            .subnet(mySubnetwork.id())
            .labels(Map.of("k", "val"))
            .metadata(Map.of("terraform", "true"))
            .serviceAccountScopes(            
                "https://www.googleapis.com/auth/bigquery",
                "https://www.googleapis.com/auth/devstorage.read_write",
                "https://www.googleapis.com/auth/cloud-platform",
                "https://www.googleapis.com/auth/userinfo.email")
            .tags(            
                "foo",
                "bar")
            .diskEncryption("CMEK")
            .kmsKey("my-crypto-key")
            .desiredState("ACTIVE")
            .build());

    }
}
resources:
  instance:
    type: gcp:notebooks:Instance
    properties:
      name: notebooks-instance
      location: us-central1-a
      machineType: e2-medium
      vmImage:
        project: cloud-notebooks-managed
        imageFamily: workbench-instances
      instanceOwners:
        - my@service-account.com
      serviceAccount: my@service-account.com
      installGpuDriver: true
      bootDiskType: PD_SSD
      bootDiskSizeGb: 150
      noPublicIp: true
      noProxyAccess: true
      network: ${myNetwork.id}
      subnet: ${mySubnetwork.id}
      labels:
        k: val
      metadata:
        terraform: 'true'
      serviceAccountScopes:
        - https://www.googleapis.com/auth/bigquery
        - https://www.googleapis.com/auth/devstorage.read_write
        - https://www.googleapis.com/auth/cloud-platform
        - https://www.googleapis.com/auth/userinfo.email
      tags:
        - foo
        - bar
      diskEncryption: CMEK
      kmsKey: my-crypto-key
      desiredState: ACTIVE
variables:
  myNetwork:
    fn::invoke:
      function: gcp:compute:getNetwork
      arguments:
        name: default
  mySubnetwork:
    fn::invoke:
      function: gcp:compute:getSubnetwork
      arguments:
        name: default
        region: us-central1

The network and subnet properties place the instance in a specific VPC. The noPublicIp property prevents external IP assignment. The diskEncryption property set to CMEK enables customer-managed encryption, requiring a kmsKey reference. The serviceAccount and instanceOwners properties control access and permissions.

Beyond these examples

These snippets focus on specific notebook instance features: VM and container image deployment, GPU acceleration and driver installation, and VPC networking and encryption. They’re intentionally minimal rather than full data science environments.

The examples may reference pre-existing infrastructure such as VPC networks and subnets, KMS encryption keys, and service accounts with notebook permissions. They focus on configuring the instance rather than provisioning the surrounding infrastructure.

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

  • Startup scripts and post-boot automation (postStartupScript)
  • Disk sizing and type selection (bootDiskSizeGb, dataDiskSizeGb)
  • Shielded VM configuration (shieldedInstanceConfig)
  • Reservation affinity for committed use discounts

These omissions are intentional: the goal is to illustrate how each notebook feature is wired, not provide drop-in ML environments. See the Notebooks Instance resource reference for all available configuration options.

Let's deploy GCP Notebook Instances

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Migration & Deprecation
Should I still use gcp.notebooks.Instance?
No, gcp.notebooks.Instance is deprecated and will be removed in a future major release. Migrate to gcp.workbench.Instance instead.
Resource Lifecycle & State
Why aren't my configuration changes being detected?
Due to limitations of the Notebooks Instance API, many fields do not properly detect drift and will not appear in state once imported. Manual verification of changes may be required.
What properties can't I change after creating an instance?
Most properties are immutable, including location, machineType, name, network, subnet, serviceAccount, diskEncryption, vmImage, containerImage, installGpuDriver, acceleratorConfig, bootDiskType, dataDiskType, and noRemoveDataDisk.
How do I stop or start an instance?
Set desiredState to STOPPED to stop the instance, or ACTIVE to start it.
Why can't I see the proxy URL right after creation?
The proxyUri output is only returned when the resource is in a PROVISIONED state. Use pulumi up -refresh-only to await population of this value if needed.
Image & Runtime Configuration
What's the difference between vmImage and containerImage?
Use vmImage (with project and imageFamily) for Compute Engine VM images, or containerImage (with repository and tag) for container-based instances. They are mutually exclusive.
How do I configure GPU acceleration?
Set installGpuDriver to true and configure acceleratorConfig with type (e.g., NVIDIA_TESLA_T4) and coreCount. Ensure your machineType has sufficient vCPUs and memory to support the accelerator.
Storage, Encryption & Labels
What are the disk size limits for notebook instances?
Both bootDiskSizeGb and dataDiskSizeGb default to 100 GB and support a maximum of 64,000 GB (64 TB). The minimum recommended boot disk size is 100 GB.
How do I use customer-managed encryption keys?
Set diskEncryption to CMEK and provide a kmsKey in the format projects/{project_id}/locations/{location}/keyRings/{key_ring_id}/cryptoKeys/{key_id}.
How do I prevent the data disk from being deleted when I delete the instance?
Set noRemoveDataDisk to true. This prevents automatic deletion of the data disk when the instance is deleted.
Why don't my labels match what I configured?
The labels field is non-authoritative and only manages labels present in your configuration. Use effectiveLabels to see all labels present on the resource, including those configured by other clients and services.

Using a different cloud?

Explore analytics guides for other cloud providers: