build(deps): gateway api 1.5.1 support via linkerd-kubert 0.27.0 - #15567
Merged
Conversation
alpeb
force-pushed
the
alpeb/linkerd-kubert-0.27.0
branch
from
August 11, 2026 14:47
952580a to
6d798ab
Compare
alpeb
marked this pull request as draft
August 11, 2026 14:47
alpeb
force-pushed
the
alpeb/linkerd-kubert-0.27.0
branch
2 times, most recently
from
August 11, 2026 20:00
12c15d3 to
5085316
Compare
This carries a kube-rs bump to 3.x, which forces the rest of the workspace along with it: * gateway-api 0.16 -> 0.21: this brings support for gateway api spec v1.5.1 * k8s-openapi 0.25 -> 0.27 * kube 1.1 -> 3.1 * schemars 0.8 -> 1 * ipnet switches from the `json` feature to `serde` + `schemars1`, since `json` still pulls in schemars 0.8 * chrono is replaced by jiff 0.2 and drops out of the tree entirely, because k8s-openapi 0.27 backs `metav1::Time` with `jiff::Timestamp` instead of `chrono::DateTime<Utc>` Source changes: * Timestamps: `creation_timestamp`, `last_transition_time` and the `Route::creation_timestamp` trait method move to `jiff::Timestamp`; `Utc::now()` becomes `Timestamp::now()` and `MIN_UTC`/`MAX_UTC` become `Timestamp::MIN`/`MAX`. * schemars 1: the hand-written `JsonSchema` impl for `K8sDuration` uses `Cow<'static, str>` for `schema_name`, `inline_schema()` in place of the inverted `is_referenceable()`, and the `json_schema!` macro. The schema is unchanged; the format is still deliberately unset. * gateway-api renamed its generated sub-types, so `HTTPRoute*` becomes `HttpRoute*`, `GRPCRoute*` becomes `GrpcRoute*`, and likewise for TCP and TLS. The top-level CRD types keep their original names. * Several gateway-api fields are no longer optional: `RouteStatusParents::conditions`, `Tls/TcpRouteRules::backend_refs`, and `TlsRouteSpec::hostnames`/`rules`. `Some(..)` wrappers and the matching `.flatten()` calls are dropped, and route spec literals gain the new `use_default_gateways` field. * kube 3.x deprecates `kube::error::ErrorResponse` in favor of `kube::core::Status`, and `Error::Api` now carries a `Box<Status>`. Note one behavior change the type system forces: now that `RouteStatusParents::conditions` is a plain `Vec`, the `eq_time_insensitive_*_route_parent_statuses` helpers can no longer distinguish an empty condition list from an absent one, so those two cases now compare equal where they previously compared unequal.
alpeb
force-pushed
the
alpeb/linkerd-kubert-0.27.0
branch
from
August 11, 2026 22:30
f9958aa to
9817f2a
Compare
alpeb
marked this pull request as ready for review
August 12, 2026 15:53
alpeb
commented
Aug 12, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
kube-rs (a.k.a "kube") 1.1.0 -> 3.1.0
This forces the rest of the workspace along with it:
jsonfeature toserde+schemars1, sincejsonstill pulls in schemars 0.8metav1::Timewithjiff::Timestampinstead ofchrono::DateTime<Utc>Source changes:
creation_timestamp,last_transition_timeand theRoute::creation_timestamptrait method move tojiff::Timestamp;Utc::now()becomesTimestamp::now()andMIN_UTC/MAX_UTCbecomeTimestamp::MIN/MAX.JsonSchemaimpl forK8sDurationusesCow<'static, str>forschema_name,inline_schema()in place of the invertedis_referenceable(), and thejson_schema!macro. The schema is unchanged; the format is still deliberately unset.kube::error::ErrorResponsein favor ofkube::core::Status, andError::Apinow carries aBox<Status>.gateway-api-rs (a.k.a "gateway-api") 0.16.0 -> 0.21.0
This bumps the gateway api spec support from 1.2.1 to 1.5.1
Forced to be bumped in tandem with the kube-rs bump as gateway-api-rs 0.16.0 was pinned to kube-rs 1.1.0
HTTPRoute*becomesHttpRoute*,GRPCRoute*becomesGrpcRoute*, and likewise for TCP and TLS. The top-level CRD types keep their original names.RouteStatusParents::conditions,Tls/TcpRouteRules::backend_refs, andTlsRouteSpec::hostnames/rules.Some(..)wrappers and the matching.flatten()calls are dropped, and route spec literals gain the newuse_default_gatewaysfield.Note one behavior change the type system forces: now that
RouteStatusParents::conditionsis a plainVec, theeq_time_insensitive_*_route_parent_statuseshelpers can no longer distinguish an empty condition list from an absent one, so those two cases now compare equal where they previously compared unequal.TLSRoute is pinned to
v1alpha2gateway-api-rs 0.21 moved its
TLSRoutebinding fromv1alpha2tov1. The other three kinds are unaffected:TLSRoute only graduated to
v1in Gateway API v1.5:In order to still support Gateway API v1.2.1, we now have in
policy-controller/k8s/api/src/lib.rsa local type pinned tov1alpha2that shadows the one from the crate's glob import (v1). It reusesTlsRouteSpec/TlsRouteStatusunchanged, so it only overrides the group/version/kind the client addresses. It carries a hand-writtenSerializebecausekube::CustomResourcesynthesizesapiVersion/kindrather than storing them as fields, plus a unit test asserting the pinned version.Backwards compatibility
CI now covers v1.2.1/standard as the minimum and v1.5.1/experimental as the maximum, alongside the CLI's vendored CRDs (still bundle v1.1.1; unchanged by this PR).
No impact:
apiVersions: ["*"], andis_kindcompares group and kind only), so TLSRoutes submitted asv1on a v1.5 cluster are still validated. Status patches addressv1alpha2, which is served across the whole range.useDefaultGateways, new in v1.5 on all four route specs, isOptionplusskip_serializing_if. Linkerd never sets it, and never writes route specs back (only the status subresource), so nothing is stripped from user objects.v1bindings, valid from v1.2 onward. Their v1.3.0 to v1.5.1 deltas are either additive (CORS and ExternalAuth filters,requestRedirect.statusCodewidened from[301, 302]to[301, 302, 303, 307, 308], GRPCRoutematchesmaxItems8 to 64) or apiserver-side tightening that does not affect decoding.Worth watching: decoding is now stricter than the endpoints we address.
The bindings are generated from the v1.5.1 schemas, so three fields lost their
Option/#[serde(default)]and are mandatory on the wire:status.parents[].conditionsspec.rules[].backendRefsspec.hostnamesv1/v1alpha3schemas, never inv1alpha2On a pre-v1.5 cluster an object omitting the first two is perfectly legal but no longer decodes. The third is stricter still:
hostnamesis optional inv1alpha2in every release, so a TLSRoute without it fails to decode on any cluster in the supported range.A failing object is logged and skipped rather than killing the watch; the route just never appears in the policy index. Admission is unaffected, since every Gateway API validator is
lenient()and parse failures are admitted with a warning rather than denied, so there are no new rejections for users.Unchanged behaviour worth noting: Linkerd still implements only the
RequestHeaderModifier,ResponseHeaderModifierandRequestRedirectfilters, so the new v1.5CORSandExternalAuthHTTPRoute filters are admitted and ignored, the same as the other filter types we do not support.