Overview
Control Plane Task Runner is a self-hosted HTTP task queue and scheduler, similar to Google Cloud Tasks. You enqueue a task over HTTP and the workers deliver it to its target URL, with automatic retries, delayed and scheduled execution, per-client rate limiting and a circuit breaker. This template deploys the API, the workers, and the Redis Sentinel cluster they persist to.What Gets Created
reveal permission on secrets. The template’s identities have no cloud access and no permission on any other Control Plane resource.
Prerequisites
Three secrets must exist before you install: the Redis password, the Sentinel password and the admin API key. Secrets are org-level, so no GVC flag is involved.Create the Redis and Sentinel credentials secrets
password: one holds the bundled Redis password, the other the Sentinel password. Redis, Sentinel, the API and the worker read both. The names below are the chart defaults for redis.redis.auth.fromSecret.name and redis.sentinel.auth.fromSecret.name:Create the admin key secret
/admin/* endpoints create, edit and delete clients and rate-limit tiers, and they are guarded by the X-Admin-Key header. The key is an opaque secret with encoding plain whose payload is the key itself:printf, not echo. A trailing newline from echo becomes part of the key and then has to be sent in every admin request. Set api.admin.apiKeySecretName to this name.Read the key back later
-o yaml. A bare cpln secret reveal prints only a summary table, not the payload:Installation
Create the three secrets first, then install with the admin key secret’s name. If you named the credentials secrets differently from the defaults, also setredis.redis.auth.fromSecret.name and redis.sentinel.auth.fromSecret.name:
UI
CLI
Terraform
Pulumi
Configuration
Image
The same image runs both the API and the worker:API Workload
api.admin.apiKeySecretName to "" turns admin authentication off entirely. The chart permits that only while api.public.enabled is false.
Worker Workload
allowPrivateUrls: false is what keeps an enqueued task off internal addresses.
Secrets and Redis
Redis and Sentinel read their passwords from the prerequisite credentials secrets:api.admin.apiKeySecretName.
Connecting
/health/ready path as the workload readiness probe:
Enqueuing Tasks
Post a task to/v1/enqueue. With the default private API, send it from a workload in the same GVC to http://RELEASE_NAME-task-runner-api.GVC_NAME.cpln.local:8080, or through the tunnel above to http://127.0.0.1:8080:
Admin Endpoints
Every/admin/* request needs the X-Admin-Key header, whose value is the payload of your api.admin.apiKeySecretName secret:
Rate Limiting
Rate limits apply per client, and a client tier is assigned through the admin API:OpenTelemetry
SetotelEndpoint under api.env and worker.env to export traces. In the GVC settings, set the Tracing Provider to Control Plane, then use the built-in HTTP collector endpoint:
Operations
Backing Up
The Redis volume setRELEASE_NAME-redis-vs takes a snapshot every day and keeps each one for 7 days. List the snapshots:
Restoring a Backup
A restore procedure for this template has not been verified. Do not rely on the snapshots as a tested recovery path for queued tasks.Rotating the Admin Key
Apply the whole secret with a new payload, confirm it, then force a redeployment of the API. A running replica keeps the old key until it is redeployed:Rotating the Redis and Sentinel Passwords
Redis reads its password from the secret at every start, but Sentinel keeps the passwords it first started with on its volume, so editing the secrets alone locks the API and worker out. Apply the new passwords live on every node first, then restart the API and worker.rx and sx run a command on one Redis node or Sentinel (LOCATION is your GVC’s location; nodes and Sentinels are numbered from 0 up to redis.redis.replicas and redis.sentinel.replicas minus one).
- Accept the new passwords alongside the old ones on every Redis node and Sentinel:
- Put the new passwords in the two secrets (key
password). For each secret, export it, change onlypassword, apply it and read it back:
- Restart the API and worker, which keep the old passwords until they restart:
- Once
get-deploymentsshows both at a higher version, alone and ready, retire the old passwords and check that the Sentinels can still fail over:
fromSecret.name values point at one secret, edit that one secret in step 2, each password under its own key.
Upgrading From 1.2.x
Two defaults change, and both break an existing workflow that relied on the old behaviour.api.env.adminApiKey or redis.admin.fromSecret, or an empty apiKeySecretName while public access is on, is rejected at render before anything is applied.
Create the admin key secret
Drop the removed keys from your values
api.env.adminApiKey and redis.admin.fromSecret, and set api.admin.apiKeySecretName instead.Decide about public access
api.public.enabled now defaults to false. Read Public Access and the Open Queue before setting it back to true.Upgrade
mypassword if never changed) go into the two credentials secrets.
Upgrading From 1.3.0
1.4.0 no longer takes the Redis and Sentinel passwords as values, and no longer creates thetask-runner-secrets secret. Use the CURRENT passwords: Redis and Sentinel keep the ones they started with, so new ones would lock the API and worker out. To change them, upgrade first, then follow Rotating the Redis and Sentinel Passwords.
With createSecret: true (the default), the upgrade deletes task-runner-secrets (or the secret named by your secretName, if you changed it), so copy the passwords into two new secrets before upgrading:
Read the current passwords
redis-password is the Redis password, redis-sentinel-password the Sentinel password. Use the name you set in secretName if you changed it:Create the two credentials secrets with those values
Drop the removed keys from your values
createSecret, secretName, redis.redisPassword and redis.sentinelPassword, and point redis.redis.auth.fromSecret.name and redis.sentinel.auth.fromSecret.name at the new secrets (the defaults above). The chart refuses to render while any of the removed keys is still set, and refuses the name task-runner-secrets; do not reuse a custom secretName either, because the upgrade deletes that secret too.Upgrade
createSecret: false and a secret of your own, keep it: remove the same four keys, keep both fromSecret.name values pointing at your secret, and set both passwordKey values to its key names explicitly (redis-password and redis-sentinel-password if you kept the 1.3.0 defaults; 1.4.0 defaults both to password). Nothing is deleted.
Public Access and the Open Queue
api.public.enabled is false by default. Turning it on exposes the following:
/v1/enqueuerequires no credential. There is no header, token or signature to supply.- An unknown
client_idis auto-registered, not rejected. A client ID is therefore not a secret and not a control. - The API becomes a request relay. Anyone reaching it can make a worker send outbound HTTP with the method, headers and body they choose.
worker.env.allowPrivateUrls: falsekeeps those requests off internal addresses. /metricsis unauthenticated and its labels list everyclient_id.
api.public.enabled at false. Access changes can take several minutes to take effect, so re-test over that window.
Scaling and Availability
The API and worker are serverless workloads that autoscale on concurrent requests withinapi.replicas and worker.replicas. Raise worker.replicas.max or worker.env.concurrency for more delivery throughput. Redis runs as three replicas with three Sentinels, which elect a new primary if the current one fails.
Troubleshooting
The API workload never starts and cpln logs returns nothing
The API workload never starts and cpln logs returns nothing
api.admin.apiKeySecretName, or a Redis or Sentinel credentials secret. get-deployments shows The secret SECRET_NAME no longer exists. Workload updates are paused until the secret is added or the reference to the secret removed.Fix: create the secret as in Prerequisites. The workload recovers on its own, or run cpln workload force-redeployment RELEASE_NAME-task-runner-api --gvc GVC_NAME.Install fails with apiKeySecretName is empty while api.public.enabled is true
Install fails with apiKeySecretName is empty while api.public.enabled is true
api.admin.apiKeySecretName is "" and public access is on. The chart refuses to publish unauthenticated admin endpoints.Fix: set api.admin.apiKeySecretName to your admin key secret, or set api.public.enabled: false.Install or upgrade fails with api.env.adminApiKey was REMOVED
Install or upgrade fails with api.env.adminApiKey was REMOVED
api.env.adminApiKey or redis.admin.fromSecret).Fix: follow Upgrading From 1.2.x.Install or upgrade fails with Removed in cpln-task-runner 1.4.0
Install or upgrade fails with Removed in cpln-task-runner 1.4.0
createSecret, secretName, redis.redisPassword or redis.sentinelPassword.Fix: follow Upgrading From 1.3.0.Admin requests are rejected
Admin requests are rejected
X-Admin-Key header is missing or does not match the secret payload, for example because the key was created with echo and carries a trailing newline, or the secret was rotated without a redeployment.Fix: read the key with cpln secret reveal SECRET_NAME -o yaml, and redeploy the API after any rotation.Tasks to internal addresses are never delivered
Tasks to internal addresses are never delivered
worker.env.allowPrivateUrls is false, so workers refuse private and internal targets.Fix: set it to true only if you accept that any enqueued task can then reach anything the worker can route to.Important Notes
- Create the admin key secret and the Redis and Sentinel credentials secrets before installing. A missing secret wedges the workloads that read it with no log output; the reason is in
status.versions[].messagefromcpln workload get-deployments. - Leave
api.public.enabledatfalseunless an authenticating proxy fronts the API./v1/enqueueis unauthenticated and auto-registers unknown client IDs. - Never change the Redis or Sentinel password by editing the secrets alone. Sentinel keeps the passwords it first started with on its volume, so that locks the API and worker out. Follow Rotating the Redis and Sentinel Passwords.
- Force a redeployment after rotating the admin key. A running replica keeps the old key.