Skip to content

EXP: XBackend Implementation#4901

Merged
k8s-ci-robot merged 16 commits into
kubernetes-sigs:mainfrom
keithmattix:experimental-backend-implementation
May 30, 2026
Merged

EXP: XBackend Implementation#4901
k8s-ci-robot merged 16 commits into
kubernetes-sigs:mainfrom
keithmattix:experimental-backend-implementation

Conversation

@keithmattix
Copy link
Copy Markdown
Contributor

@keithmattix keithmattix commented May 22, 2026

What type of PR is this?

/kind gep

What this PR does / why we need it:
Adds implementation for XBackend resource. The implementation is limited to ExternalHostname for now since EndpointSelector is still provisional.

Which issue(s) this PR fixes:

NONE

Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
@k8s-ci-robot k8s-ci-robot added kind/gep PRs related to Gateway Enhancement Proposal(GEP) do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. labels May 22, 2026
@k8s-ci-robot k8s-ci-robot requested review from rikatz and snorwin May 22, 2026 18:43
@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels May 22, 2026
@keithmattix
Copy link
Copy Markdown
Contributor Author

Part of #4894

Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
@k8s-ci-robot k8s-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels May 22, 2026
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Comment thread apisx/v1alpha1/xbackend_types.go Outdated
Comment thread apisx/v1alpha1/shared_types.go
Comment thread apisx/v1alpha1/xbackend_types.go
Comment thread apisx/v1alpha1/xbackend_types.go Outdated
Comment thread apisx/v1alpha1/xbackend_types.go Outdated
// ParentRef identifies the parent resource that this status is associated with.
//
// +required
ParentRef v1.ParentReference `json:"parentRef"`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As the Backend resource doesn't have a parentRef in the spec, what is supposed to be the parent here? Maybe ancestorRef would be a better fit, especially if it is referencing a Gateway or ListenerSet

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I was mainly going off of InferencePool: https://github.com/kubernetes-sigs/gateway-api-inference-extension/blob/main/api/v1/inferencepool_types.go#L231. Happy to change the name (ancestorRef does sound a bit better here), but was going for consistency first

Copy link
Copy Markdown
Member

@snorwin snorwin May 27, 2026

Choose a reason for hiding this comment

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

@kl52752 wouldn't we run into the same issues as with BackendTLSPolicy if we add a status per Gateway here?

@keithmattix might be worth revisiting the discussion we had on this at EGADS: https://docs.google.com/document/d/16hBNghI_J4Rbesk_hSJZhT0iBRsQwDNZspWb2UCYeM8/edit?tab=t.euigbuw01pdp#heading=h.h6cyawqw9mcg

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just thinking out loud, it could be quite a burden for implementations to add a status on the Backend resource for every referrer. Today, performance-aware implementations usually reconcile Services independently from HTTPRoutes and Gateways, and adding a status per HTTPRoute or Gateway wouldn't prevent that.

@howardjohn, curious if you share these concerns?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think the main difference with Backend is that it's always ref'd by something else that has a direct link to the Gateway (e.g. xRoute or even InferencePool via extensionRef). Because of that, calculating the ancestor becomes a lot easier. IIUC, the complexity with BackendTLSPolicy is that it can target multiple things.

I'm confusing myself writing this so let's try an example. Let's say I've got Backend foo that is referenced in HTTPRoutes A, B, and C that have parentRefs X, Y, and Z respectively. For the sake of simplicity, let's say we only have one controller (I'll just use istio). The status for that Backend would look like this:

apiVersion: gateway.networking.x-k8s.io/v1alpha1
kind: XBackend
metadata:
  name: foo
spec:
...
status:
- controllerName: istio
  ancestorRef: # or parentRef
    group: gateway.networking.k8s.io
    kind: Gateway
    name: X
  conditions: []
- controllerName: istio
  ancestorRef: # or parentRef
    group: gateway.networking.k8s.io
    kind: Gateway
    name: Y
  conditions: []
- controllerName: istio
  ancestorRef: # or parentRef
    group: gateway.networking.k8s.io
    kind: Gateway
    name: Y
  conditions: []

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@snorwin wouldn't the status be a resolvedref on the route describing the error?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@keithmattix yes, that makes sense. The question is whether it would also be visible on the Backend status, or if it would be just Accepted=true as long as at least one xRoute of a Gateway successfully references the Backend.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah I would think the latter. The alternative is to make the route the parent (different from policy and InferencePool), but the status could get absolutely massive from that with little benefit IMO since it's duplicated info from the route in most cases

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I tend to be a little skeptical that this per-referent status field is actually going to be useful enough to outweigh the complexity of implementation – but that said, this is experimental, so at this point I'd vote to leave it in (with ancestorRef rather than parentRef) with a note to the tune of "if implementing this turns out to be awful, we'll drop it".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fair enough; done!

Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Comment thread geps/gep-4894/index.md Outdated
Comment thread geps/gep-4894/metadata.yaml Outdated
Comment thread .gitignore
Comment thread apisx/v1alpha1/xbackend_types.go Outdated
Comment thread apisx/v1alpha1/xbackend_types.go Outdated
Comment thread apisx/v1alpha1/xbackend_types.go Outdated
Comment thread apisx/v1alpha1/xbackend_types.go Outdated
//
// Support: Extended for MCP; Core for TCP, HTTP, HTTP2, H2C, and HTTP11
//
// +optional
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

given this is optional, what is the default behavior when empty? I can see some phrasing on when this is useful above, but making it more clear: if user sets, what happens? if it is not set, what happens?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The proxy will use whatever protocol was declared via routes or filters. Added some language on this

Comment thread apisx/v1alpha1/xbackend_types.go Outdated
Comment thread apisx/v1alpha1/xbackend_types.go Outdated
// enforce that hostnames ending with those trust domains
// (e.g. .cluster.local) are not allowed.
//
// +kubebuiler:validation:XValidation:rule="!endsWith(self.hostname, '.cluster.local')))",message="hostname must not be an IP address or end with .cluster.local"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

same here, you can use https://kubernetes.io/docs/reference/using-api/cel/#kubernetes-ip-address-library to validate if this is an IP, and if it is a valid dnsLabel (unless you wanna go with PreciseHostname validations directly but I think it accepts IPv4 from what I can see)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Looks like PreciseHostname actually prevents IP addresses:

// matches the RFC 1123 definition of a hostname with 1 notable exception that
. And it validates a DNS label as well.

Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
// when mode is ClientAndServer and must be unset otherwise.
//
// +optional
ClientCertificateRef *v1.SecretObjectReference `json:"clientCertificateRef,omitempty"`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

so client certificate will be the same for ALL parents (aka Gateways)? If backend is going to be used from Egres don't we want to divers client certificate based on Gateway the traffic is comming from?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think the client cert depends on the destination so I'd rephrase that statement: "Any gateway using this backend will use the same client certificate because they're talking to the same destination". The egress gateway is an implementation detail of how you get there

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I agree with @keithmattix: to me, part of the point of Backend is that by definition it will always be used to group endpoints that are equivalent and that must be spoken to the same way. If you need two different TLS setups, you'd set up a Route with multiple backendRefs spanning multiple Backends.

Comment thread apisx/v1alpha1/xbackend_types.go Outdated
// +required
ParentRef v1.ParentReference `json:"parentRef"`

// Conditions describe the current state of the Backend with respect to
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

do you have some proposal what kind of conditions should be set? We don't have references to resolved, we have same CEL matching. What should be the scenarios that this Backend can be rejected by the parent?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good question; I can add these to the type comments. The main one that come to mind is Accepted just to validate that the controller reads backend resources. This would also be the place where a gateway that doesn't allow external hostname backends would say "no I don't accept this"

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. and removed do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels May 29, 2026
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
@rikatz
Copy link
Copy Markdown
Member

rikatz commented May 29, 2026

/approve

leaving lgtm for @kflynn and @mikemorris

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: keithmattix, rikatz

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

The pull request process is described 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

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 29, 2026
Comment thread apisx/v1alpha1/xbackend_types.go Outdated
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
Signed-off-by: Keith Mattix II <keithmattix2@gmail.com>
@kflynn
Copy link
Copy Markdown
Contributor

kflynn commented May 29, 2026

/lgtm
/cherry-pick release-1.6

@k8s-infra-cherrypick-robot
Copy link
Copy Markdown
Contributor

@kflynn: once the present PR merges, I will cherry-pick it on top of release-1.6 in a new PR and assign it to you.

Details

In response to this:

/lgtm
/cherry-pick release-1.6

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 29, 2026
@kflynn
Copy link
Copy Markdown
Contributor

kflynn commented May 30, 2026

Going to go ahead and

/unhold

since I think all the outstanding feedback has been addressed.

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 30, 2026
@k8s-ci-robot k8s-ci-robot merged commit 1249547 into kubernetes-sigs:main May 30, 2026
20 checks passed
@k8s-infra-cherrypick-robot
Copy link
Copy Markdown
Contributor

@kflynn: new pull request created: #4924

Details

In response to this:

/lgtm
/cherry-pick release-1.6

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/gep PRs related to Gateway Enhancement Proposal(GEP) lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note-none Denotes a PR that doesn't merit a release note. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants