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 FREEFrequently Asked Questions
Deletion & Lifecycle
deletionProtection defaults to true, preventing deletion via pulumi up or terraform destroy. Set deletionProtection: false before attempting deletion.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.latestCreatedRevision is the most recently created revision, while latestReadyRevision is the latest revision that’s actually serving traffic. During updates, these may differ temporarily.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
location, name, and project are immutable. Changing these requires recreating the WorkerPool.instanceSplits is empty or not provided, it defaults to 100% of instances assigned to the latest Ready Revision.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
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.run.googleapis.com, cloud.googleapis.com, serving.knative.dev, or autoscaling.knative.dev namespaces. Use custom namespaces instead.Secrets & Volumes
secret configuration (specifying secret, defaultMode, and items with version/path/mode), then add a volumeMount to your container pointing to that volume.cloudSqlInstance containing the connection name, mount it in your container, and grant the compute service account roles/secretmanager.secretAccessor for any secrets used.cloudSqlInstance), secrets (secret), GCS buckets (gcs), NFS shares (nfs), and ephemeral storage (emptyDir).Networking & VPC
template.vpcAccess.networkInterfaces with network, subnetwork, and optionally tags to connect your WorkerPool to VPC resources.nfs (server IP, path, readOnly), configure vpcAccess.networkInterfaces for VPC connectivity, then add a volumeMount to your container.Containers & Health
dependsOns field in a container to specify which other containers (by name) must start before it.startupProbe for initial readiness and livenessProbe for ongoing health. Both support httpGet, tcpSocket, and grpc checks with configurable periodSeconds, timeoutSeconds, and failureThreshold.resources.limits['nvidia.com/gpu'] to the GPU count, configure nodeSelector.accelerator (e.g., nvidia-l4), and optionally set gpuZonalRedundancyDisabled: true.Deprecated Features
customAudiences is deprecated and not applicable to WorkerPool resources. It will be removed in a future major release.