|
| 1 | +# Google Cloud Run Worker |
| 2 | + |
| 3 | +Run a Temporal Worker on a [Google Cloud Run worker |
| 4 | +pool](https://cloud.google.com/run/docs/worker-pools) with two GCP plugins on |
| 5 | +one client. `temporalio.contrib.gcp.cloud_run.opentelemetry.OpenTelemetryPlugin` |
| 6 | +exports Temporal Core metrics and traces over OTLP/gRPC to a Google-Built |
| 7 | +OpenTelemetry Collector sidecar, which forwards traces to the Cloud Telemetry API |
| 8 | +and metrics to Google Managed Service for Prometheus; endpoint, service name |
| 9 | +(from `CLOUD_RUN_WORKER_POOL`), tracer provider, and 60s metric export are plugin |
| 10 | +defaults, and `worker.py` opts into `add_temporal_spans=True`. |
| 11 | +`temporalio.contrib.gcp.cloud_run.id.CloudRunIdPlugin` sets the client identity |
| 12 | +to `<instance_id>@<revision>` from Cloud Run instance metadata, so each container |
| 13 | +is individually identifiable as a poller. |
| 14 | + |
| 15 | +`CloudRunIdPlugin` is unreleased, so `pyproject.toml` pins `temporalio` to the |
| 16 | +SDK commit that adds it (a git source, which also builds inside the container); |
| 17 | +drop the `[tool.uv.sources]` override once it ships on PyPI. |
| 18 | + |
| 19 | +Prerequisites: a Temporal Cloud namespace and API key; a Google Cloud project |
| 20 | +with billing and an authenticated `gcloud` CLI; `envsubst` (`gettext` package). |
| 21 | +Worker pools bill continuously, so scale to zero after testing (see below). |
| 22 | + |
| 23 | +## Deploy |
| 24 | + |
| 25 | +Run from the repository root. Set your own values (also used by the verify step |
| 26 | +below), then run the deploy script: |
| 27 | + |
| 28 | +```bash |
| 29 | +export PROJECT_ID=your-project-id REGION=us-central1 |
| 30 | +export REPOSITORY=temporal-workers WORKER_POOL=temporal-gcp-cloud-run |
| 31 | +export SERVICE_ACCOUNT_EMAIL="cloud-run-worker@${PROJECT_ID}.iam.gserviceaccount.com" |
| 32 | +export TEMPORAL_NAMESPACE=your-namespace.account-id |
| 33 | +export TEMPORAL_ADDRESS="${TEMPORAL_NAMESPACE}.tmprl.cloud:7233" |
| 34 | +export TEMPORAL_TASK_QUEUE=gcp-cloud-run |
| 35 | +export TEMPORAL_API_KEY_FILE=/secure/path/to/temporal-api-key |
| 36 | +export TEMPORAL_API_KEY_SECRET=temporal-api-key TEMPORAL_API_KEY_SECRET_VERSION=1 |
| 37 | +export COLLECTOR_CONFIG_SECRET=temporal-otel-collector COLLECTOR_CONFIG_SECRET_VERSION=1 |
| 38 | +export WORKER_IMAGE="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/gcp-cloud-run:v1" |
| 39 | +export INSTANCE_COUNT=1 |
| 40 | + |
| 41 | +./gcp/cloud_run/deploy.sh |
| 42 | +``` |
| 43 | + |
| 44 | +`deploy.sh` enables the required APIs; creates the Artifact Registry repo, the |
| 45 | +runtime service account, and the API key and collector-config secrets; grants the |
| 46 | +telemetry and secret-access roles; then builds the image and deploys the |
| 47 | +two-container worker pool. The create steps are one-time and re-run safely. |
| 48 | + |
| 49 | +Worker pools bill continuously, so scale to zero when done testing: |
| 50 | + |
| 51 | +```bash |
| 52 | +gcloud run worker-pools update "$WORKER_POOL" --instances 0 \ |
| 53 | + --region "$REGION" --project "$PROJECT_ID" |
| 54 | +``` |
| 55 | + |
| 56 | +## Run a Workflow and verify |
| 57 | + |
| 58 | +```bash |
| 59 | +TEMPORAL_API_KEY="$(cat "$TEMPORAL_API_KEY_FILE")" \ |
| 60 | + uv run python -m gcp.cloud_run.starter |
| 61 | +``` |
| 62 | + |
| 63 | +The starter prints `Hello, Temporal!`. In Google Cloud, Trace Explorer shows |
| 64 | +`RunWorkflow:GreetingWorkflow` (with `service.name` = the worker-pool name) and |
| 65 | +Metrics Explorer shows |
| 66 | +`prometheus.googleapis.com/temporal_workflow_completed_total/counter`. In the |
| 67 | +Temporal UI, the task queue's pollers report the `<instance_id>@<revision>` |
| 68 | +identity set by `CloudRunIdPlugin`. |
0 commit comments