Skip to content

Emit account_id and job metadata as Kubernetes pod labels#310

Open
wesleyjellis wants to merge 2 commits into
mainfrom
wesley/pod-name-account-id
Open

Emit account_id and job metadata as Kubernetes pod labels#310
wesleyjellis wants to merge 2 commits into
mainfrom
wesley/pod-name-account-id

Conversation

@wesleyjellis

@wesleyjellis wesleyjellis commented Jul 7, 2026

Copy link
Copy Markdown

Summary

Emit account/job metadata as Kubernetes pod labels rather than weaving it
into the pod name (which risks the 63-char limit and OpsLevel-side naming
conventions). This enables native DataDog filtering via podLabelsAsTags with
no pod-name parsing. The pod/ConfigMap/PDB name is unchanged.

Labels stamped on each job pod:

label value cardinality
app.kubernetes.io/name opslevel-job 1
opslevel.com/mode faktory | api 2
opslevel.com/account-id account id (when set) bounded by # accounts
opslevel.com/job-id job id unbounded — see note
opslevel.com/job-type job kind / template slug (when set) ~13

Labels are added after building the PDB label selector so they stay out of the
selector, which the app.kubernetes.io/instance label already makes unique.

Also adds a getRunnerJobVariable helper (named explicitly since a similar
helper is anticipated for egress proxies).

Fixes

  • ACCOUNT_ID lookup: the OpsLevel API uppercases/sanitizes variable keys
    before sending them (RunnerJobType#format_key_as_valid_env_var_name), so the
    account id arrives as ACCOUNT_ID, not account_id. The original lookup used
    the lowercase key and never matched, leaving the label always empty. Now
    matches the uppercase key.

Requires a companion OpsLevel change

opslevel.com/job-type is a no-op until the OpsLevel API emits a JOB_TYPE
variable.
The job's kind is its template (Runners::JobRun#template_name,
~13 values) and is currently only carried by the DB template_id column — it is
never sent to the runner. To light up the label, add a derived variable in
app/models/runners/job_run.rb#derived_variables (alongside JOB_ID /
ACCOUNT_ID):

{ "key" => "JOB_TYPE", "value" => template_name.demodulize.underscore, "sensitive" => false },
# e.g. "Runners::RepoGrepV1" -> "repo_grep_v1"

Sending a clean slug from the server keeps the label value valid (raw
template_name contains ::, which is invalid in a k8s label value) and
low-cardinality.

Cardinality note: opslevel.com/job-id is unbounded (one value per job).
It's fine as a k8s label (kubectl filtering) and as a DataDog log
attribute, but should not be mapped into podLabelsAsTags as a metric
tag. job-type is the opposite — low cardinality and ideal for tagging.

Test plan

  • go build ./...
  • go test ./pkg passes
  • TestGetRunnerJobVariable_* cover the helper, including a case-sensitivity
    guard for the ACCOUNT_ID bug

🤖 Generated with Claude Code

@wesleyjellis wesleyjellis self-assigned this Jul 7, 2026
Comment thread src/pkg/k8s.go Outdated
Comment thread src/pkg/k8s.go Outdated
Rather than weaving the account_id job variable into the pod name (which
risks the 63-char limit and OpsLevel-side naming conventions), stamp
descriptive labels on the job pod for observability:

  app.kubernetes.io/name:  opslevel-job
  opslevel.com/account-id: <account_id>  (when the job sets it)
  opslevel.com/job-id:     <job id>
  opslevel.com/mode:       <faktory|api>

These enable native DataDog filtering via podLabelsAsTags with no pod
name parsing. Labels are added after building the PDB label selector so
they stay out of the selector, which the instance label already makes
unique.

Adds a getRunnerJobVariable helper (named explicitly since a similar
helper is anticipated for egress proxies).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@wesleyjellis wesleyjellis force-pushed the wesley/pod-name-account-id branch from 3cc6b31 to 45b7d16 Compare July 10, 2026 14:59
The OpsLevel API uppercases/sanitizes variable keys before sending them
to the runner (RunnerJobType#format_key_as_valid_env_var_name), so the
account id arrives as ACCOUNT_ID, not account_id. The previous lookup
used the lowercase key and never matched, leaving opslevel.com/account-id
always empty. Match the uppercase key instead.

Also read a JOB_TYPE variable into an opslevel.com/job-type label so
pods can be filtered by job kind (template). This is a no-op until the
OpsLevel API emits JOB_TYPE as a derived variable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@wesleyjellis wesleyjellis changed the title Include account_id job variable in generated pod name Emit account_id and job metadata as Kubernetes pod labels Jul 10, 2026
@wesleyjellis wesleyjellis marked this pull request as ready for review July 10, 2026 15:50

@archf archf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is super cool, thanks a heap!

Let's also add a changie record and we're good to go!

Comment thread src/pkg/k8s.go
// name. Added after building the selector so they stay out of the PDB
// selector, which the instance label already makes unique.
labels["app.kubernetes.io/name"] = "opslevel-job"
labels["opslevel.com/job-id"] = id

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we 'dup' and add short form keys as well?

e.g.:

labels["accountiD"] = accountID ...
[...]

That would be cool for a CLI speedrun instead of typing out the long form.

e.g. kubectl get pods -l accountID=XXX

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants