Skip to content

Rename Function to Assignment and dual-write K8s annotations - #138

Open
scott-rc wants to merge 1 commit into
mainfrom
sc/assignment-redesign
Open

scott-rc wants to merge 1 commit into
mainfrom
sc/assignment-redesign

Conversation

@scott-rc

@scott-rc scott-rc commented May 7, 2026 •

Copy link
Copy Markdown
Contributor

Function is FaaS vocabulary that mismatches Skipper's behavior. Skipper does not invoke code -- it routes traffic to tenant-supplied pods. The misnomer is most visible at x-skipper-function, the header tenants set on every request, and it leaks into the type vocabulary that contributors learn first. Assignment describes what the carrier actually represents: the binding of a pod to a tenant for a request.

The rename also clears the way for a follow-up redesign that adds a per-tenant policy surface (heartbeat timeout, retry policy, HPA tolerance, assign timeout, token TTL, transport, zone awareness) on the same carrier -- those are stuck as cluster-wide flags today, with no natural home on Function. This PR does not touch the policy surface; it sets up the vocabulary the next round of work builds on.

This PR is the internal rename plus K8s annotation dual-support. External surfaces (HTTP header, Prometheus labels, OTLP attrs, slog keys, CLI flags, web URL paths, user-visible UI labels) deliberately stay on legacy function- form here -- follow-up PRs introduce dual-support for each so tenant SDKs, dashboards, and operator manifests can migrate at their own pace.

The one external surface this PR changes is K8s pod annotations: the controller now dual-writes both skipper/function and skipper/assignment on every assigned pod, and the read path prefers the new key with fallback to the legacy. Dual-write is required for rolling-deploy safety -- a controller running pre-rename code observing a pod that carries only skipper/assignment would treat it as unassigned and trigger cleanup. Removal of the legacy write is sequenced for a release boundary after one full deploy plus a deprecation window.

Two typed keys live side by side: LegacyFunctionKey (Name "function", used by every existing emission site this PR touches) and AssignmentKey (Name "assignment", declared but only wired into the K8s annotation write). Subsequent PRs route AssignmentKey through HTTP header dual-parse and telemetry dual-emit, then CLI flags and web URLs.

The proto rename is binary-wire-safe: field tag numbers stay stable, so mixed-version controller / router gRPC interoperates throughout the migration.

Test plan

  • dev test -short ./... -- 1216 pass, 34 skipped
  • dev lint clean
  • dev kube-lint clean
  • internal/skipper/testdata/json.golden regenerated for the proto rename; internal/key/testdata/keys.golden byte-identical (legacy emission preserved)
  • New table-driven cases in TestAssignmentFromPod cover the four annotation-presence shapes (legacy-only, new-only, both, neither)
  • Manual mixed-version verification deferred to staging deploy; static review confirms field-tag-number stability across the rename

Function is FaaS vocabulary that mismatches Skipper's behavior --
Skipper routes traffic to tenant-supplied pods, it does not invoke
code. Internal Go now uses Assignment throughout: AssignmentHash,
AssignmentFromHeader, AssignmentKey, file renames in internal/skipper
and internal/fixture, web UI internal types, fixture helpers, doc-
rendering machinery, and the pod-read helper.

The K8s pod-annotation surface dual-writes both skipper/function and
skipper/assignment on every assigned pod, and the read path prefers
skipper/assignment with fallback to skipper/function. Dual-write is
required for rolling-deploy safety: a controller running pre-rename
code that observed a pod carrying only skipper/assignment would treat
it as unassigned and trigger cleanup. The cleanup followup plan
removes the legacy write after one full deploy plus a deprecation
window.

Two typed keys exist now: LegacyFunctionKey (Name "function", emits
the legacy header / label / OTel / slog vocabulary) and AssignmentKey
(Name "assignment"). Phase 1 leaves every existing emission site
pointed at LegacyFunctionKey -- HTTP header read, Prometheus label,
OTLP attr, slog identity-group, CLI flag, web URL paths, and user-
visible UI labels all still emit / accept function- form. The lone
exception is the K8s annotation write, which dual-writes via both
keys' PatchAnnotation. Phase 2 introduces dual-emit for HTTP header
and telemetry; Phase 3 covers CLI flags and web URLs.

The proto rename is binary-wire-safe: field tag numbers stay stable,
so mixed-version controller / router gRPC interoperates throughout
the migration.
@scott-rc

scott-rc commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

This change is part of the following stack:

Change managed by git-spice.

@scott-rc scott-rc changed the title Phase 1: rename Function to Assignment, dual-write K8s annotations Rename Function to Assignment and dual-write K8s annotations May 7, 2026

This branch has not been deployed

No deployments
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