[Proposal] Use Major Version for Policy Identity Between Gateway Controller and Policy Engine #1094
renuka-fernando
started this conversation in
Ideas
Replies: 1 comment 1 reply
-
|
This proposal effectively addresses the rolling update compatibility issue by using major-only versions. I'd like to suggest an additional enhancement that could make the system even more resilient: Instead of strict version matching, we could implement a fallback mechanism:
Benefits:
This would make the system more robust during gradual rollouts and provide early warning signals for |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
Change the internal version contract between Gateway Controller and Policy Engine from full semantic versions (
v0.1.2) to major-only versions (v0). The policy engine registry would key policies byname:vNinstead ofname:vN.M.P, and the Gateway Controller would send major-only versions over xDS. This eliminates version mismatch failures during Kubernetes rolling updates and aligns the internal protocol with the already major-only user-facing API YAML contract.Motivation
The API Platform gateway has three main runtime components that interact around policy versions:
api-key-auth.yamlwithversion: v0.1.2) and sends policy chains to the Policy Engine via xDS.api-key-auth:v0.1.2).Current Version Flow
version: v0v0tov0.1.2(full semver) usingResolvePolicyVersion()from loaded policy definitionsv0.1.2to Policy Engine via xDS inPolicyInstance.Versionapi-key-auth:v0.1.2api-key-auth:v0.1.2-- must match exactlyThe Problem
Only one implementation per major version can exist. The policy engine binary contains exactly one compiled implementation of each policy. There is no scenario where
v0.1.0andv0.1.2ofapi-key-authcoexist in the same binary. The full semver in the registry key carries precision that does not correspond to any real distinction.Kubernetes rolling updates cause version mismatch failures. In a Kubernetes deployment, the Gateway Controller pod and Gateway Runtime pod may briefly run different builds during a rollout restart. A new Gateway Controller (loading policy definitions at
v0.1.3) may connect to an old Policy Engine (compiled withv0.1.2). The exact-match lookup onapi-key-auth:v0.1.3fails against the registry entryapi-key-auth:v0.1.2, even though the policies are functionally compatible within the same major version.The internal protocol is more precise than the user-facing contract. Users already specify
version: v0in their API YAML. The Gateway Controller resolves this to full semver solely for the internal xDS message, introducing fragile coupling that the user never asked for.Rollout Restart Failure Scenario
sequenceDiagram participant User as User/CI participant K8s as Kubernetes participant GC_old as Gateway Controller<br/>(Old Build v0.1.2) participant GC_new as Gateway Controller<br/>(New Build v0.1.3) participant PE_old as Policy Engine<br/>(Old Build v0.1.2) participant PE_new as Policy Engine<br/>(New Build v0.1.3) Note over K8s: Initial State: Both components running v0.1.2 User->>K8s: Deploy new gateway image (v0.1.3) K8s->>GC_new: Start new Gateway Controller pod Note over GC_new: Loads policy defs v0.1.3 K8s--xGC_old: Terminate old Gateway Controller Note over PE_old: Policy Engine still running old build (v0.1.2) User->>GC_new: Deploy API with policy version: v0 GC_new->>GC_new: Resolve v0 → v0.1.3 (full semver) rect rgb(255, 200, 200) Note over GC_new,PE_old: VERSION MISMATCH WINDOW GC_new->>PE_old: xDS: PolicyInstance{version: "v0.1.3"} PE_old->>PE_old: Lookup "api-key-auth:v0.1.3" PE_old-->>GC_new: ERROR: policy not found<br/>(registry has "api-key-auth:v0.1.2") end Note over K8s: Eventually PE pod also restarts... K8s->>PE_new: Start new Policy Engine pod K8s--xPE_old: Terminate old Policy Engine GC_new->>PE_new: xDS: PolicyInstance{version: "v0.1.3"} PE_new->>PE_new: Lookup "api-key-auth:v0.1.3" ✓ PE_new-->>GC_new: OKSolution with Major-Only Versions
sequenceDiagram participant User as User/CI participant K8s as Kubernetes participant GC_new as Gateway Controller<br/>(New Build v0.1.3) participant PE_old as Policy Engine<br/>(Old Build v0.1.2) participant PE_new as Policy Engine<br/>(New Build v0.1.3) Note over K8s: Rolling update in progress User->>GC_new: Deploy API with policy version: v0 rect rgb(200, 255, 200) Note over GC_new,PE_old: MAJOR VERSION - ALWAYS COMPATIBLE GC_new->>PE_old: xDS: PolicyInstance{version: "v0"} PE_old->>PE_old: Lookup "api-key-auth:v0" ✓<br/>(registered v0.1.2 as major v0) PE_old-->>GC_new: OK end Note over K8s: PE pod restarts later... K8s->>PE_new: Start new Policy Engine pod K8s--xPE_old: Terminate old Policy Engine rect rgb(200, 255, 200) Note over GC_new,PE_new: STILL COMPATIBLE GC_new->>PE_new: xDS: PolicyInstance{version: "v0"} PE_new->>PE_new: Lookup "api-key-auth:v0" ✓<br/>(registered v0.1.3 as major v0) PE_new-->>GC_new: OK endProposal
Principle
Use major version only (
v0,v1,v2) as the policy identity contract between Gateway Controller and Policy Engine. This matches:Changes Required
Policy Engine Side
1. Registry
Register()method -- Extract the major version fromdef.Version(full semver) before creating the composite key.Current behavior:
Proposed behavior:
The
majorVersion()helper extracts the major component:2.
CreateInstance()andPolicyExists()-- No changes needed. They receive major-only versions from xDS and look up directly against the major-keyed registry.Gateway Controller Side
1.
DerivePolicyFromAPIConfiginbuilder.go-- Still callResolvePolicyVersion()for validation (confirming a policy definition exists for the requested major version), but pass the original major-only version from the API YAML toConvertAPIPolicyToModelinstead of the resolved full semver.Current behavior:
Proposed behavior:
2. System policy constants -- Change version constants from full semver to major-only:
Key Design Decisions
PolicyEntry.Definitionretains full semver. The originaldef.Versionfield (e.g.,"v0.1.2") is preserved in the storedPolicyDefinitionstruct. Only the map key changes. Admin endpoints likeDumpPolicies()continue to report the precise build-time version for debugging.Validation still happens.
ResolvePolicyVersion()is still called to confirm that a policy definition exists for the requested major version. The resolved full version is simply discarded rather than being passed through to xDS.Duplicate detection at major level. Attempting to register both
v1.0.0andv1.1.0of the same policy will fail as a duplicate (both map toapi-key-auth:v1). This is correct since only one implementation per major version can be compiled into the binary.Backward Compatibility
Both Gateway Controller and Policy Engine must be updated together. In practice this is safe because:
There is no supported scenario where a pre-change Gateway Controller communicates with a post-change Policy Engine or vice versa across different release trains.
Alternatives Considered
Alternative 1: Fuzzy Matching in the Policy Engine Registry
Make the registry lookup tolerate minor/patch differences. If
api-key-auth:v0.1.3is not found, fall back to anyapi-key-auth:v0.x.x.Rejected because:
Alternative 2: Version Negotiation via xDS
Add a handshake where the Policy Engine reports its compiled policy versions, and the Gateway Controller adapts its xDS messages accordingly.
Rejected because:
Alternative 3: Keep Full Semver but Ignore Patch/Minor in Lookup
The registry key remains
api-key-auth:v0.1.2, but theCreateInstance()method strips to major version before lookup.Rejected because:
Impact Analysis
Benefits
Risks
Document Version: 1.0
Last Updated: 2026-02-12
Status: Proposed
Beta Was this translation helpful? Give feedback.
All reactions