-
Notifications
You must be signed in to change notification settings - Fork 133
Move Contour routing to Gateway API recipes by default #11995
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
willdavsmith
wants to merge
11
commits into
main
Choose a base branch
from
replace-contour-with-nginx-demo
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
16e1942
Demo
willdavsmith df0068c
Add Contour HTTPProxy recipe pack design note
willdavsmith 0a6f4e7
Revert "Demo"
willdavsmith 6f7c88e
Install default Contour Gateway
willdavsmith cccc6c1
Grant Gateway API permissions to dynamic RP
willdavsmith fca6e56
Use Contour Gateway API as default recipe path
willdavsmith 0a7563c
Simplify Contour Gateway install helpers
willdavsmith 8cfc2c9
Remove nonexistent gateways resource from design
willdavsmith 4cb83dc
Configure Contour for default Gateway API
willdavsmith edac559
Enable Gateway API CRDs for Contour install
willdavsmith 3ae3ba9
Add HTTPS listener to managed Contour Gateway
willdavsmith File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
210 changes: 210 additions & 0 deletions
210
eng/design-notes/recipes/2026-05-contour-recipe-packs.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,210 @@ | ||
| # Move Contour Routing to Gateway API Recipes | ||
|
|
||
| * **Author**: Will Smith (@willdavsmith) | ||
|
|
||
| ## Overview | ||
|
|
||
| Radius currently installs Contour by default on Kubernetes and has built-in code that renders Contour `HTTPProxy` resources for application ingress. This design moves application route rendering out of Radius core and into recipes, using Kubernetes Gateway API as the default Contour-backed path. | ||
|
|
||
| Radius keeps installing Contour by default for now. When Contour install is enabled, Radius also creates the shared Gateway API infrastructure used by the default route recipe: | ||
|
|
||
| - `GatewayClass/contour` | ||
| - `Gateway/radius` in `radius-system` | ||
| - HTTP listener on port 80 with routes allowed from application namespaces | ||
|
|
||
| With that infrastructure in place, the default `Radius.Compute/routes` recipe can create Gateway API route resources such as `HTTPRoute` and attach them to the shared `radius-system/radius` Gateway. | ||
|
|
||
| ## Current Radius Behavior | ||
|
|
||
| Today `rad install kubernetes` installs Contour by default after installing the Radius Helm chart. The install command wires this through the existing Contour chart options: | ||
|
|
||
| - Helm release name: `contour` | ||
| - Namespace: `radius-system` | ||
| - Chart repository: `https://projectcontour.github.io/helm-charts` | ||
| - Default chart version: `0.1.0` | ||
| - Opt-out flag: `rad install kubernetes --skip-contour-install` | ||
|
|
||
| Radius also includes built-in Kubernetes rendering for Contour `HTTPProxy` resources. Gateway rendering creates a root `HTTPProxy`, route rendering creates child `HTTPProxy` resources, and the Radius RP ClusterRole includes permissions for `projectcontour.io/httpproxies`. | ||
|
|
||
| This change keeps default Contour installation in place, but replaces the default application routing implementation with Gateway API recipes. When users opt out with `rad install kubernetes --skip-contour-install`, Radius skips both Contour installation and the managed Contour Gateway API setup. Removing Contour from the default install remains a separate design review decision. | ||
|
|
||
| Radius already has a default recipe pack experience for development scenarios. `rad init --preview` creates a default recipe pack named `default` in `/planes/radius/local/resourceGroups/default` and links it to the created environment. `rad deploy` also creates or fetches that default recipe pack and injects it into environment resources that do not specify recipe packs. | ||
|
|
||
| ## Objectives | ||
|
|
||
| > **Issue Reference:** https://github.com/radius-project/radius/issues/11952 | ||
|
|
||
| ### Goals | ||
|
|
||
| - Keep Contour installed by default for now. | ||
| - Create the shared Contour Gateway API `Gateway` during Radius install when Contour install is enabled, with HTTP and HTTPS listeners for existing HTTPProxy behavior. | ||
| - Use the existing `Radius.Compute/routes` recipe to render Gateway API route resources by default. | ||
| - Keep Gateway API infrastructure out of the application model in the default path. | ||
| - Allow users to swap ingress behavior by changing recipe packs. | ||
|
|
||
| ### Non goals | ||
|
|
||
| - Do not change the Radius application resource model. | ||
| - Do not remove Contour from the default Radius install as part of this change. | ||
| - Do not require users to define a gateway resource in application Bicep. | ||
|
|
||
| ## User Experience | ||
|
|
||
| Users deploy routes with the existing `Radius.Compute/routes` resource. They do not need to define an application-level gateway resource for the default Contour path. | ||
|
|
||
| ```bicep | ||
| resource route 'Radius.Compute/routes@2025-08-01-preview' = { | ||
| name: 'web' | ||
| properties: { | ||
| application: app.id | ||
| environment: environment | ||
| kind: 'HTTP' | ||
| hostnames: [ | ||
| 'web.example.com' | ||
| ] | ||
| rules: [ | ||
| { | ||
| matches: [ | ||
| { | ||
| httpPath: '/' | ||
| } | ||
| ] | ||
| destinationContainer: { | ||
| resourceId: web.id | ||
| containerName: 'web' | ||
| containerPort: 80 | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| The default route recipe attaches HTTP and TLS routes to `Gateway/radius` in `radius-system`. Users who want a different Gateway API controller, such as NGINX Gateway Fabric, can select a different recipe pack or pass recipe parameters that target a different Gateway. | ||
|
|
||
| ## Design | ||
|
|
||
| The default Kubernetes route path becomes: | ||
|
|
||
| ```text | ||
| Radius install with Contour enabled -> GatewayClass/contour + Gateway/radius | ||
| Radius.Compute/containers -> Kubernetes Deployment + Service | ||
| Radius.Compute/routes -> Gateway API HTTPRoute/TLSRoute/TCPRoute/UDPRoute | ||
| ``` | ||
|
|
||
| The route recipe defaults are: | ||
|
|
||
| - `gateway_name`: `radius` | ||
| - `gateway_namespace`: `radius-system` | ||
|
|
||
| For HTTP and TLS routes, the route must include at least one hostname when attaching to the shared default Gateway. This prevents multiple applications from unintentionally claiming the same catch-all listener. | ||
|
|
||
| The Radius dynamic RP needs permission to manage Gateway API route resources: | ||
|
|
||
| ```yaml | ||
| apiGroups: | ||
| - gateway.networking.k8s.io | ||
| resources: | ||
| - gateways | ||
| - httproutes | ||
| - tlsroutes | ||
| - tcproutes | ||
| - udproutes | ||
| - referencegrants | ||
| verbs: | ||
| - get | ||
| - list | ||
| - watch | ||
| - create | ||
| - update | ||
| - patch | ||
| - delete | ||
| ``` | ||
|
|
||
| ## Default Recipe Registration | ||
|
|
||
| The existing `default` recipe pack should use the Gateway API `Radius.Compute/routes` recipe. Contour installation and recipe selection are separate concerns: | ||
|
|
||
| - Installing Contour adds the ingress controller and Gateway API support to the cluster. | ||
| - Radius install creates the shared Contour `Gateway` only when Contour install is enabled. | ||
| - The default route recipe renders application routes that attach to that Gateway. | ||
|
|
||
| Today the default recipe pack follows the Radius version channel, including `latest` on the edge channel. A future hardening step should pin default recipes to the Radius release or another explicit artifact version so the default experience does not depend on floating recipe artifacts. | ||
|
|
||
| If Radius later stops installing Contour by default, default Gateway creation and default route recipe selection should be revisited together. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could use PM input here. We might not need to revisit the design it if the expectation is that users bring their own networking infrastructure. This would just need to be called out explicitly in documentation |
||
|
|
||
| ## API Design | ||
|
|
||
| No Radius API changes are required. | ||
|
|
||
| This design uses existing resource types: | ||
|
|
||
| - `Radius.Compute/routes@2025-08-01-preview` | ||
| - `Radius.Compute/containers@2025-08-01-preview` | ||
| - `Radius.Core/recipePacks@2025-08-01-preview` | ||
|
|
||
| ## Implementation Details | ||
|
|
||
| Radius should: | ||
|
|
||
| - Continue installing Contour by default unless `--skip-contour-install` is set. | ||
| - Create or update the default Contour `GatewayClass` and `Gateway` after Contour installation. | ||
| - Delete the managed default `Gateway` and `GatewayClass` during uninstall. | ||
| - Grant the dynamic RP Gateway API permissions. | ||
|
|
||
| `resource-types-contrib` should: | ||
|
|
||
| - Keep the Kubernetes container recipe rendering workload and service resources. | ||
| - Use Gateway API as the default Kubernetes route recipe. | ||
| - Default the route recipe to `Gateway/radius` in `radius-system`. | ||
| - Validate that HTTP and TLS routes include hostnames when using the shared Gateway. | ||
|
|
||
| ## Error Handling | ||
|
|
||
| - If Contour is not installed, the default shared Gateway is not created. | ||
| - If the recipe execution identity lacks Gateway API RBAC, route deployment fails. | ||
| - If a route has no hostname for HTTP or TLS, the default route recipe fails validation. | ||
| - If a rendered Gateway API route is invalid, e2e tests should dump the route status and gateway diagnostics. | ||
|
|
||
| ## Test Plan | ||
|
|
||
| The demo validates the default recipe shape end to end: | ||
|
|
||
| - Contour Gateway API recipes: https://github.com/willdavsmith/radius-nginx-demo/actions/runs/26665457465 | ||
| - NGINX Gateway API recipes: https://github.com/willdavsmith/radius-nginx-demo/actions/runs/26665457417 | ||
|
|
||
| ## Security | ||
|
|
||
| The main security consideration is Kubernetes RBAC. The recipe execution identity needs explicit permissions for Gateway API route resources. | ||
|
|
||
| Because the default Gateway allows routes from application namespaces, route hostnames are required for HTTP and TLS routes. This avoids accidental catch-all route attachment to the shared Gateway. | ||
|
|
||
| Recipe artifacts should be published from trusted locations. The local registry and module server used in the demo are test infrastructure, not a production distribution model. | ||
|
|
||
| ## Compatibility | ||
|
|
||
| Keeping Contour installed by default preserves the default install experience. The application model remains stable because users continue defining containers and routes. | ||
|
|
||
| This changes the Kubernetes ingress implementation from Contour `HTTPProxy` to Gateway API route resources. Users who require direct HTTPProxy behavior can use an alternate recipe pack, but the default path should be Gateway API because it works with Contour today and lets users swap Gateway API controllers without Radius core changes. | ||
|
|
||
| ## Development Plan | ||
|
|
||
| 1. Add default Contour Gateway API infrastructure creation to Radius install and cleanup to uninstall. | ||
| 2. Grant Gateway API permissions to the dynamic RP. | ||
| 3. Update the default Kubernetes route recipe to attach to `radius-system/radius`. | ||
| 4. Validate Contour Gateway API and NGINX Gateway API e2e paths in the demo. | ||
| 5. Review default Contour installation separately. | ||
|
|
||
| ## Alternatives Considered | ||
|
|
||
| ### Preserve HTTPProxy as the default recipe path | ||
|
|
||
| This matches the current implementation more closely, but it keeps the default path tied to Contour-specific APIs. Gateway API gives Radius the same application shape while allowing alternate Gateway API controllers through recipe packs. | ||
|
|
||
| ### Keep Contour rendering in Radius core | ||
|
|
||
| This preserves the current implementation but prevents users from swapping ingress behavior through recipes. | ||
|
|
||
| ## Design Review Notes | ||
|
|
||
| Pending. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just confirming, the routes recipe has support for TCP and UDP routes depending on the application template. The expectation is that this would not be supported with a Contour installation, correct (I don't think Contour natively supports these)? i.e. we'd use either HTTP or the TLS routing with the Gateway API for default Contour installations