Configure GCP Cloud Run Worker Pools

The gcp:cloudrunv2/workerPool:WorkerPool resource, part of the Pulumi GCP provider, defines a Cloud Run worker pool that manages pull-based workloads: container images, resource allocation, networking, and storage mounts. This guide focuses on four capabilities: container deployment with resource limits, VPC networking and database connectivity, storage mounts (Cloud SQL, GCS, NFS), and GPU acceleration.

Worker pools process tasks from queues rather than handling HTTP requests. They reference container images in Artifact Registry and may connect to Cloud SQL, Secret Manager, VPC networks, Cloud Storage, or Filestore. The examples are intentionally small. Combine them with your own infrastructure and task queues.

Deploy a worker pool with a container image

Most deployments start by specifying a container image and basic configuration for processing background tasks.

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

const _default = new gcp.cloudrunv2.WorkerPool("default", {
    name: "cloudrun-worker-pool",
    location: "us-central1",
    deletionProtection: false,
    launchStage: "BETA",
    template: {
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/worker-pool",
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.cloudrunv2.WorkerPool("default",
    name="cloudrun-worker-pool",
    location="us-central1",
    deletion_protection=False,
    launch_stage="BETA",
    template={
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/worker-pool",
        }],
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrunv2.NewWorkerPool(ctx, "default", &cloudrunv2.WorkerPoolArgs{
			Name:               pulumi.String("cloudrun-worker-pool"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			LaunchStage:        pulumi.String("BETA"),
			Template: &cloudrunv2.WorkerPoolTemplateArgs{
				Containers: cloudrunv2.WorkerPoolTemplateContainerArray{
					&cloudrunv2.WorkerPoolTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/worker-pool"),
					},
				},
			},
		})
		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 @default = new Gcp.CloudRunV2.WorkerPool("default", new()
    {
        Name = "cloudrun-worker-pool",
        Location = "us-central1",
        DeletionProtection = false,
        LaunchStage = "BETA",
        Template = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/worker-pool",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudrunv2.WorkerPool;
import com.pulumi.gcp.cloudrunv2.WorkerPoolArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateArgs;
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 default_ = new WorkerPool("default", WorkerPoolArgs.builder()
            .name("cloudrun-worker-pool")
            .location("us-central1")
            .deletionProtection(false)
            .launchStage("BETA")
            .template(WorkerPoolTemplateArgs.builder()
                .containers(WorkerPoolTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/worker-pool")
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:WorkerPool
    properties:
      name: cloudrun-worker-pool
      location: us-central1
      deletionProtection: false
      launchStage: BETA
      template:
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/worker-pool

The template.containers array defines the workload containers. Each container needs an image from Artifact Registry or Container Registry. The launchStage property controls access to preview features; BETA enables features not yet generally available. The name and location properties identify the worker pool within your GCP project.

Set CPU and memory limits for containers

Compute-intensive tasks need explicit resource limits for predictable performance and cost control.

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

const _default = new gcp.cloudrunv2.WorkerPool("default", {
    name: "cloudrun-worker-pool",
    location: "us-central1",
    deletionProtection: false,
    launchStage: "BETA",
    template: {
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/worker-pool",
            resources: {
                limits: {
                    cpu: "2",
                    memory: "1024Mi",
                },
            },
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.cloudrunv2.WorkerPool("default",
    name="cloudrun-worker-pool",
    location="us-central1",
    deletion_protection=False,
    launch_stage="BETA",
    template={
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/worker-pool",
            "resources": {
                "limits": {
                    "cpu": "2",
                    "memory": "1024Mi",
                },
            },
        }],
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrunv2.NewWorkerPool(ctx, "default", &cloudrunv2.WorkerPoolArgs{
			Name:               pulumi.String("cloudrun-worker-pool"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			LaunchStage:        pulumi.String("BETA"),
			Template: &cloudrunv2.WorkerPoolTemplateArgs{
				Containers: cloudrunv2.WorkerPoolTemplateContainerArray{
					&cloudrunv2.WorkerPoolTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/worker-pool"),
						Resources: &cloudrunv2.WorkerPoolTemplateContainerResourcesArgs{
							Limits: pulumi.StringMap{
								"cpu":    pulumi.String("2"),
								"memory": pulumi.String("1024Mi"),
							},
						},
					},
				},
			},
		})
		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 @default = new Gcp.CloudRunV2.WorkerPool("default", new()
    {
        Name = "cloudrun-worker-pool",
        Location = "us-central1",
        DeletionProtection = false,
        LaunchStage = "BETA",
        Template = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/worker-pool",
                    Resources = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerResourcesArgs
                    {
                        Limits = 
                        {
                            { "cpu", "2" },
                            { "memory", "1024Mi" },
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudrunv2.WorkerPool;
import com.pulumi.gcp.cloudrunv2.WorkerPoolArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateArgs;
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 default_ = new WorkerPool("default", WorkerPoolArgs.builder()
            .name("cloudrun-worker-pool")
            .location("us-central1")
            .deletionProtection(false)
            .launchStage("BETA")
            .template(WorkerPoolTemplateArgs.builder()
                .containers(WorkerPoolTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/worker-pool")
                    .resources(WorkerPoolTemplateContainerResourcesArgs.builder()
                        .limits(Map.ofEntries(
                            Map.entry("cpu", "2"),
                            Map.entry("memory", "1024Mi")
                        ))
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:WorkerPool
    properties:
      name: cloudrun-worker-pool
      location: us-central1
      deletionProtection: false
      launchStage: BETA
      template:
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/worker-pool
            resources:
              limits:
                cpu: '2'
                memory: 1024Mi

The resources.limits block sets CPU cores and memory allocation. CPU is specified as a string (e.g., “2” for 2 cores), and memory uses units like “1024Mi” for mebibytes. Without explicit limits, containers use Cloud Run defaults.

Coordinate container startup with dependencies

Multi-container worker pools can control startup order using health checks to ensure supporting containers are ready first.

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

const _default = new gcp.cloudrunv2.WorkerPool("default", {
    name: "cloudrun-worker-pool",
    location: "us-central1",
    deletionProtection: false,
    launchStage: "BETA",
    template: {
        containers: [
            {
                name: "foo-1",
                image: "us-docker.pkg.dev/cloudrun/container/worker-pool",
                dependsOns: ["foo-2"],
            },
            {
                name: "foo-2",
                image: "us-docker.pkg.dev/cloudrun/container/worker-pool",
                startupProbe: {
                    httpGet: {
                        path: "/healthz",
                        port: 8080,
                    },
                    periodSeconds: 5,
                    timeoutSeconds: 2,
                    failureThreshold: 3,
                },
            },
        ],
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.cloudrunv2.WorkerPool("default",
    name="cloudrun-worker-pool",
    location="us-central1",
    deletion_protection=False,
    launch_stage="BETA",
    template={
        "containers": [
            {
                "name": "foo-1",
                "image": "us-docker.pkg.dev/cloudrun/container/worker-pool",
                "depends_ons": ["foo-2"],
            },
            {
                "name": "foo-2",
                "image": "us-docker.pkg.dev/cloudrun/container/worker-pool",
                "startup_probe": {
                    "http_get": {
                        "path": "/healthz",
                        "port": 8080,
                    },
                    "period_seconds": 5,
                    "timeout_seconds": 2,
                    "failure_threshold": 3,
                },
            },
        ],
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrunv2.NewWorkerPool(ctx, "default", &cloudrunv2.WorkerPoolArgs{
			Name:               pulumi.String("cloudrun-worker-pool"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			LaunchStage:        pulumi.String("BETA"),
			Template: &cloudrunv2.WorkerPoolTemplateArgs{
				Containers: cloudrunv2.WorkerPoolTemplateContainerArray{
					&cloudrunv2.WorkerPoolTemplateContainerArgs{
						Name:  pulumi.String("foo-1"),
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/worker-pool"),
						DependsOns: pulumi.StringArray{
							pulumi.String("foo-2"),
						},
					},
					&cloudrunv2.WorkerPoolTemplateContainerArgs{
						Name:  pulumi.String("foo-2"),
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/worker-pool"),
						StartupProbe: &cloudrunv2.WorkerPoolTemplateContainerStartupProbeArgs{
							HttpGet: &cloudrunv2.WorkerPoolTemplateContainerStartupProbeHttpGetArgs{
								Path: pulumi.String("/healthz"),
								Port: pulumi.Int(8080),
							},
							PeriodSeconds:    pulumi.Int(5),
							TimeoutSeconds:   pulumi.Int(2),
							FailureThreshold: pulumi.Int(3),
						},
					},
				},
			},
		})
		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 @default = new Gcp.CloudRunV2.WorkerPool("default", new()
    {
        Name = "cloudrun-worker-pool",
        Location = "us-central1",
        DeletionProtection = false,
        LaunchStage = "BETA",
        Template = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerArgs
                {
                    Name = "foo-1",
                    Image = "us-docker.pkg.dev/cloudrun/container/worker-pool",
                    DependsOns = new[]
                    {
                        "foo-2",
                    },
                },
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerArgs
                {
                    Name = "foo-2",
                    Image = "us-docker.pkg.dev/cloudrun/container/worker-pool",
                    StartupProbe = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerStartupProbeArgs
                    {
                        HttpGet = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerStartupProbeHttpGetArgs
                        {
                            Path = "/healthz",
                            Port = 8080,
                        },
                        PeriodSeconds = 5,
                        TimeoutSeconds = 2,
                        FailureThreshold = 3,
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudrunv2.WorkerPool;
import com.pulumi.gcp.cloudrunv2.WorkerPoolArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateArgs;
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 default_ = new WorkerPool("default", WorkerPoolArgs.builder()
            .name("cloudrun-worker-pool")
            .location("us-central1")
            .deletionProtection(false)
            .launchStage("BETA")
            .template(WorkerPoolTemplateArgs.builder()
                .containers(                
                    WorkerPoolTemplateContainerArgs.builder()
                        .name("foo-1")
                        .image("us-docker.pkg.dev/cloudrun/container/worker-pool")
                        .dependsOns("foo-2")
                        .build(),
                    WorkerPoolTemplateContainerArgs.builder()
                        .name("foo-2")
                        .image("us-docker.pkg.dev/cloudrun/container/worker-pool")
                        .startupProbe(WorkerPoolTemplateContainerStartupProbeArgs.builder()
                            .httpGet(WorkerPoolTemplateContainerStartupProbeHttpGetArgs.builder()
                                .path("/healthz")
                                .port(8080)
                                .build())
                            .periodSeconds(5)
                            .timeoutSeconds(2)
                            .failureThreshold(3)
                            .build())
                        .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:WorkerPool
    properties:
      name: cloudrun-worker-pool
      location: us-central1
      deletionProtection: false
      launchStage: BETA
      template:
        containers:
          - name: foo-1
            image: us-docker.pkg.dev/cloudrun/container/worker-pool
            dependsOns:
              - foo-2
          - name: foo-2
            image: us-docker.pkg.dev/cloudrun/container/worker-pool
            startupProbe:
              httpGet:
                path: /healthz
                port: 8080
              periodSeconds: 5
              timeoutSeconds: 2
              failureThreshold: 3

The dependsOns array specifies which containers must start before others. The startupProbe checks container health using HTTP, TCP, or gRPC probes. Here, “foo-1” waits for “foo-2” to pass its HTTP health check on port 8080 before starting.

Connect to Cloud SQL with mounted secrets

Worker pools accessing databases need Cloud SQL socket connections and credentials from Secret Manager.

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

const secret = new gcp.secretmanager.Secret("secret", {
    secretId: "secret-1",
    replication: {
        auto: {},
    },
});
const secret_version_data = new gcp.secretmanager.SecretVersion("secret-version-data", {
    secret: secret.name,
    secretData: "secret-data",
});
const instance = new gcp.sql.DatabaseInstance("instance", {
    name: "cloudrun-sql",
    region: "us-central1",
    databaseVersion: "MYSQL_5_7",
    settings: {
        tier: "db-f1-micro",
    },
    deletionProtection: true,
});
const _default = new gcp.cloudrunv2.WorkerPool("default", {
    name: "cloudrun-worker-pool",
    location: "us-central1",
    deletionProtection: false,
    launchStage: "BETA",
    template: {
        volumes: [{
            name: "cloudsql",
            cloudSqlInstance: {
                instances: [instance.connectionName],
            },
        }],
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/worker-pool",
            envs: [
                {
                    name: "FOO",
                    value: "bar",
                },
                {
                    name: "SECRET_ENV_VAR",
                    valueSource: {
                        secretKeyRef: {
                            secret: secret.secretId,
                            version: "1",
                        },
                    },
                },
            ],
            volumeMounts: [{
                name: "cloudsql",
                mountPath: "/cloudsql",
            }],
        }],
    },
    instanceSplits: [{
        type: "INSTANCE_SPLIT_ALLOCATION_TYPE_LATEST",
        percent: 100,
    }],
}, {
    dependsOn: [secret_version_data],
});
const project = gcp.organizations.getProject({});
const secret_access = new gcp.secretmanager.SecretIamMember("secret-access", {
    secretId: secret.id,
    role: "roles/secretmanager.secretAccessor",
    member: project.then(project => `serviceAccount:${project.number}-compute@developer.gserviceaccount.com`),
}, {
    dependsOn: [secret],
});
import pulumi
import pulumi_gcp as gcp

secret = gcp.secretmanager.Secret("secret",
    secret_id="secret-1",
    replication={
        "auto": {},
    })
secret_version_data = gcp.secretmanager.SecretVersion("secret-version-data",
    secret=secret.name,
    secret_data="secret-data")
instance = gcp.sql.DatabaseInstance("instance",
    name="cloudrun-sql",
    region="us-central1",
    database_version="MYSQL_5_7",
    settings={
        "tier": "db-f1-micro",
    },
    deletion_protection=True)
default = gcp.cloudrunv2.WorkerPool("default",
    name="cloudrun-worker-pool",
    location="us-central1",
    deletion_protection=False,
    launch_stage="BETA",
    template={
        "volumes": [{
            "name": "cloudsql",
            "cloud_sql_instance": {
                "instances": [instance.connection_name],
            },
        }],
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/worker-pool",
            "envs": [
                {
                    "name": "FOO",
                    "value": "bar",
                },
                {
                    "name": "SECRET_ENV_VAR",
                    "value_source": {
                        "secret_key_ref": {
                            "secret": secret.secret_id,
                            "version": "1",
                        },
                    },
                },
            ],
            "volume_mounts": [{
                "name": "cloudsql",
                "mount_path": "/cloudsql",
            }],
        }],
    },
    instance_splits=[{
        "type": "INSTANCE_SPLIT_ALLOCATION_TYPE_LATEST",
        "percent": 100,
    }],
    opts = pulumi.ResourceOptions(depends_on=[secret_version_data]))
project = gcp.organizations.get_project()
secret_access = gcp.secretmanager.SecretIamMember("secret-access",
    secret_id=secret.id,
    role="roles/secretmanager.secretAccessor",
    member=f"serviceAccount:{project.number}-compute@developer.gserviceaccount.com",
    opts = pulumi.ResourceOptions(depends_on=[secret]))
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudrunv2"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/secretmanager"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/sql"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		secret, err := secretmanager.NewSecret(ctx, "secret", &secretmanager.SecretArgs{
			SecretId: pulumi.String("secret-1"),
			Replication: &secretmanager.SecretReplicationArgs{
				Auto: &secretmanager.SecretReplicationAutoArgs{},
			},
		})
		if err != nil {
			return err
		}
		secret_version_data, err := secretmanager.NewSecretVersion(ctx, "secret-version-data", &secretmanager.SecretVersionArgs{
			Secret:     secret.Name,
			SecretData: pulumi.String("secret-data"),
		})
		if err != nil {
			return err
		}
		instance, err := sql.NewDatabaseInstance(ctx, "instance", &sql.DatabaseInstanceArgs{
			Name:            pulumi.String("cloudrun-sql"),
			Region:          pulumi.String("us-central1"),
			DatabaseVersion: pulumi.String("MYSQL_5_7"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier: pulumi.String("db-f1-micro"),
			},
			DeletionProtection: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		_, err = cloudrunv2.NewWorkerPool(ctx, "default", &cloudrunv2.WorkerPoolArgs{
			Name:               pulumi.String("cloudrun-worker-pool"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			LaunchStage:        pulumi.String("BETA"),
			Template: &cloudrunv2.WorkerPoolTemplateArgs{
				Volumes: cloudrunv2.WorkerPoolTemplateVolumeArray{
					&cloudrunv2.WorkerPoolTemplateVolumeArgs{
						Name: pulumi.String("cloudsql"),
						CloudSqlInstance: &cloudrunv2.WorkerPoolTemplateVolumeCloudSqlInstanceArgs{
							Instances: pulumi.StringArray{
								instance.ConnectionName,
							},
						},
					},
				},
				Containers: cloudrunv2.WorkerPoolTemplateContainerArray{
					&cloudrunv2.WorkerPoolTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/worker-pool"),
						Envs: cloudrunv2.WorkerPoolTemplateContainerEnvArray{
							&cloudrunv2.WorkerPoolTemplateContainerEnvArgs{
								Name:  pulumi.String("FOO"),
								Value: pulumi.String("bar"),
							},
							&cloudrunv2.WorkerPoolTemplateContainerEnvArgs{
								Name: pulumi.String("SECRET_ENV_VAR"),
								ValueSource: &cloudrunv2.WorkerPoolTemplateContainerEnvValueSourceArgs{
									SecretKeyRef: &cloudrunv2.WorkerPoolTemplateContainerEnvValueSourceSecretKeyRefArgs{
										Secret:  secret.SecretId,
										Version: pulumi.String("1"),
									},
								},
							},
						},
						VolumeMounts: cloudrunv2.WorkerPoolTemplateContainerVolumeMountArray{
							&cloudrunv2.WorkerPoolTemplateContainerVolumeMountArgs{
								Name:      pulumi.String("cloudsql"),
								MountPath: pulumi.String("/cloudsql"),
							},
						},
					},
				},
			},
			InstanceSplits: cloudrunv2.WorkerPoolInstanceSplitArray{
				&cloudrunv2.WorkerPoolInstanceSplitArgs{
					Type:    pulumi.String("INSTANCE_SPLIT_ALLOCATION_TYPE_LATEST"),
					Percent: pulumi.Int(100),
				},
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			secret_version_data,
		}))
		if err != nil {
			return err
		}
		project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		_, err = secretmanager.NewSecretIamMember(ctx, "secret-access", &secretmanager.SecretIamMemberArgs{
			SecretId: secret.ID(),
			Role:     pulumi.String("roles/secretmanager.secretAccessor"),
			Member:   pulumi.Sprintf("serviceAccount:%v-compute@developer.gserviceaccount.com", project.Number),
		}, pulumi.DependsOn([]pulumi.Resource{
			secret,
		}))
		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 secret = new Gcp.SecretManager.Secret("secret", new()
    {
        SecretId = "secret-1",
        Replication = new Gcp.SecretManager.Inputs.SecretReplicationArgs
        {
            Auto = null,
        },
    });

    var secret_version_data = new Gcp.SecretManager.SecretVersion("secret-version-data", new()
    {
        Secret = secret.Name,
        SecretData = "secret-data",
    });

    var instance = new Gcp.Sql.DatabaseInstance("instance", new()
    {
        Name = "cloudrun-sql",
        Region = "us-central1",
        DatabaseVersion = "MYSQL_5_7",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-f1-micro",
        },
        DeletionProtection = true,
    });

    var @default = new Gcp.CloudRunV2.WorkerPool("default", new()
    {
        Name = "cloudrun-worker-pool",
        Location = "us-central1",
        DeletionProtection = false,
        LaunchStage = "BETA",
        Template = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateArgs
        {
            Volumes = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateVolumeArgs
                {
                    Name = "cloudsql",
                    CloudSqlInstance = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateVolumeCloudSqlInstanceArgs
                    {
                        Instances = new[]
                        {
                            instance.ConnectionName,
                        },
                    },
                },
            },
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/worker-pool",
                    Envs = new[]
                    {
                        new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerEnvArgs
                        {
                            Name = "FOO",
                            Value = "bar",
                        },
                        new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerEnvArgs
                        {
                            Name = "SECRET_ENV_VAR",
                            ValueSource = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerEnvValueSourceArgs
                            {
                                SecretKeyRef = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerEnvValueSourceSecretKeyRefArgs
                                {
                                    Secret = secret.SecretId,
                                    Version = "1",
                                },
                            },
                        },
                    },
                    VolumeMounts = new[]
                    {
                        new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerVolumeMountArgs
                        {
                            Name = "cloudsql",
                            MountPath = "/cloudsql",
                        },
                    },
                },
            },
        },
        InstanceSplits = new[]
        {
            new Gcp.CloudRunV2.Inputs.WorkerPoolInstanceSplitArgs
            {
                Type = "INSTANCE_SPLIT_ALLOCATION_TYPE_LATEST",
                Percent = 100,
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            secret_version_data,
        },
    });

    var project = Gcp.Organizations.GetProject.Invoke();

    var secret_access = new Gcp.SecretManager.SecretIamMember("secret-access", new()
    {
        SecretId = secret.Id,
        Role = "roles/secretmanager.secretAccessor",
        Member = $"serviceAccount:{project.Apply(getProjectResult => getProjectResult.Number)}-compute@developer.gserviceaccount.com",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            secret,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.secretmanager.Secret;
import com.pulumi.gcp.secretmanager.SecretArgs;
import com.pulumi.gcp.secretmanager.inputs.SecretReplicationArgs;
import com.pulumi.gcp.secretmanager.inputs.SecretReplicationAutoArgs;
import com.pulumi.gcp.secretmanager.SecretVersion;
import com.pulumi.gcp.secretmanager.SecretVersionArgs;
import com.pulumi.gcp.sql.DatabaseInstance;
import com.pulumi.gcp.sql.DatabaseInstanceArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsArgs;
import com.pulumi.gcp.cloudrunv2.WorkerPool;
import com.pulumi.gcp.cloudrunv2.WorkerPoolArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolInstanceSplitArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.secretmanager.SecretIamMember;
import com.pulumi.gcp.secretmanager.SecretIamMemberArgs;
import com.pulumi.resources.CustomResourceOptions;
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 secret = new Secret("secret", SecretArgs.builder()
            .secretId("secret-1")
            .replication(SecretReplicationArgs.builder()
                .auto(SecretReplicationAutoArgs.builder()
                    .build())
                .build())
            .build());

        var secret_version_data = new SecretVersion("secret-version-data", SecretVersionArgs.builder()
            .secret(secret.name())
            .secretData("secret-data")
            .build());

        var instance = new DatabaseInstance("instance", DatabaseInstanceArgs.builder()
            .name("cloudrun-sql")
            .region("us-central1")
            .databaseVersion("MYSQL_5_7")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-f1-micro")
                .build())
            .deletionProtection(true)
            .build());

        var default_ = new WorkerPool("default", WorkerPoolArgs.builder()
            .name("cloudrun-worker-pool")
            .location("us-central1")
            .deletionProtection(false)
            .launchStage("BETA")
            .template(WorkerPoolTemplateArgs.builder()
                .volumes(WorkerPoolTemplateVolumeArgs.builder()
                    .name("cloudsql")
                    .cloudSqlInstance(WorkerPoolTemplateVolumeCloudSqlInstanceArgs.builder()
                        .instances(instance.connectionName())
                        .build())
                    .build())
                .containers(WorkerPoolTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/worker-pool")
                    .envs(                    
                        WorkerPoolTemplateContainerEnvArgs.builder()
                            .name("FOO")
                            .value("bar")
                            .build(),
                        WorkerPoolTemplateContainerEnvArgs.builder()
                            .name("SECRET_ENV_VAR")
                            .valueSource(WorkerPoolTemplateContainerEnvValueSourceArgs.builder()
                                .secretKeyRef(WorkerPoolTemplateContainerEnvValueSourceSecretKeyRefArgs.builder()
                                    .secret(secret.secretId())
                                    .version("1")
                                    .build())
                                .build())
                            .build())
                    .volumeMounts(WorkerPoolTemplateContainerVolumeMountArgs.builder()
                        .name("cloudsql")
                        .mountPath("/cloudsql")
                        .build())
                    .build())
                .build())
            .instanceSplits(WorkerPoolInstanceSplitArgs.builder()
                .type("INSTANCE_SPLIT_ALLOCATION_TYPE_LATEST")
                .percent(100)
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(secret_version_data)
                .build());

        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        var secret_access = new SecretIamMember("secret-access", SecretIamMemberArgs.builder()
            .secretId(secret.id())
            .role("roles/secretmanager.secretAccessor")
            .member(String.format("serviceAccount:%s-compute@developer.gserviceaccount.com", project.number()))
            .build(), CustomResourceOptions.builder()
                .dependsOn(secret)
                .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:WorkerPool
    properties:
      name: cloudrun-worker-pool
      location: us-central1
      deletionProtection: false
      launchStage: BETA
      template:
        volumes:
          - name: cloudsql
            cloudSqlInstance:
              instances:
                - ${instance.connectionName}
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/worker-pool
            envs:
              - name: FOO
                value: bar
              - name: SECRET_ENV_VAR
                valueSource:
                  secretKeyRef:
                    secret: ${secret.secretId}
                    version: '1'
            volumeMounts:
              - name: cloudsql
                mountPath: /cloudsql
      instanceSplits:
        - type: INSTANCE_SPLIT_ALLOCATION_TYPE_LATEST
          percent: 100
    options:
      dependsOn:
        - ${["secret-version-data"]}
  secret:
    type: gcp:secretmanager:Secret
    properties:
      secretId: secret-1
      replication:
        auto: {}
  secret-version-data:
    type: gcp:secretmanager:SecretVersion
    properties:
      secret: ${secret.name}
      secretData: secret-data
  secret-access:
    type: gcp:secretmanager:SecretIamMember
    properties:
      secretId: ${secret.id}
      role: roles/secretmanager.secretAccessor
      member: serviceAccount:${project.number}-compute@developer.gserviceaccount.com
    options:
      dependsOn:
        - ${secret}
  instance:
    type: gcp:sql:DatabaseInstance
    properties:
      name: cloudrun-sql
      region: us-central1
      databaseVersion: MYSQL_5_7
      settings:
        tier: db-f1-micro
      deletionProtection: true
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The volumes array defines a cloudSqlInstance volume that mounts the Cloud SQL Unix socket. The envs array injects environment variables, including secrets via valueSource.secretKeyRef. The volumeMounts array makes the socket available at /cloudsql inside the container. The IAM member grants the compute service account permission to read secrets.

Place worker pools in a VPC network

Worker pools that access private resources need VPC connectivity to reach internal services or databases.

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

const _default = new gcp.cloudrunv2.WorkerPool("default", {
    name: "cloudrun-worker-pool",
    location: "us-central1",
    deletionProtection: false,
    launchStage: "BETA",
    template: {
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/worker-pool",
        }],
        vpcAccess: {
            networkInterfaces: [{
                network: "default",
                subnetwork: "default",
                tags: [
                    "tag1",
                    "tag2",
                    "tag3",
                ],
            }],
        },
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.cloudrunv2.WorkerPool("default",
    name="cloudrun-worker-pool",
    location="us-central1",
    deletion_protection=False,
    launch_stage="BETA",
    template={
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/worker-pool",
        }],
        "vpc_access": {
            "network_interfaces": [{
                "network": "default",
                "subnetwork": "default",
                "tags": [
                    "tag1",
                    "tag2",
                    "tag3",
                ],
            }],
        },
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrunv2.NewWorkerPool(ctx, "default", &cloudrunv2.WorkerPoolArgs{
			Name:               pulumi.String("cloudrun-worker-pool"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			LaunchStage:        pulumi.String("BETA"),
			Template: &cloudrunv2.WorkerPoolTemplateArgs{
				Containers: cloudrunv2.WorkerPoolTemplateContainerArray{
					&cloudrunv2.WorkerPoolTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/worker-pool"),
					},
				},
				VpcAccess: &cloudrunv2.WorkerPoolTemplateVpcAccessArgs{
					NetworkInterfaces: cloudrunv2.WorkerPoolTemplateVpcAccessNetworkInterfaceArray{
						&cloudrunv2.WorkerPoolTemplateVpcAccessNetworkInterfaceArgs{
							Network:    pulumi.String("default"),
							Subnetwork: pulumi.String("default"),
							Tags: pulumi.StringArray{
								pulumi.String("tag1"),
								pulumi.String("tag2"),
								pulumi.String("tag3"),
							},
						},
					},
				},
			},
		})
		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 @default = new Gcp.CloudRunV2.WorkerPool("default", new()
    {
        Name = "cloudrun-worker-pool",
        Location = "us-central1",
        DeletionProtection = false,
        LaunchStage = "BETA",
        Template = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/worker-pool",
                },
            },
            VpcAccess = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateVpcAccessArgs
            {
                NetworkInterfaces = new[]
                {
                    new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateVpcAccessNetworkInterfaceArgs
                    {
                        Network = "default",
                        Subnetwork = "default",
                        Tags = new[]
                        {
                            "tag1",
                            "tag2",
                            "tag3",
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudrunv2.WorkerPool;
import com.pulumi.gcp.cloudrunv2.WorkerPoolArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateVpcAccessArgs;
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 default_ = new WorkerPool("default", WorkerPoolArgs.builder()
            .name("cloudrun-worker-pool")
            .location("us-central1")
            .deletionProtection(false)
            .launchStage("BETA")
            .template(WorkerPoolTemplateArgs.builder()
                .containers(WorkerPoolTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/worker-pool")
                    .build())
                .vpcAccess(WorkerPoolTemplateVpcAccessArgs.builder()
                    .networkInterfaces(WorkerPoolTemplateVpcAccessNetworkInterfaceArgs.builder()
                        .network("default")
                        .subnetwork("default")
                        .tags(                        
                            "tag1",
                            "tag2",
                            "tag3")
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:WorkerPool
    properties:
      name: cloudrun-worker-pool
      location: us-central1
      deletionProtection: false
      launchStage: BETA
      template:
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/worker-pool
        vpcAccess:
          networkInterfaces:
            - network: default
              subnetwork: default
              tags:
                - tag1
                - tag2
                - tag3

The vpcAccess.networkInterfaces block places containers in specified VPC networks and subnets. The tags array applies network tags for firewall rules. This configuration enables access to private IP addresses within the VPC.

Attach GPUs for accelerated workloads

Machine learning and compute-intensive workloads benefit from GPU acceleration for training or processing.

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

const _default = new gcp.cloudrunv2.WorkerPool("default", {
    name: "cloudrun-worker-pool",
    location: "us-central1",
    deletionProtection: false,
    launchStage: "BETA",
    template: {
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/worker-pool",
            resources: {
                limits: {
                    cpu: "4",
                    memory: "16Gi",
                    "nvidia.com/gpu": "1",
                },
            },
        }],
        nodeSelector: {
            accelerator: "nvidia-l4",
        },
        gpuZonalRedundancyDisabled: true,
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.cloudrunv2.WorkerPool("default",
    name="cloudrun-worker-pool",
    location="us-central1",
    deletion_protection=False,
    launch_stage="BETA",
    template={
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/worker-pool",
            "resources": {
                "limits": {
                    "cpu": "4",
                    "memory": "16Gi",
                    "nvidia.com/gpu": "1",
                },
            },
        }],
        "node_selector": {
            "accelerator": "nvidia-l4",
        },
        "gpu_zonal_redundancy_disabled": True,
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrunv2.NewWorkerPool(ctx, "default", &cloudrunv2.WorkerPoolArgs{
			Name:               pulumi.String("cloudrun-worker-pool"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			LaunchStage:        pulumi.String("BETA"),
			Template: &cloudrunv2.WorkerPoolTemplateArgs{
				Containers: cloudrunv2.WorkerPoolTemplateContainerArray{
					&cloudrunv2.WorkerPoolTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/worker-pool"),
						Resources: &cloudrunv2.WorkerPoolTemplateContainerResourcesArgs{
							Limits: pulumi.StringMap{
								"cpu":            pulumi.String("4"),
								"memory":         pulumi.String("16Gi"),
								"nvidia.com/gpu": pulumi.String("1"),
							},
						},
					},
				},
				NodeSelector: &cloudrunv2.WorkerPoolTemplateNodeSelectorArgs{
					Accelerator: pulumi.String("nvidia-l4"),
				},
				GpuZonalRedundancyDisabled: pulumi.Bool(true),
			},
		})
		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 @default = new Gcp.CloudRunV2.WorkerPool("default", new()
    {
        Name = "cloudrun-worker-pool",
        Location = "us-central1",
        DeletionProtection = false,
        LaunchStage = "BETA",
        Template = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/worker-pool",
                    Resources = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerResourcesArgs
                    {
                        Limits = 
                        {
                            { "cpu", "4" },
                            { "memory", "16Gi" },
                            { "nvidia.com/gpu", "1" },
                        },
                    },
                },
            },
            NodeSelector = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateNodeSelectorArgs
            {
                Accelerator = "nvidia-l4",
            },
            GpuZonalRedundancyDisabled = true,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudrunv2.WorkerPool;
import com.pulumi.gcp.cloudrunv2.WorkerPoolArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateNodeSelectorArgs;
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 default_ = new WorkerPool("default", WorkerPoolArgs.builder()
            .name("cloudrun-worker-pool")
            .location("us-central1")
            .deletionProtection(false)
            .launchStage("BETA")
            .template(WorkerPoolTemplateArgs.builder()
                .containers(WorkerPoolTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/worker-pool")
                    .resources(WorkerPoolTemplateContainerResourcesArgs.builder()
                        .limits(Map.ofEntries(
                            Map.entry("cpu", "4"),
                            Map.entry("memory", "16Gi"),
                            Map.entry("nvidia.com/gpu", "1")
                        ))
                        .build())
                    .build())
                .nodeSelector(WorkerPoolTemplateNodeSelectorArgs.builder()
                    .accelerator("nvidia-l4")
                    .build())
                .gpuZonalRedundancyDisabled(true)
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:WorkerPool
    properties:
      name: cloudrun-worker-pool
      location: us-central1
      deletionProtection: false
      launchStage: BETA
      template:
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/worker-pool
            resources:
              limits:
                cpu: '4'
                memory: 16Gi
                nvidia.com/gpu: '1'
        nodeSelector:
          accelerator: nvidia-l4
        gpuZonalRedundancyDisabled: true

The resources.limits block includes “nvidia.com/gpu” to request GPU allocation. The nodeSelector.accelerator specifies the GPU type (e.g., “nvidia-l4”). The gpuZonalRedundancyDisabled property controls whether GPUs are spread across zones; setting it to true keeps instances in a single zone.

Mount Cloud Storage buckets as volumes

Worker pools that process files can mount Cloud Storage buckets directly into the container filesystem.

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

const defaultBucket = new gcp.storage.Bucket("default", {
    name: "cloudrun-worker-pool",
    location: "US",
    uniformBucketLevelAccess: true,
});
const _default = new gcp.cloudrunv2.WorkerPool("default", {
    name: "cloudrun-worker-pool",
    location: "us-central1",
    deletionProtection: false,
    launchStage: "BETA",
    template: {
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/worker-pool",
            volumeMounts: [{
                name: "bucket",
                mountPath: "/var/www",
            }],
        }],
        volumes: [{
            name: "bucket",
            gcs: {
                bucket: defaultBucket.name,
                readOnly: false,
            },
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

default_bucket = gcp.storage.Bucket("default",
    name="cloudrun-worker-pool",
    location="US",
    uniform_bucket_level_access=True)
default = gcp.cloudrunv2.WorkerPool("default",
    name="cloudrun-worker-pool",
    location="us-central1",
    deletion_protection=False,
    launch_stage="BETA",
    template={
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/worker-pool",
            "volume_mounts": [{
                "name": "bucket",
                "mount_path": "/var/www",
            }],
        }],
        "volumes": [{
            "name": "bucket",
            "gcs": {
                "bucket": default_bucket.name,
                "read_only": False,
            },
        }],
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		defaultBucket, err := storage.NewBucket(ctx, "default", &storage.BucketArgs{
			Name:                     pulumi.String("cloudrun-worker-pool"),
			Location:                 pulumi.String("US"),
			UniformBucketLevelAccess: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		_, err = cloudrunv2.NewWorkerPool(ctx, "default", &cloudrunv2.WorkerPoolArgs{
			Name:               pulumi.String("cloudrun-worker-pool"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			LaunchStage:        pulumi.String("BETA"),
			Template: &cloudrunv2.WorkerPoolTemplateArgs{
				Containers: cloudrunv2.WorkerPoolTemplateContainerArray{
					&cloudrunv2.WorkerPoolTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/worker-pool"),
						VolumeMounts: cloudrunv2.WorkerPoolTemplateContainerVolumeMountArray{
							&cloudrunv2.WorkerPoolTemplateContainerVolumeMountArgs{
								Name:      pulumi.String("bucket"),
								MountPath: pulumi.String("/var/www"),
							},
						},
					},
				},
				Volumes: cloudrunv2.WorkerPoolTemplateVolumeArray{
					&cloudrunv2.WorkerPoolTemplateVolumeArgs{
						Name: pulumi.String("bucket"),
						Gcs: &cloudrunv2.WorkerPoolTemplateVolumeGcsArgs{
							Bucket:   defaultBucket.Name,
							ReadOnly: pulumi.Bool(false),
						},
					},
				},
			},
		})
		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 defaultBucket = new Gcp.Storage.Bucket("default", new()
    {
        Name = "cloudrun-worker-pool",
        Location = "US",
        UniformBucketLevelAccess = true,
    });

    var @default = new Gcp.CloudRunV2.WorkerPool("default", new()
    {
        Name = "cloudrun-worker-pool",
        Location = "us-central1",
        DeletionProtection = false,
        LaunchStage = "BETA",
        Template = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/worker-pool",
                    VolumeMounts = new[]
                    {
                        new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerVolumeMountArgs
                        {
                            Name = "bucket",
                            MountPath = "/var/www",
                        },
                    },
                },
            },
            Volumes = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateVolumeArgs
                {
                    Name = "bucket",
                    Gcs = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateVolumeGcsArgs
                    {
                        Bucket = defaultBucket.Name,
                        ReadOnly = false,
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.storage.Bucket;
import com.pulumi.gcp.storage.BucketArgs;
import com.pulumi.gcp.cloudrunv2.WorkerPool;
import com.pulumi.gcp.cloudrunv2.WorkerPoolArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateArgs;
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 defaultBucket = new Bucket("defaultBucket", BucketArgs.builder()
            .name("cloudrun-worker-pool")
            .location("US")
            .uniformBucketLevelAccess(true)
            .build());

        var default_ = new WorkerPool("default", WorkerPoolArgs.builder()
            .name("cloudrun-worker-pool")
            .location("us-central1")
            .deletionProtection(false)
            .launchStage("BETA")
            .template(WorkerPoolTemplateArgs.builder()
                .containers(WorkerPoolTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/worker-pool")
                    .volumeMounts(WorkerPoolTemplateContainerVolumeMountArgs.builder()
                        .name("bucket")
                        .mountPath("/var/www")
                        .build())
                    .build())
                .volumes(WorkerPoolTemplateVolumeArgs.builder()
                    .name("bucket")
                    .gcs(WorkerPoolTemplateVolumeGcsArgs.builder()
                        .bucket(defaultBucket.name())
                        .readOnly(false)
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:WorkerPool
    properties:
      name: cloudrun-worker-pool
      location: us-central1
      deletionProtection: false
      launchStage: BETA
      template:
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/worker-pool
            volumeMounts:
              - name: bucket
                mountPath: /var/www
        volumes:
          - name: bucket
            gcs:
              bucket: ${defaultBucket.name}
              readOnly: false
  defaultBucket:
    type: gcp:storage:Bucket
    name: default
    properties:
      name: cloudrun-worker-pool
      location: US
      uniformBucketLevelAccess: true

The volumes array defines a gcs volume pointing to a Cloud Storage bucket. The readOnly property controls write access. The volumeMounts array makes the bucket contents available at /var/www inside the container, allowing standard filesystem operations on Cloud Storage objects.

Mount Filestore NFS shares for persistent storage

Worker pools needing shared persistent storage can mount Filestore NFS shares across containers.

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

const defaultInstance = new gcp.filestore.Instance("default", {
    name: "cloudrun-worker-pool",
    location: "us-central1-b",
    tier: "BASIC_HDD",
    fileShares: {
        capacityGb: 1024,
        name: "share1",
    },
    networks: [{
        network: "default",
        modes: ["MODE_IPV4"],
    }],
});
const _default = new gcp.cloudrunv2.WorkerPool("default", {
    name: "cloudrun-worker-pool",
    location: "us-central1",
    deletionProtection: false,
    launchStage: "BETA",
    template: {
        containers: [{
            image: "us-docker.pkg.dev/cloudrun/container/worker-pool:latest",
            volumeMounts: [{
                name: "nfs",
                mountPath: "/mnt/nfs/filestore",
            }],
        }],
        vpcAccess: {
            networkInterfaces: [{
                network: "default",
                subnetwork: "default",
            }],
        },
        volumes: [{
            name: "nfs",
            nfs: {
                server: defaultInstance.networks.apply(networks => networks[0].ipAddresses?.[0]),
                path: "/share1",
                readOnly: false,
            },
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

default_instance = gcp.filestore.Instance("default",
    name="cloudrun-worker-pool",
    location="us-central1-b",
    tier="BASIC_HDD",
    file_shares={
        "capacity_gb": 1024,
        "name": "share1",
    },
    networks=[{
        "network": "default",
        "modes": ["MODE_IPV4"],
    }])
default = gcp.cloudrunv2.WorkerPool("default",
    name="cloudrun-worker-pool",
    location="us-central1",
    deletion_protection=False,
    launch_stage="BETA",
    template={
        "containers": [{
            "image": "us-docker.pkg.dev/cloudrun/container/worker-pool:latest",
            "volume_mounts": [{
                "name": "nfs",
                "mount_path": "/mnt/nfs/filestore",
            }],
        }],
        "vpc_access": {
            "network_interfaces": [{
                "network": "default",
                "subnetwork": "default",
            }],
        },
        "volumes": [{
            "name": "nfs",
            "nfs": {
                "server": default_instance.networks[0].ip_addresses[0],
                "path": "/share1",
                "read_only": False,
            },
        }],
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		defaultInstance, err := filestore.NewInstance(ctx, "default", &filestore.InstanceArgs{
			Name:     pulumi.String("cloudrun-worker-pool"),
			Location: pulumi.String("us-central1-b"),
			Tier:     pulumi.String("BASIC_HDD"),
			FileShares: &filestore.InstanceFileSharesArgs{
				CapacityGb: pulumi.Int(1024),
				Name:       pulumi.String("share1"),
			},
			Networks: filestore.InstanceNetworkArray{
				&filestore.InstanceNetworkArgs{
					Network: pulumi.String("default"),
					Modes: pulumi.StringArray{
						pulumi.String("MODE_IPV4"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		_, err = cloudrunv2.NewWorkerPool(ctx, "default", &cloudrunv2.WorkerPoolArgs{
			Name:               pulumi.String("cloudrun-worker-pool"),
			Location:           pulumi.String("us-central1"),
			DeletionProtection: pulumi.Bool(false),
			LaunchStage:        pulumi.String("BETA"),
			Template: &cloudrunv2.WorkerPoolTemplateArgs{
				Containers: cloudrunv2.WorkerPoolTemplateContainerArray{
					&cloudrunv2.WorkerPoolTemplateContainerArgs{
						Image: pulumi.String("us-docker.pkg.dev/cloudrun/container/worker-pool:latest"),
						VolumeMounts: cloudrunv2.WorkerPoolTemplateContainerVolumeMountArray{
							&cloudrunv2.WorkerPoolTemplateContainerVolumeMountArgs{
								Name:      pulumi.String("nfs"),
								MountPath: pulumi.String("/mnt/nfs/filestore"),
							},
						},
					},
				},
				VpcAccess: &cloudrunv2.WorkerPoolTemplateVpcAccessArgs{
					NetworkInterfaces: cloudrunv2.WorkerPoolTemplateVpcAccessNetworkInterfaceArray{
						&cloudrunv2.WorkerPoolTemplateVpcAccessNetworkInterfaceArgs{
							Network:    pulumi.String("default"),
							Subnetwork: pulumi.String("default"),
						},
					},
				},
				Volumes: cloudrunv2.WorkerPoolTemplateVolumeArray{
					&cloudrunv2.WorkerPoolTemplateVolumeArgs{
						Name: pulumi.String("nfs"),
						Nfs: &cloudrunv2.WorkerPoolTemplateVolumeNfsArgs{
							Server: defaultInstance.Networks.ApplyT(func(networks []filestore.InstanceNetwork) (*string, error) {
								return &networks[0].IpAddresses[0], nil
							}).(pulumi.StringPtrOutput),
							Path:     pulumi.String("/share1"),
							ReadOnly: pulumi.Bool(false),
						},
					},
				},
			},
		})
		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 defaultInstance = new Gcp.Filestore.Instance("default", new()
    {
        Name = "cloudrun-worker-pool",
        Location = "us-central1-b",
        Tier = "BASIC_HDD",
        FileShares = new Gcp.Filestore.Inputs.InstanceFileSharesArgs
        {
            CapacityGb = 1024,
            Name = "share1",
        },
        Networks = new[]
        {
            new Gcp.Filestore.Inputs.InstanceNetworkArgs
            {
                Network = "default",
                Modes = new[]
                {
                    "MODE_IPV4",
                },
            },
        },
    });

    var @default = new Gcp.CloudRunV2.WorkerPool("default", new()
    {
        Name = "cloudrun-worker-pool",
        Location = "us-central1",
        DeletionProtection = false,
        LaunchStage = "BETA",
        Template = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateArgs
        {
            Containers = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerArgs
                {
                    Image = "us-docker.pkg.dev/cloudrun/container/worker-pool:latest",
                    VolumeMounts = new[]
                    {
                        new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateContainerVolumeMountArgs
                        {
                            Name = "nfs",
                            MountPath = "/mnt/nfs/filestore",
                        },
                    },
                },
            },
            VpcAccess = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateVpcAccessArgs
            {
                NetworkInterfaces = new[]
                {
                    new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateVpcAccessNetworkInterfaceArgs
                    {
                        Network = "default",
                        Subnetwork = "default",
                    },
                },
            },
            Volumes = new[]
            {
                new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateVolumeArgs
                {
                    Name = "nfs",
                    Nfs = new Gcp.CloudRunV2.Inputs.WorkerPoolTemplateVolumeNfsArgs
                    {
                        Server = defaultInstance.Networks.Apply(networks => networks[0].IpAddresses[0]),
                        Path = "/share1",
                        ReadOnly = false,
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.filestore.Instance;
import com.pulumi.gcp.filestore.InstanceArgs;
import com.pulumi.gcp.filestore.inputs.InstanceFileSharesArgs;
import com.pulumi.gcp.filestore.inputs.InstanceNetworkArgs;
import com.pulumi.gcp.cloudrunv2.WorkerPool;
import com.pulumi.gcp.cloudrunv2.WorkerPoolArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateArgs;
import com.pulumi.gcp.cloudrunv2.inputs.WorkerPoolTemplateVpcAccessArgs;
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 defaultInstance = new Instance("defaultInstance", InstanceArgs.builder()
            .name("cloudrun-worker-pool")
            .location("us-central1-b")
            .tier("BASIC_HDD")
            .fileShares(InstanceFileSharesArgs.builder()
                .capacityGb(1024)
                .name("share1")
                .build())
            .networks(InstanceNetworkArgs.builder()
                .network("default")
                .modes("MODE_IPV4")
                .build())
            .build());

        var default_ = new WorkerPool("default", WorkerPoolArgs.builder()
            .name("cloudrun-worker-pool")
            .location("us-central1")
            .deletionProtection(false)
            .launchStage("BETA")
            .template(WorkerPoolTemplateArgs.builder()
                .containers(WorkerPoolTemplateContainerArgs.builder()
                    .image("us-docker.pkg.dev/cloudrun/container/worker-pool:latest")
                    .volumeMounts(WorkerPoolTemplateContainerVolumeMountArgs.builder()
                        .name("nfs")
                        .mountPath("/mnt/nfs/filestore")
                        .build())
                    .build())
                .vpcAccess(WorkerPoolTemplateVpcAccessArgs.builder()
                    .networkInterfaces(WorkerPoolTemplateVpcAccessNetworkInterfaceArgs.builder()
                        .network("default")
                        .subnetwork("default")
                        .build())
                    .build())
                .volumes(WorkerPoolTemplateVolumeArgs.builder()
                    .name("nfs")
                    .nfs(WorkerPoolTemplateVolumeNfsArgs.builder()
                        .server(defaultInstance.networks().applyValue(_networks -> _networks[0].ipAddresses()[0]))
                        .path("/share1")
                        .readOnly(false)
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  default:
    type: gcp:cloudrunv2:WorkerPool
    properties:
      name: cloudrun-worker-pool
      location: us-central1
      deletionProtection: false
      launchStage: BETA
      template:
        containers:
          - image: us-docker.pkg.dev/cloudrun/container/worker-pool:latest
            volumeMounts:
              - name: nfs
                mountPath: /mnt/nfs/filestore
        vpcAccess:
          networkInterfaces:
            - network: default
              subnetwork: default
        volumes:
          - name: nfs
            nfs:
              server: ${defaultInstance.networks[0].ipAddresses[0]}
              path: /share1
              readOnly: false
  defaultInstance:
    type: gcp:filestore:Instance
    name: default
    properties:
      name: cloudrun-worker-pool
      location: us-central1-b
      tier: BASIC_HDD
      fileShares:
        capacityGb: 1024
        name: share1
      networks:
        - network: default
          modes:
            - MODE_IPV4

The volumes.nfs block specifies the Filestore server IP and export path. The vpcAccess configuration is required because Filestore uses private IP addresses. The volumeMounts array makes the NFS share available at /mnt/nfs/filestore, providing shared persistent storage across worker instances.

Beyond these examples

These snippets focus on specific worker pool features: container deployment and resource limits, VPC networking and storage mounts, and GPU acceleration and multi-container coordination. They’re intentionally minimal rather than full task processing systems.

The examples may reference pre-existing infrastructure such as Artifact Registry container images, Cloud SQL instances and Secret Manager secrets, VPC networks and subnets, and Cloud Storage buckets or Filestore instances. They focus on configuring the worker pool rather than provisioning everything around it.

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

  • Scaling configuration (minInstanceCount, maxInstanceCount)
  • Instance split allocation for traffic distribution
  • Binary Authorization for deployment policy
  • Liveness probes for container health monitoring

These omissions are intentional: the goal is to illustrate how each worker pool feature is wired, not provide drop-in task processing modules. See the Cloud Run WorkerPool resource reference for all available configuration options.

Let's configure GCP Cloud Run Worker Pools

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Deletion & Lifecycle
Why can't I delete my WorkerPool?
deletionProtection defaults to true, preventing deletion via pulumi up or terraform destroy. Set deletionProtection: false before attempting deletion.
What does the reconciling field mean?
reconciling indicates Cloud Run is asynchronously updating the WorkerPool to match your desired state. During reconciliation, fields like observedGeneration and latestReadyRevision may show transient values that don’t match your configuration.
What's the difference between latestCreatedRevision and latestReadyRevision?
latestCreatedRevision is the most recently created revision, while latestReadyRevision is the latest revision that’s actually serving traffic. During updates, these may differ temporarily.
What's the difference between generation and observedGeneration?
generation represents your desired state (increments with each update), while observedGeneration shows the generation currently serving traffic. They match when reconciliation completes successfully.
Configuration & Immutability
What fields can't I change after creating a WorkerPool?
location, name, and project are immutable. Changing these requires recreating the WorkerPool.
What happens if I don't specify instanceSplits?
If instanceSplits is empty or not provided, it defaults to 100% of instances assigned to the latest Ready Revision.
What launch stages are available?
Valid values are UNIMPLEMENTED, PRELAUNCH, EARLY_ACCESS, ALPHA, BETA, GA, and DEPRECATED. If you specify ALPHA but only use BETA/GA features, the output will show BETA.
Annotations & Labels
Why aren't my annotations and labels being removed when I delete them from my config?
annotations and labels are non-authoritative, meaning they only manage values in your configuration. Use effectiveAnnotations and effectiveLabels to see all annotations/labels, including those added by other tools.
What namespaces are forbidden for annotations and labels?
Cloud Run API v2 rejects annotations and labels with run.googleapis.com, cloud.googleapis.com, serving.knative.dev, or autoscaling.knative.dev namespaces. Use custom namespaces instead.
Secrets & Volumes
How do I mount secrets as files?
Create a volume with secret configuration (specifying secret, defaultMode, and items with version/path/mode), then add a volumeMount to your container pointing to that volume.
How do I connect to Cloud SQL?
Add a volume with cloudSqlInstance containing the connection name, mount it in your container, and grant the compute service account roles/secretmanager.secretAccessor for any secrets used.
What storage types can I mount as volumes?
You can mount Cloud SQL instances (cloudSqlInstance), secrets (secret), GCS buckets (gcs), NFS shares (nfs), and ephemeral storage (emptyDir).
Networking & VPC
How do I configure Direct VPC access?
Set template.vpcAccess.networkInterfaces with network, subnetwork, and optionally tags to connect your WorkerPool to VPC resources.
How do I mount an NFS share from Filestore?
Create a volume with nfs (server IP, path, readOnly), configure vpcAccess.networkInterfaces for VPC connectivity, then add a volumeMount to your container.
Containers & Health
How do I control container startup order?
Use the dependsOns field in a container to specify which other containers (by name) must start before it.
How do I configure health checks?
Use startupProbe for initial readiness and livenessProbe for ongoing health. Both support httpGet, tcpSocket, and grpc checks with configurable periodSeconds, timeoutSeconds, and failureThreshold.
How do I add GPU support?
Set resources.limits['nvidia.com/gpu'] to the GPU count, configure nodeSelector.accelerator (e.g., nvidia-l4), and optionally set gpuZonalRedundancyDisabled: true.
Deprecated Features
Should I use customAudiences?
No. customAudiences is deprecated and not applicable to WorkerPool resources. It will be removed in a future major release.

Using a different cloud?

Explore compute guides for other cloud providers: