Skip to content

fix(helm): give the server Deployment its own component selector - #1600

Merged
lusoris merged 2 commits into
masterfrom
fix/helm-server-selector
Sep 28, 2026
Merged

lusoris merged 2 commits into
masterfrom
fix/helm-server-selector

Conversation

@lusoris

@lusoris lusoris commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The chart's server Deployment and StatefulSet selected only name and instance, so they also matched the operator and node Pods (T-HELM-SERVER-DEPLOYMENT-SELECTOR-OVERLAP-2026-09-27). Kubernetes does not support overlapping selectors, and kubectl logs deployment/vmafx printed the operator's log in the E2E run. Both selectors now include app.kubernetes.io/component: server. The Services, ServiceMonitor, PDBs and NetworkPolicy already selected by component.

Upgrade note for rc.1 installs: a selector is immutable, so a plain helm upgrade from 1.0.0-rc.1 fails with spec.selector: ... field is immutable. Per your 2026-09-27 decision (recorded as ADR-1353), there is no chart major bump; the upgrade guide documents delete-and-reinstall. The tested path is:

kubectl delete deployment,statefulset -n <ns> --cascade=orphan \
  -l app.kubernetes.io/instance=<release>,app.kubernetes.io/component=server
helm upgrade <release> deploy/helm/vmafx -n <ns>

On a kind cluster (Kubernetes v1.37.0, Helm 4.2.4, rc.1 chart and published rc.1 images), the new Deployment adopts the running Pod without a restart. The StatefulSet keeps its Pod and PVC.

  • New gate: scripts/ci/check-helm-selector-isolation.py fails if any workload selector matches another component's Pods, or if a Service or PDB spans components. It runs in helm-chart.yml over Deployment, StatefulSet and Job renders, with 19 unit tests.
  • Docs: docs/development/k8s-deployment.md gains "Upgrading from 1.0.0-rc.1", including uninstall/reinstall and Argo CD/Flux notes. docs/k8s/integration-tests.md gains a troubleshooting entry.
  • Chart version stays 0.1.0: the release guide keeps it packaging-only, and release-please owns appVersion.

Type

  • fix — bug fix

Checklist

  • Commits follow Conventional Commits (the commit-msg hook enforces this).
  • make format && make lint is green locally. Partly: ruff, black, strict mypy, actionlint, shellcheck, reuse lint, markdownlint and mkdocs build --strict pass; some Windows-host hooks need ninja/LF.
  • Unit tests pass: python3 scripts/ci/run_meson_test.py -- -C build. Not applicable: chart and CI change only.

Bug-status hygiene (ADR-0165)

Netflix golden-data gate (ADR-0024)

  • I did not modify any assertAlmostEqual(...) score in the Netflix golden Python tests.

Deep-dive deliverables (ADR-0108)

  • Research digest — no digest needed: the upgrade-path decision and its evidence are in ADR-1353.
  • Decision matrix — ADR-1353 ## Alternatives considered.
  • AGENTS.md invariant note — deploy/helm/vmafx/AGENTS.md and scripts/ci/AGENTS.md.
  • Reproducer / smoke-test command — see below.
  • CHANGELOG fragment — changelog.d/fixed/helm-server-selector.md.
  • Rebase note — new entry in docs/rebase-notes.md.

Reproducer

helm template t deploy/helm/vmafx --set operator.enabled=true --set node.enabled=true > /tmp/rendered.yaml
python3 scripts/ci/check-helm-selector-isolation.py /tmp/rendered.yaml   # passes; the rc.1 chart fails
python3 -m pytest scripts/ci/tests/test_check_helm_selector_isolation.py -q   # 19 passed

The existing E2E builds a fresh cluster on each run, so it only ever installs. The one-time rc.1 upgrade was exercised manually on kind, as described above, rather than added to CI.

🤖 Generated with Claude Code

@github-actions github-actions Bot added the type:bug Something isn't working label Sep 28, 2026
@lusoris
lusoris force-pushed the fix/helm-server-selector branch 2 times, most recently from d16e464 to 0906925 Compare September 28, 2026 13:04
lusoris and others added 2 commits September 28, 2026 17:32
The chart's server Deployment and StatefulSet selected only the release
labels, so they also matched the operator, node and helm test Pods, and
`kubectl logs deployment/vmafx` could print the operator's log. Both
selectors now include `app.kubernetes.io/component: server` (ADR-1353).
A new check in the Helm Chart workflow renders the chart and fails when
any workload selector matches another component's Pods. Scoring traffic
was never affected: the Services already selected the server Pods only.

Upgrade note for v1.0.0-rc.1 installs: a workload's selector cannot be
changed in place, so `helm upgrade` fails with `spec.selector: ... field
is immutable`. Delete the server workload first, then upgrade:

    kubectl delete deployment,statefulset -n <ns> --cascade=orphan \
      -l app.kubernetes.io/instance=<release>,app.kubernetes.io/component=server
    helm upgrade <release> deploy/helm/vmafx -n <ns> --reuse-values

With `--cascade=orphan` the Pods keep serving and the new workload adopts
them. Uninstalling and installing again also works. The steps were checked
on kind with the rc.1 chart and images, and are documented in
docs/development/k8s-deployment.md.

Closes T-HELM-SERVER-DEPLOYMENT-SELECTOR-OVERLAP-2026-09-27.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The merge-base mypy gate flagged the new selector check and its tests:
yaml has no stubs in the pinned mypy environment, and the test helpers
used bare dict annotations. The check now imports yaml with the same
import-untyped ignore as cross_backend_calibration.py, and the helpers
return dict[str, Any].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lusoris
lusoris force-pushed the fix/helm-server-selector branch from 0906925 to 3644a50 Compare September 28, 2026 15:33
@lusoris
lusoris merged commit 6bc097b into master Sep 28, 2026
99 checks passed
@lusoris
lusoris deleted the fix/helm-server-selector branch September 28, 2026 15:57
lusoris added a commit that referenced this pull request Oct 2, 2026
…each with its size and the upstream change that ends it (ADR-1479 to ADR-1486)

The reference for code inherited from Netflix/vmaf is Netflix's source;
a difference needs an ADR. The upstream parity audit of 2026-10-02 found
deliberate differences that had none of their own, or whose ADR
(ADR-1033) names neither upstream's behaviour nor the size:

- ADR-1479 ciede on 4:2:2: chroma flags (fork PR #1050); 0.153 on 48 of
  48 frames; Netflix/vmaf#1611.
- ADR-1480 speed_temporal buffers at speed_prescale above 1 (#1643);
  up to 195, upstream segfaults on two fixtures; Netflix/vmaf#1627.
- ADR-1481 a failing extractor fails the run (#871); status only, 78
  probe runs where upstream is silent and 88 where it crashes.
- ADR-1482 integer adm on frames of 17 to 32 pixels (#1473, #1507);
  scale 3 up to 0.23; Netflix/vmaf#1599, #1600.
- ADR-1483 odd-sized chroma planes round up (4f08d32); psnr_cb / cr
  up to 0.684 / 0.826 dB, ciede 0.198.
- ADR-1484 float_ms_ssim magnitude before pow() (#641, ADR-1033 item 2);
  NaN upstream on the 10 px checkerboard; Netflix/vmaf#1665.
- ADR-1485 apsnr of a plane without error (#641, item 1); 114 against
  60 dB; Netflix/vmaf#1666.
- ADR-1486 float_motion scale-1 stride (#641, item 9); up to 25.1;
  Netflix/vmaf#1667.

Each ADR gives upstream's file and line at Netflix 9e48141b, the fork's
lines, the reason found in the fork's pull request, commit or code, and
the measured size from the audit. Documentation only.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant