Skip to content

(apigw/httproute) Add support to disable traffic with weight 0 in services#23216

Open
sujay-hashicorp wants to merge 1 commit intomainfrom
sujay/fix/route-weight-0
Open

(apigw/httproute) Add support to disable traffic with weight 0 in services#23216
sujay-hashicorp wants to merge 1 commit intomainfrom
sujay/fix/route-weight-0

Conversation

@sujay-hashicorp
Copy link
Contributor

@sujay-hashicorp sujay-hashicorp commented Feb 16, 2026

Description

This PR fixes Consul API Gateway behavior for Kubernetes HTTPRoute backends with weight: 0.

Previously, HTTPRoute normalization converted all weight <= 0 values to 1, which caused explicit weight: 0 backends to still receive traffic. This conflicted with Gateway API expectations and customer-observed behavior.

This change updates normalization logic to:

  • Preserve explicit weight: 0 (so zero-weight backends can be excluded from traffic).
  • Continue normalizing negative weights to 1.
    Preserve backward compatibility by normalizing all-zero rules to 1 (to avoid breaking older configs that relied on omitted/default weights).

Links

Tests

  • With this fix, the routes support definition of 0 weight services.
  • The instance with weight: 0 does not receive any traffic.
HTTPRoute config output

$ consul config read -kind http-route -name quill-route

{
    "Kind": "http-route",
    "Name": "quill-route",
    "Parents": [
        {
            "Kind": "api-gateway",
            "Name": "api-gateway",
            "SectionName": "http-listener"
        }
    ],
    "Rules": [
        {
            "Filters": {
                "Headers": null,
                "URLRewrite": null,
                "RetryFilter": null,
                "TimeoutFilter": null,
                "JWT": null
            },
            "ResponseFilters": {
                "Headers": null
            },
            "Matches": [
                {
                    "Headers": null,
                    "Method": "",
                    "Path": {
                        "Match": "prefix",
                        "Value": "/"
                    },
                    "Query": null
                }
            ],
            "Services": [
                {
                    "Name": "quill-v1",
                    "Weight": 0,
                    "Filters": {
                        "Headers": null,
                        "URLRewrite": null,
                        "RetryFilter": null,
                        "TimeoutFilter": null,
                        "JWT": null
                    },
                    "ResponseFilters": {
                        "Headers": null
                    }
                },
                {
                    "Name": "quill-v2",
                    "Weight": 100,
                    "Filters": {
                        "Headers": null,
                        "URLRewrite": null,
                        "RetryFilter": null,
                        "TimeoutFilter": null,
                        "JWT": null
                    },
                    "ResponseFilters": {
                        "Headers": null
                    }
                }
            ]
        }
    ],
    "Hostnames": null,
    "CreateIndex": 43,
    "ModifyIndex": 80,
    "Status": {
        "Conditions": [
            {
                "Type": "Accepted",
                "Status": "True",
                "Reason": "Accepted",
                "Message": "route is valid",
                "Resource": {
                    "Kind": "",
                    "Name": "",
                    "SectionName": ""
                },
                "LastTransitionTime": "2026-02-16T08:17:57.943208Z"
            },
            {
                "Type": "Bound",
                "Status": "True",
                "Reason": "Bound",
                "Message": "successfully bound route",
                "Resource": {
                    "Kind": "api-gateway",
                    "Name": "api-gateway",
                    "SectionName": "http-listener"
                },
                "LastTransitionTime": "2026-02-16T08:17:57.943215Z"
            }
        ]
    }
}

Traffic Distribution

case 1:
Services = [
  {
    Name = "quill-v1"
    Weight = 100
  },
  {
    Name = "quill-v2"
    Weight = 100
  }
]
Screenshot 2026-02-16 at 14 29 59
case 2:
Services = [
  {
    Name = "quill-v1"
    Weight = 0
  },
  {
    Name = "quill-v2"
    Weight = 100
  }
]
Screenshot 2026-02-16 at 14 32 55

PR Checklist

  • updated test coverage
  • external facing docs updated
  • appropriate backport labels added
  • not a security concern

PCI review checklist

  • I have documented a clear reason for, and description of, the change I am making.

  • If applicable, I've documented a plan to revert these changes if they require more than reverting the pull request.

  • If applicable, I've documented the impact of any changes to security controls.

    Examples of changes to security controls include using new access control methods, adding or removing logging pipelines, etc.

@sujay-hashicorp sujay-hashicorp added pr/no-changelog PR does not need a corresponding .changelog entry pr/no-backport labels Feb 16, 2026
@sujay-hashicorp sujay-hashicorp changed the title (discoverychain) Add support to disable routes with weight 0 instead of setting it 1 explicitly (apigw/httproute) Add support to disable routes with weight 0 instead of setting it 1 explicitly Feb 16, 2026
@sujay-hashicorp sujay-hashicorp force-pushed the sujay/fix/route-weight-0 branch from 08b2d33 to 1472d47 Compare February 16, 2026 09:09
@sujay-hashicorp sujay-hashicorp added backport/all Apply backports for all active releases per .release/versions.hcl and removed pr/no-changelog PR does not need a corresponding .changelog entry pr/no-backport labels Feb 16, 2026
@sujay-hashicorp sujay-hashicorp marked this pull request as ready for review February 16, 2026 09:10
@sujay-hashicorp sujay-hashicorp requested review from a team as code owners February 16, 2026 09:10
@sujay-hashicorp sujay-hashicorp changed the title (apigw/httproute) Add support to disable routes with weight 0 instead of setting it 1 explicitly (apigw/httproute) Add support to disable traffic with weight 0 in services Feb 16, 2026
@sujay-hashicorp sujay-hashicorp added the pr/do-not-merge PR cannot be merged in its current form. label Feb 16, 2026
@@ -105,8 +105,19 @@ func (e *HTTPRouteConfigEntry) Normalize() error {
rule.Matches[j] = normalizeHTTPMatch(match)
}

allServicesHaveZeroWeight := len(rule.Services) > 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is misleading, why can't we simply have
allServicesHaveZeroWeight := true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I have updated it to true. It was set like this so to skip extra processing in cases where there are no services. But I think HTTPRoute must have at least 1 service.

@sujay-hashicorp sujay-hashicorp force-pushed the sujay/fix/route-weight-0 branch from 1472d47 to 67d104e Compare February 19, 2026 10:57
@sujay-hashicorp sujay-hashicorp force-pushed the sujay/fix/route-weight-0 branch 2 times, most recently from 73e47ae to 9e8325a Compare February 19, 2026 14:21
@sujay-hashicorp sujay-hashicorp force-pushed the sujay/fix/route-weight-0 branch from 9e8325a to 6c84033 Compare February 25, 2026 08:36
service.Merge(e.GetEnterpriseMeta())
service.Normalize()
if service.Weight <= 0 {
if service.Weight < 0 {
Copy link
Member

@krutibaraiya krutibaraiya Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this reintroduce the same issue again? This normalisation layer looks fine, but down the discovery chain, the 0-weight services would get skipped here and at the end of the loop no spiltter would be created.
Will this handled by Envoy now? If yes, can we add some test coverage to ensure that we return 503?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport/all Apply backports for all active releases per .release/versions.hcl pr/do-not-merge PR cannot be merged in its current form.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants