-
Notifications
You must be signed in to change notification settings - Fork 49
Bug: setWeight incorrectly modifies header-based routing rules, breaking canary traffic routing #158
Description
Description
I've discovered a bug in the rollouts-plugin-trafficrouter-gatewayapi plugin where the setWeight operation incorrectly modifies ALL routing rules, including header-based routes, causing canary traffic routing to fail.
Problem
The plugin's setWeight logic is too aggressive - it doesn't distinguish between regular routing rules and header-based routing rules. When setting weights, it modifies the weight of all backend references pointing to the canary service, including those in header-match rules that should remain unaffected.
Root Cause
In the plugin source code at pkg/plugin/httproute.go, the setHTTPRouteWeight function implements the following logic:
// 1. Get all rules from the HTTPRoute
routeRuleList := HTTPRouteRuleList(httpRoute.Spec.Rules)
// 2. Find all BackendRefs pointing to the Canary service across ALL rules
canaryBackendRefs, err := getBackendRefs(canaryServiceName, routeRuleList)
// 3. Set the weight for ALL found references to desiredWeight
for _, ref := range canaryBackendRefs {
ref.Weight = &desiredWeight
}Reproduction Steps
When a Rollout progresses through its first step with both header routing and weight configuration:
setHeaderRoute executes first: The plugin adds a new rule (e.g., Rule #2) to the HTTPRoute that matches the X-Canary-start header and routes to the Canary service with default weight (effectively 100%).
setWeight: 0 executes: The plugin runs the logic described above:
- It iterates through ALL rules in the HTTPRoute
- It finds the Canary service in Rule [BE]:Add Gateway API plugin #1 (main route) and sets weight to 0 ✓
- It also finds the Canary service in Rule Update readme #2 (header route) and sets its weight to 0 ✗
Result
The generated HTTPRoute YAML looks like this:
spec:
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: my-app-stable
port: 80
weight: 100
- name: my-app-canary
port: 80
weight: 0
- matches:
- headers:
- name: X-Canary-start
value: "true"
path:
type: PathPrefix
value: /
backendRefs:
- name: my-app-canary
port: 80
weight: 100
Impact:
The header-based routing rule exists but doesn't receive any traffic (or produces undefined behavior) because weight: 0 effectively disables it.
Expected Behavior
setWeight should only control the traffic distribution in the main routing rule and should NOT modify weights in header-based routing rules created by setHeaderRoute.Proposed FixWhen updating weights, the plugin should skip rules that were created by setHeaderRoute.
This could be achieved by:
- Adding metadata/annotations to identify header-based rules
- Checking for the presence of header matches before modifying weights
- Only applying weight changes to the primary/default route rule
Would appreciate any guidance on this issue or if there's a workaround available. Happy to provide more details or help with a PR if needed.