Google Cloud CloudRun

Google Cloud CloudRun

Certified
Enterprise Edition

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.

yaml
type: io.kestra.plugin.ee.gcp.runner.CloudRun

Execute a Shell command.

yaml
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.

yaml
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.txt

Execute a task with Direct VPC Egress.

yaml
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).

yaml
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 /output

Stream container logs through the staging bucket instead of Cloud Logging, so concurrency is not capped by the Cloud Logging read quota.

yaml
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"; done

Reuse one stable Cloud Run job across runs instead of creating a fresh job each run.

yaml
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

GCP region

Region where the Cloud Run job executes.

Staging GCS bucket

Bucket used to upload input/namespace files and retrieve outputs; required when using file transfer or {{outputDir}}.

DefaultPT5S

Completion 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.

Defaulttrue

Delete job after completion

Defaults to true; set false to inspect runs but stale jobs may be reused.

Defaulttrue

Delete 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.

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).

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.

DefaultPT2S

Log 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.

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.

Default3

Max Cloud Run retries

Number of execution retries; defaults to 3.

VPC network

VPC network for Direct VPC Egress, for example projects/my-project/global/networks/my-vpc; cannot be used with vpcAccessConnector.

Reference (ref) of the pluginDefaults to apply to this task runner.

The GCP project ID

Container resource limits

CPU and memory limits for the Cloud Run container. If unset, Cloud Run defaults apply.

Definitions
cpustring

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

memorystring

Memory limit

Memory limit for the Cloud Run container. Examples: 512Mi, 1Gi, 2Gi, 4Gi. See https://cloud.google.com/run/docs/configuring/memory-limits

Defaulttrue

Resume 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.

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.

SubTypestring
Default["https://www.googleapis.com/auth/cloud-platform"]

The GCP scopes to be used

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.

VPC subnetwork

VPC subnetwork for Direct VPC Egress, for example projects/my-project/regions/europe-west1/subnetworks/my-subnet; cannot be used with vpcAccessConnector.

Whether to synchronize working directory from remote runner back to local one after run.

Defaultfalse

Stream 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.

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).

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.

Definitions
bucket*Requiredstring

GCS bucket name

Name of the Cloud Storage bucket to mount.

mountPath*Requiredstring

Container mount path

Absolute path inside the container where the bucket will be mounted.

readOnlybooleanstring
Defaultfalse

Read-only

If true, the volume is mounted read-only. Defaults to false.

VPC Access Connector

Full resource name for egress connector, e.g. projects/my-project/locations/europe-west1/connectors/my-connector.

Possible Values
VPC_EGRESS_UNSPECIFIEDALL_TRAFFICPRIVATE_RANGES_ONLYUNRECOGNIZED

VPC egress setting

PRIVATE_RANGES_ONLY or ALL_TRAFFIC; requires either vpcAccessConnector, network, or subnetwork.

DefaultPT5S

Post-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.

DefaultPT1H

Task 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).

Time spent draining late log entries after completion. Not emitted in useBucketForLog mode.

Log entries received from Cloud Logging, i.e. what Kestra read rather than what the container wrote. Not emitted in useBucketForLog mode.

Cloud Logging log polls issued, tagged with projectId and region. Not emitted in useBucketForLog mode.

Cloud Logging log polls that errored, the leading indicator of read-quota exhaustion. Not emitted in useBucketForLog mode.