Skip to content

fix(chart): scope server Deployment selector to component=server#103

Merged
ServerSideHannes merged 1 commit into
mainfrom
fix/server-deployment-selector-scope
Jul 1, 2026
Merged

fix(chart): scope server Deployment selector to component=server#103
ServerSideHannes merged 1 commit into
mainfrom
fix/server-deployment-selector-scope

Conversation

@ServerSideHannes

Copy link
Copy Markdown
Owner

Problem

The server Deployment's .spec.selector is only {app.kubernetes.io/name, app.kubernetes.io/instance} — it omits the component label. Since the frontproxy, redis and dashboard pods all carry the same name+instance labels, that selector is a superset matching every pod in the release.

The Deployment controller itself is fine (its ReplicaSets disambiguate ownership via pod-template-hash), but any consumer that reads the bare .spec.selector over-matches. The concrete breakage:

A HorizontalPodAutoscaler with a Resource (CPU) metric targeting this Deployment inherits the target's selector verbatim and averages CPU across all four components. The near-idle frontproxy/redis/dashboard pods carry ~2600m of CPU requests at almost no usage, diluting the average:

  • server-only: ~90% of request
  • blended (observed): ~68%

That keeps the computed utilisation pinned just under target and suppresses scale-up, so the HPA never reaches its max replicas under real server load.

Fix

Add app.kubernetes.io/component: server to the server Deployment selector. The Services (incl. headless) already scope with component: server; only the Deployment selector omitted it. The pod template already carries the label, so this only tightens the selector — no other change.

Rollout caveat

.spec.selector is immutable. Applying this to an existing Deployment fails with field is immutable; rolling it out requires a one-time delete + recreate of the s3proxy-python Deployment (e.g. ArgoCD Replace=true or kubectl delete deployment s3proxy-python). Frontproxy queues/redispatches during the brief gap.

Verify

helm template now renders the server Deployment selector with component: server, matching the pod template labels; helm lint passes.

The server Deployment selector was only {name, instance}, with no
component label — a superset that matches the frontproxy, redis and
dashboard pods too (they all carry name+instance). The Deployment
controller is unaffected (ReplicaSets disambiguate via
pod-template-hash), but anything reading the bare selector over-matches.

Concretely this breaks a Resource-metric HPA targeting this Deployment:
the HPA inherits the target's selector and averages CPU across all four
components. The near-idle frontproxy/redis/dashboard requests dilute the
average (~90% server-only -> ~68% blended), suppressing scale-up.

The Services already scope with component=server; only the Deployment
selector omitted it. The pod template already carries the label, so this
only tightens the selector.

Note: .spec.selector is immutable — rolling this out requires a one-time
delete/recreate of the existing Deployment.
@ServerSideHannes ServerSideHannes merged commit 267c131 into main Jul 1, 2026
4 checks passed
@ServerSideHannes ServerSideHannes deleted the fix/server-deployment-selector-scope branch July 1, 2026 09:05
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.

1 participant