Skip to content

feat: add runtime fraction to EnvoyExtensionPolicy - #8849

Closed
aburan28 wants to merge 1 commit into
envoyproxy:mainfrom
aburan28:adam--envoyextensionpolicy-runtime-fraction
Closed

feat: add runtime fraction to EnvoyExtensionPolicy#8849
aburan28 wants to merge 1 commit into
envoyproxy:mainfrom
aburan28:adam--envoyextensionpolicy-runtime-fraction

Conversation

@aburan28

Copy link
Copy Markdown
Contributor

What type of PR is this?

feature

What this PR does / why we need it

This PR adds percentage-based runtime fraction support to EnvoyExtensionPolicy for Wasm, ExtProc, and Lua extensions.

Envoy Gateway currently lets users attach extension filters through EnvoyExtensionPolicy, but it does not expose Envoy's runtime_fraction behavior for those filters. Users who need gradual rollout or sampled execution of extensions have to patch generated xDS manually. This change lets users configure a percentage fraction directly on each extension entry.

This recreates and refreshes the closed/unmerged work from #8374 on top of current main.

How it works

  • Adds optional percentage fields to Wasm, ExtProc, and Lua EnvoyExtensionPolicy API types using gwapiv1.Fraction.
  • Propagates the fraction through Gateway API translation into IR extension structs.
  • Applies the fraction to generated xDS route matches as Envoy runtime_fraction.
  • Adds fallback IR routes immediately after sampled routes so non-sampled traffic can continue without the extension filter.
  • Keeps the tightest runtime fraction if multiple extension filters on the same route specify a percentage.
  • Regenerates CRDs, API docs, deepcopy code, and Helm golden output.

Testing

  • go test ./internal/xds/utils/fractionalpercent ./internal/xds/translator ./internal/gatewayapi
  • go test ./internal/gatewayapi -run 'TestAppendFallbackRoutes|TestExtensionsUsePercentage'
  • go test ./internal/xds/translator -run 'TestApplyRuntimeFractionToRouteMatch|TestPatchRouteAppliesRuntimeFractionForExtensions'
  • make -k gen-check

Which issue(s) this PR fixes

None linked.

Release Notes

Added percentage-based runtime fraction support for EnvoyExtensionPolicy Wasm, ExtProc, and Lua extensions.

@aburan28
aburan28 requested a review from a team as a code owner April 24, 2026 16:21
@netlify

netlify Bot commented Apr 24, 2026

Copy link
Copy Markdown

Deploy Preview for cerulean-figolla-1f9435 ready!

