Skip to content

Use Route traffic for Knative DomainMappings - #16685

Open
kahirokunn wants to merge 1 commit into
knative:mainfrom
kahirokunn:domainmapping-direct-route-traffic
Open

Use Route traffic for Knative DomainMappings#16685
kahirokunn wants to merge 1 commit into
knative:mainfrom
kahirokunn:domainmapping-direct-route-traffic

Conversation

@kahirokunn

@kahirokunn kahirokunn commented Aug 28, 2026

Copy link
Copy Markdown
Member

Fixes knative-extensions/net-gateway-api#961
Fixes #14872

Proposed Changes

Copy the first matching cluster-local HTTP paths from a referenced Knative Service or Route into the DomainMapping Ingress, while preserving its last-known-good configuration when the source is unavailable.

Before and after

This DomainMapping exposes the Knative Service website as app.example.com:

apiVersion: serving.knative.dev/v1beta1
kind: DomainMapping
metadata:
  name: app.example.com
  namespace: default
spec:
  ref:
    apiVersion: serving.knative.dev/v1
    kind: Service
    name: website

Before this change, requests were sent through Service/website, which points to the cluster-local ingress:

flowchart TD
    host["app.example.com"] --> mappingIngress["DomainMapping Ingress"]
    mappingIngress --> website["Service/website<br/>(ExternalName)"]
    website --> clusterLocalIngress["cluster-local ingress"]
    clusterLocalIngress --> revisionService1["Service/website-00001"]
    clusterLocalIngress --> revisionService2["Service/website-00002"]
Loading

The Ingress created by the Route controller already names the backend Services and their percentages. The DomainMapping controller now copies those HTTP paths:

flowchart TD
    host["app.example.com"] --> mappingIngress["DomainMapping Ingress"]
    mappingIngress -->|80%| revisionService1["Service/website-00001"]
    mappingIngress -->|20%| revisionService2["Service/website-00002"]
    revisionService1 --> revision1["Revision/website-00001"]
    revisionService2 --> revision2["Revision/website-00002"]
Loading

Service/website-00001 and Service/website-00002 are Kubernetes Services that can be used as HTTPRoute backendRefs.

Generated Ingress

For a Route that sends 80% of requests to website-00001 and 20% to website-00002, the relevant part of the Ingress for the DomainMapping is:

spec:
  rules:
  - hosts:
    - app.example.com
    visibility: ExternalIP
    http:
      paths:
      - splits:
        - serviceNamespace: default
          serviceName: website-00001
          servicePort: 80
          percent: 80
          appendHeaders:
            Knative-Serving-Namespace: default
            Knative-Serving-Revision: website-00001
            K-Original-Host: app.example.com
        - serviceNamespace: default
          serviceName: website-00002
          servicePort: 80
          percent: 20
          appendHeaders:
            Knative-Serving-Namespace: default
            Knative-Serving-Revision: website-00002
            K-Original-Host: app.example.com

The copied paths do not set rewriteHost because requests now go to the backend Services instead of re-entering the cluster-local ingress. The controller adds K-Original-Host: app.example.com and keeps the headers set by the Route controller. It also keeps each backend port, including port 443 when system-internal-tls is enabled.

Reconciliation

For a Knative Service or Route reference, the controller:

  1. Resolves the reference to its cluster-local host.
  2. Gets the target Route. For a Service reference, the Route uses the Service's child-resource name and must be controlled by that Service.
  3. Gets the Ingress with the Route's child-resource name and verifies that the Route controls it.
  4. Selects the first cluster-local rule whose hosts contain the resolved target host.
  5. Deep-copies that rule's HTTP paths into the DomainMapping Ingress.
  6. Keeps backend Service names, namespaces, ports, percentages, path headers, and split headers; adds K-Original-Host; and removes rewriteHost.
  7. Tracks the Route and its Ingress so a change to either resource reconciles the DomainMapping.

The Route controller owns validation of the source Ingress. DomainMapping does not add separate validation for empty paths or backends; it copies the first matching rule as produced by the Route controller. A matching rule with http: nil is reported as a reconciliation error instead of being dereferenced.

When the source cannot be used, the controller does not create or update the DomainMapping Ingress. If a previously configured Ingress exists, it is left unchanged as the last-known-good configuration.

Situation DomainMapping result Ingress for the DomainMapping
The Service or Route reference cannot be resolved ReferenceResolved=False, reason ResolveFailed; IngressReady=Unknown, reason IngressNotConfigured Existing Ingress is left unchanged
The target Service, Route, or Route Ingress has not been observed yet IngressReady=Unknown, reason IngressNotConfigured Existing Ingress is left unchanged
The Service does not control the Route, or the Route does not control the Ingress IngressReady=False, reason NotOwned Existing Ingress is left unchanged
No cluster-local rule contains the resolved target host IngressReady=Unknown, reason IngressNotConfigured Existing Ingress is left unchanged
A matching rule has http: nil Reconciliation returns an error and emits an InternalError event Existing Ingress is left unchanged
More than one cluster-local rule matches The first matching rule is used Ingress is created or updated from that rule

When the DomainMapping itself is deleted, Kubernetes garbage collection removes its Ingress through the owner reference. Long DomainMapping names continue to use a deterministic, Kubernetes-safe child Ingress name.

Compatibility

DomainMapping reference Backend used by its Ingress
Knative Service Backend Services from the first matching cluster-local rule in the Ingress for the Service's Route
Knative Route Backend Services from the first matching cluster-local rule in the Route's Ingress
Any other Addressable Backend Service from the resolved URL, with the existing host rewrite

Requests for a Knative Service or Route no longer pass through the target Route's cluster-local Ingress.

There are no API schema changes or new condition types.

DomainMappings that reference Knative Services or Routes now use the backend Services and traffic splits from the target Route.

Signed-off-by: kahirokunn <okinakahiro@gmail.com>
@knative-prow knative-prow Bot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Aug 28, 2026
@knative-prow

knative-prow Bot commented Aug 28, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: kahirokunn
Once this PR has been reviewed and has the lgtm label, please assign dprotaso for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@knative-prow
knative-prow Bot requested review from dprotaso and skonto August 28, 2026 13:59
@codecov

codecov Bot commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.42857% with 40 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.25%. Comparing base (618b0c2) to head (225151e).

Files with missing lines Patch % Lines
pkg/reconciler/domainmapping/reconciler.go 76.74% 11 Missing and 9 partials ⚠️
pkg/reconciler/domainmapping/controller.go 0.00% 18 Missing ⚠️
.../reconciler/domainmapping/resources/names/names.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #16685      +/-   ##
==========================================
- Coverage   80.29%   80.25%   -0.04%     
==========================================
  Files         217      218       +1     
  Lines       13560    13682     +122     
==========================================
+ Hits        10888    10981      +93     
- Misses       2309     2330      +21     
- Partials      363      371       +8     

☔ 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.

@kahirokunn

kahirokunn commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

@dprotaso @Cali0707 @dsimansk Hello. Would you mind leaving a review? 🙏
I opened this PR because DomainMapping currently does not work with net-gateway-api and Envoy Gateway. I’d appreciate a review if you have time.

There is an ongoing discussion about ExternalName in #11821 . Removing ExternalName could make DomainMapping work without this change, but this PR
also avoids routing traffic from the external gateway through the internal gateway. This reduces resource usage, so I believe the change is valuable in its own right rather than just a workaround.

Thank you 🙇‍♂️

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

Labels

size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Envoy Gateway returns 503 DomainMapping creates configuration that routes through the local gateway

1 participant