
Google Cloud CloudRun
CertifiedEnterprise EditionRun tasks on Google Cloud Run
Google Cloud CloudRun
Run tasks on Google Cloud Run
Enterprise-only task runner that launches the container image as a Cloud Run Job; requires the Cloud Run Developer (roles/run.developer) role, and the Logs Viewer (roles/logging.viewer) role unless useBucketForLog is enabled.
Uses a GCS bucket to stage input/namespace files and collect outputs (required when using those features), polls every 5s by default, and times out after 1h unless the task timeout overrides it.
The container starts in the root directory (use {{workingDir}} / WORKING_DIR); jobs default to deleting on completion and resuming existing executions when labels match, unless jobName is set, in which case one stable job is reused across runs and never deleted. To generate output files, you can either use the outputFiles task's property and create a file with the same name in the task's working directory, or create any file in the output directory which can be accessed by the {{outputDir}} Pebble expression or the OUTPUT_DIR environment variables.
To use inputFiles, outputFiles, or namespaceFiles properties, make sure to set the bucket property. The bucket serves as an intermediary storage layer for the task runner. Input and namespace files will be uploaded to the cloud storage bucket before the task run. Similarly, the task runner will store outputFiles in this bucket during the task run. In the end, the task runner will make those files available for download and preview from the UI by sending them to internal storage.
The task runner will generate a folder in the configured bucket for each task run. You can access that folder using the {{ bucketPath }} Pebble expression or the BUCKET_PATH environment variable.
By default the container's output is read back from Cloud Logging, whose read path is limited to 60 requests per minute per GCP project — a quota Google does not increase — which in practice caps you at a handful of concurrent Cloud Run tasks per project before log lines, and therefore task outputs, start going missing. Set useBucketForLog: true to have the container write its own stdout/stderr into the staging bucket instead, as immutable chunk files that Kestra streams as they appear. Cloud Storage meters reads per bucket rather than per project, so this scales with concurrency; it requires bucket to be set, needs the Cloud Run runtime service account to have write access to it, and lets Kestra read logs from the bucket instead of Cloud Logging, which is what removes the read-quota ceiling (so roles/logging.viewer is not needed for reads). Cloud Run still ships the container's console output to Cloud Logging as usual, so logs and task outputs also remain there and incur its ingestion cost. Log files live under the task's own working-directory prefix and are removed with it.
Warning: contrary to other task runners, this task runner didn't run the task in the working directory but in the root directory. You must use the {{ workingDir }} Pebble expression or the WORKING_DIR environment variable to access files.
The waitUntilCompletion property maps directly to the GCP "Task timeout" field (visible in the GCP console under Task capacity). It is applied both to the job template and to the per-run override, so the Cloud Run task will be forcibly terminated by GCP when this duration elapses. The Kestra task-level timeout property takes precedence over waitUntilCompletion when set.
Note that when the Kestra Worker running this task is terminated, the Cloud Run Job will still run until completion.
type: io.kestra.plugin.ee.gcp.runner.CloudRunExamples
Execute a Shell command.
id: new-shell
namespace: company.team
variables:
projectId: "projectId"
region: "europe-west2"
tasks:
- id: shell
type: io.kestra.plugin.scripts.shell.Commands
taskRunner:
type: io.kestra.plugin.ee.gcp.runner.CloudRun
projectId: "{{ vars.projectId }}"
region: "{{ vars.region }}"
serviceAccount: "{{ secret('GOOGLE_SA') }}"
commands:
- echo "Hello World"Pass input files to the task, execute a Shell command, then retrieve output files.
id: new-shell-with-file
namespace: company.team
inputs:
- id: file
type: FILE
variables:
projectId: "projectId"
bucket: "bucket"
region: "europe-west2"
tasks:
- id: shell
type: io.kestra.plugin.scripts.shell.Commands
inputFiles:
data.txt: "{{ inputs.file }}"
outputFiles:
- out.txt
containerImage: centos
taskRunner:
type: io.kestra.plugin.ee.gcp.runner.CloudRun
projectId: "{{ vars.projectId }}"
region: "{{ vars.region }}"
bucket: "{{ vars.bucket }}"
serviceAccount: "{{ secret('GOOGLE_SA') }}"
commands:
- cp {{ workingDir }}/data.txt {{ workingDir }}/out.txtExecute a task with Direct VPC Egress.
id: shell-direct-vpc-egress
namespace: company.team
variables:
projectId: "projectId"
region: "europe-west1"
network: "projects/projectId/global/networks/my-vpc"
subnetwork: "projects/projectId/regions/europe-west1/subnetworks/my-subnet"
tasks:
- id: shell
type: io.kestra.plugin.scripts.shell.Commands
taskRunner:
type: io.kestra.plugin.ee.gcp.runner.CloudRun
projectId: "{{ vars.projectId }}"
region: "{{ vars.region }}"
network: "{{ vars.network }}"
subnetwork: "{{ vars.subnetwork }}"
vpcEgress: ALL_TRAFFIC
serviceAccount: "{{ secret('GOOGLE_SA') }}"
commands:
- echo "Hello from Direct VPC Egress"Mount GCS buckets as volumes (read-only or read-write).
id: shell-with-gcs-volume
namespace: company.team
variables:
projectId: "projectId"
region: "europe-west1"
tasks:
- id: shell
type: io.kestra.plugin.scripts.shell.Commands
taskRunner:
type: io.kestra.plugin.ee.gcp.runner.CloudRun
projectId: "{{ vars.projectId }}"
region: "{{ vars.region }}"
serviceAccount: "{{ secret('GOOGLE_SA') }}"
volumes:
- bucket: my-reference-data-bucket
mountPath: /data
readOnly: true
- bucket: my-output-bucket
mountPath: /output
commands:
- ls /data
- ls /outputStream container logs through the staging bucket instead of Cloud Logging, so concurrency is not capped by the Cloud Logging read quota.
id: shell-with-bucket-logs
namespace: company.team
variables:
projectId: "projectId"
region: "europe-west1"
bucket: "bucket"
tasks:
- id: shell
type: io.kestra.plugin.scripts.shell.Commands
taskRunner:
type: io.kestra.plugin.ee.gcp.runner.CloudRun
projectId: "{{ vars.projectId }}"
region: "{{ vars.region }}"
bucket: "{{ vars.bucket }}"
serviceAccount: "{{ secret('GOOGLE_SA') }}"
useBucketForLog: true
logFlushInterval: PT2S
commands:
- for i in $(seq 1 1000); do echo "line $i"; doneReuse one stable Cloud Run job across runs instead of creating a fresh job each run.
id: shell-reusing-a-job
namespace: company.team
variables:
projectId: "projectId"
region: "europe-west1"
tasks:
- id: shell
type: io.kestra.plugin.scripts.shell.Commands
taskRunner:
type: io.kestra.plugin.ee.gcp.runner.CloudRun
projectId: "{{ vars.projectId }}"
region: "{{ vars.region }}"
serviceAccount: "{{ secret('GOOGLE_SA') }}"
jobName: my-team-cloud-run-job
commands:
- echo "Hello from a reused job"Properties
region *Requiredstring
GCP region
Region where the Cloud Run job executes.
bucket string
Staging GCS bucket
Bucket used to upload input/namespace files and retrieve outputs; required when using file transfer or {{outputDir}}.
completionCheckInterval string
PT5SCompletion poll interval
How often to poll the execution status, and the default cadence for log polling unless logPollInterval overrides it. Defaults to PT5S. Lower for short jobs, higher to reduce API calls.
delete booleanstring
trueDelete job after completion
Defaults to true; set false to inspect runs but stale jobs may be reused.
deleteLogs booleanstring
trueDelete container log files from the bucket after the task
Only applies when useBucketForLog is true. When true (default), the log chunk files kotlp wrote into the staging bucket are removed during cleanup along with the other staged files. Set false to keep them in the bucket for audit or later inspection, in which case they are preserved even when delete is true. Has no effect unless useBucketForLog is enabled, and no effect when delete is false, since no cleanup runs then. Defaults to true.
impersonatedServiceAccount string
The GCP service account to impersonate
Service account email to impersonate for API calls.
For Cloud Run runner, this value applies to API calls used to create and run the job (--impersonate-service-account equivalent).
It does not set the job execution identity (--service-account).
jobName string
Reuse a stable Cloud Run job instead of creating one per run
Reuse a single Cloud Run Job with this name across runs instead of creating and deleting one per run. The job is created once if absent, each run submits an execution with its command and working directory as per-run overrides, and only the execution is deleted, never the job.
Removes the 1,000-jobs-per-project cap and roughly halves Admin API writes. The container image, resources, volumes, VPC, service account, maxRetries and the baked command are fixed at first creation and ignored afterwards until the job is deleted and recreated. useBucketForLog and logFlushInterval are part of that command, so changing them has no effect on an existing job, and changing useBucketForLog is rejected rather than ignored. resume does not apply: a worker crash starts a new execution instead of reattaching. Leave unset to create and delete a job per run.
logFlushInterval string
PT2SLog chunk flush interval
Only used when useBucketForLog is true. How often the current log chunk file is rotated, and also how often Kestra polls the bucket for new chunks — so the worst-case delay before a line reaches Kestra is about twice this value, and it is also the sampling period for the CPU/memory/IO metrics kotlp reports. Rounded up to whole seconds, with a floor of one second, because POSIX sleep is only required to accept integers. Defaults to PT2S.
logPollInterval string
Log poll interval
How often to poll Cloud Logging for new container log lines, independent of the execution-status poll. Defaults to completionCheckInterval when unset. Cloud Logging's read path is capped at 60 requests per minute per project (a limit Google does not raise), while status polling has far more headroom, so raise this alone to relieve the log read quota at high concurrency without slowing completion detection. Has no effect when useBucketForLog is true, where logs are read from the bucket at logFlushInterval.
maxRetries integerstring
3Max Cloud Run retries
Number of execution retries; defaults to 3.
network string
VPC network
VPC network for Direct VPC Egress, for example projects/my-project/global/networks/my-vpc; cannot be used with vpcAccessConnector.
pluginDefaultsRef Non-dynamicstring
Reference (ref) of the pluginDefaults to apply to this task runner.
projectId string
The GCP project ID
resources Non-dynamic
Container resource limits
CPU and memory limits for the Cloud Run container. If unset, Cloud Run defaults apply.
io.kestra.plugin.ee.gcp.runner.CloudRun-ContainerResources
CPU limit
CPU limit for the Cloud Run container. Examples: 1, 2, 4, 8 (vCPUs) or 1000m (millicores). See https://cloud.google.com/run/docs/configuring/cpu
Memory limit
Memory limit for the Cloud Run container. Examples: 512Mi, 1Gi, 2Gi, 4Gi. See https://cloud.google.com/run/docs/configuring/memory-limits
resume booleanstring
trueResume existing job
If true (default), reattach to an already-running execution of a matching job so a restarted worker resumes instead of re-running the task. This does not reuse job definitions across task runs. When enabled, a listJobs call is made on every task start to look for a match, and its cost grows with the project's job inventory. Ignored when jobName is set: reused jobs do not use label-based resume yet.
If Cloud Run already removed the execution, a useBucketForLog run is recovered from the bucket instead of re-run, reported as adopted in the output. The default transport cannot recover it, so the task re-runs and its side effects happen twice. A new definition is created only when neither applies.
runtimeServiceAccount string
Cloud Run runtime service account
Service account email used as the Cloud Run Job execution identity (--service-account equivalent).
This only controls runtime identity for the job's container and does not affect API authentication.
If unset, the runner falls back to serviceAccount for backward compatibility.
scopes array
["https://www.googleapis.com/auth/cloud-platform"]The GCP scopes to be used
serviceAccount string
The GCP service account key
Service account JSON key used to authenticate API calls.
For Cloud Run runner job execution identity, this value is used as a fallback for --service-account
when runtimeServiceAccount is not provided.
subnetwork string
VPC subnetwork
VPC subnetwork for Direct VPC Egress, for example projects/my-project/regions/europe-west1/subnetworks/my-subnet; cannot be used with vpcAccessConnector.
syncWorkingDirectory booleanstring
Whether to synchronize working directory from remote runner back to local one after run.
useBucketForLog booleanstring
falseStream container logs through the staging bucket
If true, the container writes its own stdout/stderr into the staging bucket as a sequence of immutable chunk files that Kestra streams as they appear, instead of Kestra reading them back from Cloud Logging. Requires bucket, and requires the Cloud Run runtime service account to be able to write to it.
Cloud Logging's read path allows 60 requests per minute per GCP project and Google does not raise that limit, so the default log transport caps you at roughly five concurrent Cloud Run tasks per project — beyond which log lines, and therefore the task outputs that travel as log lines, are silently lost. Cloud Storage meters reads per bucket in the thousands per second, so enable this when you run more than a handful of Cloud Run tasks in parallel.
Concurrency is not the only reason to enable it: Cloud Logging gives no completeness guarantee at any concurrency, so a line can be indexed after the runner stops reading and is lost with no error. This is the only transport that knows whether it received everything, because Kestra checks the chunk sequence against the record kotlp writes on exit.
Under the hood this wraps the container's command with kotlp, a small binary Kestra stages into the working directory automatically — no image change required — which also samples the container's CPU, memory, disk I/O, and open file descriptors and reports them as Kestra task metrics.
Trade-offs: it is fail-closed, so an incomplete log stream fails the task instead of reporting success with missing output; a container killed outright (out-of-memory, or the Cloud Run task timeout) fails that way and may also lose its last logFlushInterval of output; and the image must provide a POSIX /bin/sh. Cloud Run still ships the console output to Cloud Logging, so it stays there and incurs ingestion cost. Defaults to false.
version Non-dynamicstring
Plugin Version
Defines the version of the plugin to use.
The version must follow the Semantic Versioning (SemVer) specification:
- A single-digit MAJOR version (e.g.,
1). - A MAJOR.MINOR version (e.g.,
1.1). - A MAJOR.MINOR.PATCH version, optionally with any qualifier
(e.g.,
1.1.2,1.1.0-SNAPSHOT).
volumes Non-dynamicarray
Additional GCS bucket volumes
List of GCS buckets to mount as volumes inside the container. Each entry requires a bucket name and a container mount path. Set readOnly: true for read-only access; omit or set readOnly: false (the default) for read-write access.
io.kestra.plugin.ee.gcp.runner.CloudRun-GcsBucketVolume
GCS bucket name
Name of the Cloud Storage bucket to mount.
Container mount path
Absolute path inside the container where the bucket will be mounted.
falseRead-only
If true, the volume is mounted read-only. Defaults to false.
vpcAccessConnector string
VPC Access Connector
Full resource name for egress connector, e.g. projects/my-project/locations/europe-west1/connectors/my-connector.
vpcEgress string
VPC_EGRESS_UNSPECIFIEDALL_TRAFFICPRIVATE_RANGES_ONLYUNRECOGNIZEDVPC egress setting
PRIVATE_RANGES_ONLY or ALL_TRAFFIC; requires either vpcAccessConnector, network, or subnetwork.
waitForLogInterval string
PT5SPost-completion log wait
Quiet period after the job ends: Kestra keeps polling for new log entries until none have arrived for this long, then finalizes logs and outputs; defaults to PT5S.
waitUntilCompletion string
PT1HTask timeout
Maps to the GCP "Task timeout" field visible in the GCP console under Task capacity. Controls both the GCP-enforced task timeout (applied to the job template and the per-run override) and the Kestra polling timeout — the Cloud Run task is forcibly terminated by GCP when this duration elapses. The Kestra task-level timeout property takes precedence over this value when set. Defaults to PT1H. GCP maximum is 168 hours (PT168H).
Metrics
cloudlogging.drain.duration timer
Time spent draining late log entries after completion. Not emitted in useBucketForLog mode.
cloudlogging.entries.received counter
Log entries received from Cloud Logging, i.e. what Kestra read rather than what the container wrote. Not emitted in useBucketForLog mode.
cloudlogging.polls.issued counter
Cloud Logging log polls issued, tagged with projectId and region. Not emitted in useBucketForLog mode.
cloudlogging.polls.rejected counter
Cloud Logging log polls that errored, the leading indicator of read-quota exhaustion. Not emitted in useBucketForLog mode.