Context
SeiNodeDeployment.spec.template.metadata.labels is a footgun for anyone coming from Kubernetes Deployment semantics.
In a stock K8s Deployment:
spec.template.metadata.labels → pod labels (what you select with kubectl get pods -l ...)
In SeiNodeDeployment today:
spec.template.metadata.labels → labels on the owned SeiNode CR only
spec.template.spec.podLabels → labels that actually land on pods
This inverts a strong, widely-internalized Kubernetes convention. We hit it while writing the autobake smoke-test workflow — the probe step used labels declared in template.metadata.labels expecting them on pods, kubectl returned zero matches, run failed. See sei-protocol/platform#110 for the symptom.
Call sites
internal/controller/nodedeployment/labels.go:65-66 — applies template.metadata.labels to SeiNode resources
internal/controller/nodedeployment/nodes.go:224-228 — auto-injects sei.io/nodedeployment + revision into SeiNode.Spec.PodLabels
internal/noderesource/noderesource.go:52-57 — ResourceLabels reads from SeiNode.Spec.PodLabels for the StatefulSet pod template
So only template.spec.podLabels reaches pods. Anything in template.metadata.labels is applied to the SeiNode CR and stops there.
Options
A. Also propagate template.metadata.labels onto pods — makes SND feel like Deployment. Low risk: these labels already get added to SeiNode metadata, adding them to PodLabels as well is a strict superset. Provider owns the interface, so consumers only gain labels they already expected.
B. Prominent CRD schema description + godoc comment — cheaper, preserves current semantics. Relies on every future consumer reading the schema carefully before using the field.
C. Reject template.metadata.labels at admission — force callers to use podLabels explicitly. Breaks existing consumers.
My lean is A: it costs little, removes the trap, and aligns with the most common K8s mental model.
Acceptance (for option A)
template.metadata.labels keys appear on both the child SeiNode CR and the pods it creates
template.spec.podLabels still works as today (keys still apply to pods)
- Conflict policy:
template.spec.podLabels wins over template.metadata.labels on key collision (explicit beats implicit), or flag the conflict at admission
- System labels (
sei.io/nodedeployment, revision) still set last so they can't be overridden
- Unit test in
internal/controller/nodedeployment/ covering the merge order
Context
SeiNodeDeployment.spec.template.metadata.labelsis a footgun for anyone coming from KubernetesDeploymentsemantics.In a stock K8s
Deployment:spec.template.metadata.labels→ pod labels (what you select withkubectl get pods -l ...)In
SeiNodeDeploymenttoday:spec.template.metadata.labels→ labels on the owned SeiNode CR onlyspec.template.spec.podLabels→ labels that actually land on podsThis inverts a strong, widely-internalized Kubernetes convention. We hit it while writing the autobake smoke-test workflow — the probe step used labels declared in
template.metadata.labelsexpecting them on pods, kubectl returned zero matches, run failed. See sei-protocol/platform#110 for the symptom.Call sites
internal/controller/nodedeployment/labels.go:65-66— appliestemplate.metadata.labelsto SeiNode resourcesinternal/controller/nodedeployment/nodes.go:224-228— auto-injectssei.io/nodedeployment+ revision intoSeiNode.Spec.PodLabelsinternal/noderesource/noderesource.go:52-57—ResourceLabelsreads fromSeiNode.Spec.PodLabelsfor the StatefulSet pod templateSo only
template.spec.podLabelsreaches pods. Anything intemplate.metadata.labelsis applied to the SeiNode CR and stops there.Options
A. Also propagate
template.metadata.labelsonto pods — makes SND feel likeDeployment. Low risk: these labels already get added to SeiNode metadata, adding them toPodLabelsas well is a strict superset. Provider owns the interface, so consumers only gain labels they already expected.B. Prominent CRD schema description + godoc comment — cheaper, preserves current semantics. Relies on every future consumer reading the schema carefully before using the field.
C. Reject
template.metadata.labelsat admission — force callers to usepodLabelsexplicitly. Breaks existing consumers.My lean is A: it costs little, removes the trap, and aligns with the most common K8s mental model.
Acceptance (for option A)
template.metadata.labelskeys appear on both the child SeiNode CR and the pods it createstemplate.spec.podLabelsstill works as today (keys still apply to pods)template.spec.podLabelswins overtemplate.metadata.labelson key collision (explicit beats implicit), or flag the conflict at admissionsei.io/nodedeployment, revision) still set last so they can't be overriddeninternal/controller/nodedeployment/covering the merge order