Name Link
🔨 Latest commit 079f74d
🔍 Latest deploy log https://app.netlify.com/projects/cerulean-figolla-1f9435/deploys/69f21bcafc5ad0000869fb96
😎 Deploy Preview https://deploy-preview-8849--cerulean-figolla-1f9435.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 50ba8509bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
if extensionsUsePercentage(r.EnvoyExtensions) {
fallback := irListener.Routes[i].DeepCopy()
fallback.EnvoyExtensions = &ir.EnvoyExtensionFeatures{}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep non-sampled extensions on fallback routes

Clearing fallback.EnvoyExtensions makes unsampled traffic skip every extension on that route, including ones whose percentage is unset (documented as 100%). In a mixed policy (for example, lua.percentage=20 plus ExtProc without percentage), only 20% of requests will execute ExtProc because the fallback route has no extension config at all. This breaks per-extension semantics and affects both route- and gateway-targeted paths where the same fallback reset is used.

Useful? React with 👍 / 👎.

@codecov

codecov Bot commented Apr 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.83838% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.59%. Comparing base (4628260) to head (079f74d).
⚠️ Report is 207 commits behind head on main.

Files with missing lines Patch % Lines
internal/gatewayapi/envoyextensionpolicy.go 82.35% 9 Missing and 3 partials ⚠️
internal/xds/translator/utils.go 69.23% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8849      +/-   ##
==========================================
+ Coverage   74.57%   74.59%   +0.02%     
==========================================
  Files         250      250              
  Lines       39751    39839      +88     
==========================================
+ Hits        29644    29719      +75     
- Misses       8056     8066      +10     
- Partials     2051     2054       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: Adam Buran <aburan28@gmail.com>
@aburan28
aburan28 force-pushed the adam--envoyextensionpolicy-runtime-fraction branch from 50ba850 to 079f74d Compare April 29, 2026 14:55
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had activity in the last 30 days. Please feel free to give a status update now, ping for review, when it's ready. Thank you for your contributions!

@github-actions github-actions Bot added the stale label May 29, 2026
@github-actions github-actions Bot closed this Jun 5, 2026
@arkodg arkodg reopened this Jun 8, 2026
@arkodg arkodg added this to the v1.9.0-rc.1 Release milestone Jun 8, 2026
@arkodg

arkodg commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

can we call it percent to keep it idiomatic with https://gateway-api.sigs.k8s.io/reference/api-spec/1.5/spec/#httprequestmirrorfilter

@arkodg arkodg removed the stale label Jun 8, 2026
@arkodg

arkodg commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

the design for this, will require more thought

  - P2: Per-extension percentages collapse to the smallest percentage.
    The API docs make percentage per extension: ExtProc, Lua, and Wasm each say it controls the percent of requests sent through that extension. But the Gateway API layer
    puts all extensions on one main IR route, creates one fallback route, and drops all percentage-bearing extensions from that fallback. The xDS layer then tightens the
    route match to the minimum runtime fraction.
    Example: ExtProc percentage=50% plus Lua percentage=20% yields one main route with both filters at runtime_fraction=20%, and the fallback route has neither sampled
    filter. ExtProc runs on 20% of traffic, not 50%.
    See PR head: internal/gatewayapi/envoyextensionpolicy.go:598-608, internal/gatewayapi/envoyextensionpolicy.go:1336-1360, and internal/xds/translator/utils.go:130-152.
    The user-facing contract is in api/v1alpha1/ext_proc_types.go:110-114, lua_types.go:49-53, wasm_types.go:71-75.

  Required fix: either reject multiple distinct sampled percentages on the same effective route, or synthesize tiered fallback routes so each extension’s requested
  percentage is honored.

should we wait until we've moved to per route configs @zhaohuabing ?

@zhaohuabing

zhaohuabing commented Jun 9, 2026

Copy link
Copy Markdown
Member

The PR is trying to solve a per-filter fraction, but the implementation is per-route (forking the route into a sampled entry + a fallback clone), so the mechanism doesn't map cleanly onto the problem — and route duplication splits per-route state like stats, rate-limit descriptors, and session persistence.

The clearer model is sampling at the filter level. Envoy supports this on ext_authz via filter_enabled (a RuntimeFractionalPercent), but there's no consistent equivalent across filters — rbac has none, fault only has per-behavior abort/delay percentages, and cors's filter_enabled lives on the route-level CorsPolicy, not the filter. So ExtProc/Lua/Wasm have no native knob today.

I checked envoyproxy/envoy#42912 in case it helped — it's a per-route chain selector with no sampling primitive, so it'd still need a runtime_fraction at the route to pick a chain, reintroducing the same duplication.

The cleanest fix would be Envoy supporting a generic filter_enabled runtime fraction on the HttpFilter wrapper itself (which today only has disabled), e.g.:

 httpFilters:
 - name: envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-http-route/extproc/0
   filterEnabled:          # proposed: generic per-filter runtime fraction
     defaultValue:
       numerator: 50
   typedConfig:
     '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor
     grpcService:
       envoyGrpc:
         authority: grpc-backend.envoy-gateway:8000
         clusterName: envoyextensionpolicy/default/policy-for-http-route/0
       timeout: 10s
     processingMode:
       requestHeaderMode: SKIP
       requestTrailerMode: SKIP
       responseHeaderMode: SKIP

That would cover all extension filters uniformly without touching the route. Might be worth raising upstream before we commit to the per-route approach here.

cc @wbpcode you have a lot more Envoy expertise here—do you think the generic filter_enabled runtime fraction approach would work on the Envoy side?

@wbpcode

wbpcode commented Jun 11, 2026

Copy link
Copy Markdown
Member

If this feature actually is EG wants, I will suggest to add a new HTTP filter which works as a wrapper to avoid impact Envoy core but at same time, could achieve same target that Huabing referred.

@zhaohuabing

Copy link
Copy Markdown
Member

@aburan28 could you open an issue to describe your use case in more detail and gather feedback from the community?

If this is something we need, we could then open an upstream Envoy issue, as @wbpcode suggested, to explore adding generic filter-level runtime fraction support rather than modeling it at the route level.

@zhaohuabing zhaohuabing removed this from the v1.9.0-rc.1 Release milestone Jun 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had activity in the last 30 days. Please feel free to give a status update now, ping for review, when it's ready. Thank you for your contributions!

@github-actions github-actions Bot added the stale label Jul 11, 2026
@github-actions github-actions Bot closed this Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants