v1.4.0
Important
This release changes some defaults. Review these before upgrading:
- Watches are enabled by default (#569):
--enable-watchesnow defaults totrue, which increases the provider's resource consumption. Set--enable-watches=falsethrough aDeploymentRuntimeConfigto keep the previous behavior. - Startup requires readable ProviderConfigs (#560): the provider sizes its client cache from the cluster at startup and fails to start if its ProviderConfigs and their credentials cannot be read within 300 seconds.
- Client-side rate limiting is disabled for target cluster clients (#543): a cached client is shared by all concurrent reconciles of its credential set. Load on target clusters is bounded by
--max-reconcile-rateand the API server's Priority and Fairness.
Performance
This release removes most of the provider's memory and API server overhead on large clusters. Target cluster clients are built once per credential set instead of once per reconcile (#543), the client cache sizes itself and reports metrics (#560), CRD schemas no longer sit in the provider's informer cache and the Secret informer can be turned off (#549), and the CRD gate ignores CRDs of other providers (#574). Measured with a reconcile load test on a kind cluster carrying the provider-upjet-aws CRD set (~2,000 CRDs) and 3,000 Secrets, with 300 Objects each managing a ConfigMap and publishing a connection Secret, averaged over three update rounds:
| v1.3.0 | Client cache only | Client cache, CRD schema strip, --enable-secret-cache=false
| |
|---|---|---|---|
| Aggregated discovery requests per round | hundreds | single digits | single digits |
| Peak heap in use | 1.5-1.9 GiB | 450 MiB | 72 MiB |
| Allocation per round | ~2.2 GiB | ~240 MiB | ~250 MiB |
By default v1.4.0 runs the client cache and the CRD schema strip with the Secret informer on, so it lands between the last two columns. Disabling the Secret cache through a DeploymentRuntimeConfig trades roughly 200 live Secret reads per round for the remaining memory. There is nothing to size by hand: a sustained provider_kubernetes_client_cache_events_total{event="evict"} rate is the signal that more credential sets appeared than the cache was sized for at startup.
New Features
-
Watches promoted to beta and enabled by default (#569): The Watches feature graduates from alpha to beta (feature flag
EnableAlphaWatchesis nowEnableBetaWatches) and--enable-watchesnow defaults totrue, soObjects withspec.watch: truereact to changes of their managed and referenced resources without extra configuration. -
Automatic client cache sizing and cache metrics (#560): At startup the provider lists its
ProviderConfigandClusterProviderConfigobjects, counts the distinct credential sets and sizes the target cluster client cache to that count plus headroom (10% or 4 entries, whichever is larger, never below 8). The computed size is logged at startup, and the cache exposesprovider_kubernetes_client_cache_size,provider_kubernetes_client_cache_entriesandprovider_kubernetes_client_cache_events_total{event="hit|miss|evict"}. Cache hits no longer re-run the cloud identity wrappers (GKE, AWS, Azure, Nebius, Upbound). -
CEL optional field selection in readiness queries (#575): The
DeriveFromCelQueryreadiness policy now supports.?andorValue(), so queries no longer need ahas()guard on every level, e.g.object.?status.?conditions.orValue([]).exists(c, c.type == "Complete" && c.status == "True"). Existing queries are unaffected. -
Leaner caches with crossplane-runtime v2.4.0 (#549): CRD schemas are stripped from cached CRD objects, reducing the provider's baseline memory. A new
--enable-secret-cacheflag (defaulttrue, matching prior behavior) lets you serve Secrets with direct API calls instead of an informer cache. Also shipped in v1.3.1. -
Gate controller only considers provider CRDs (#574): The CRD Gate controller now filters on the provider's own API groups and ignores all other CRDs in the cluster.
-
ProviderConfigs protected while managed resources terminate (#565): Consumes crossplane-runtime#1113, which adds a finalizer to
ProviderConfigUsageso aProviderConfigcannot be deleted while anObjectthat uses it is still terminating. -
Configurable TLS certs directory and working
make run(#532): A new--certs-dirflag (CERTS_DIRenv) sets the TLS certificate directory; setting it to an empty string disables the conversion webhook.make runnow strips the partial conversion stanza from the CRDs and runs without TLS certificates, fixing out-of-cluster development (#343, #249).
Bug Fixes
-
Fix ObservedObjectCollection failing to create Objects (#556):
deletionPropagationPolicyis no longer serialized as an empty string, which made everyObjectcreated by anObservedObjectCollectionfail validation in v1.3.0 (#555). Also shipped in v1.3.1. -
Stop running full API discovery on every reconcile (#543): Target cluster clients are now cached per credential set, so aggregated discovery runs once per credential set instead of once per reconcile. On a cluster with 1000 CRDs and 300
Objects, discovery requests per round dropped by 99% and peak provider memory by ~85% (#541). EKS tokens are now issued with the request context, so IRSA credentials keep refreshing for clients that outlive a reconcile. -
Fix
Createfailing forever after the target was deleted out of band (#581): The client-side-apply to server-side-apply field manager migration patched the resource recorded instatus.atProvider.manifesteven whenObservehad just found it gone. AnObjectwhose target was removed outside the provider after a client-side-apply provider version had observed it, for example aJobwithttlSecondsAfterFinishedacross an upgrade, failed everyCreatewithcannot upgrade field managers: ... not foundand never recreated it. The migration patch now ignores a missing target and the apply that follows creates it under the SSA field manager; the same race onUpdateis covered. StuckObjects heal on the first reconcile after upgrading. -
Do not create resources when the
Createmanagement policy is not set (#571): Consumes crossplane-runtime#1130, which skipsUpdateandLateInitializefor non-existent resources. Because the provider uses server-side apply, the update path previously created the resource even whenCreatewas excluded frommanagementPolicies(#542). -
Document write-only field limitation (#534): The README now has a "Known limitations" section explaining why write-only fields such as
Secret.stringDatacannot be reconciled inObjectmanifests, and recommends round-trippable fields (e.g. base64data) instead. The underlying issues (#418, #420) remain open.
Dependency & Security Updates
- Crossplane runtime bumped to v2.4.0 (#549), then to
main(v2.5.0-rc.0.0.20260922181840-9d02af3667a0) to consume crossplane-runtime#1113 and #1130 (#565, #571) - Kubernetes libraries → v0.37.1,
sigs.k8s.io/controller-runtime→ v0.25.2,sigs.k8s.io/controller-tools→ v0.22.0 - Security patches:
google.golang.org/grpc→ v1.84.0 (#557, #568),golang.org/x/net→ v0.58.0,golang.org/x/crypto→ v0.56.0,github.com/google/cel-go→ v0.30.0,go.opentelemetry.io/otel→ v1.45.0 github.com/pkg/errorsis no longer a direct dependency (#566)- Go toolchain updated to v1.27.1
- E2E tests run against Crossplane v2.4.2 and now cover
ObservedObjectCollectionand CEL optional readiness queries
Contributors
Thank you to everyone who contributed to this release:
- @bobh66 (Bob Haddleton)
- @jonasz-lasut (Jonasz Małecki)
- @rashiq (Rashiq)
What's Changed
- Fix per reconcile discovery by @jonasz-lasut in #543
- Add a client cache autopilot as a replacement for user-provided flag by @jonasz-lasut in #560
- Remove imports of github.com/pkg/errors by @jonasz-lasut in #566
- Update module google.golang.org/grpc to v1.83.1 [SECURITY] by @renovate[bot] in #557
- Update dependency kubernetes-sigs/kind to v0.33.0 by @renovate[bot] in #553
- Consume crossplane-runtime #1113 by @jonasz-lasut in #565
- Add --certs-dir flag and fix make run by @jonasz-lasut in #532
- docs: document write-only field limitation in Object manifests by @jonasz-lasut in #534
- Promote Watches feature to beta by @jonasz-lasut in #569
- Update module google.golang.org/grpc to v1.83.2 [SECURITY] by @renovate[bot] in #568
- Update docker/setup-qemu-action digest to 9901266 - autoclosed by @renovate[bot] in #567
- Update crossplane-runtime to consume crossplane/crossplane-runtime#1130 by @jonasz-lasut in #571
- Update gate controller options to filter out unnecessary CRDs. by @bobh66 in #574
- feat(object): enable CEL optional field selection in readiness queries by @rashiq in #575
- Update dependency go to v1.27.1 by @renovate[bot] in #547
- Update codecov/codecov-action digest to 303a32d by @renovate[bot] in #570
- Update docker/setup-buildx-action digest to f87e599 by @renovate[bot] in #572
- Update dependency crossplane/crossplane to v2.4.2 by @renovate[bot] in #552
- Update dependency docker/buildx to v0.37.2 by @renovate[bot] in #525
- Update dependency golangci/golangci-lint to v2.14.0 by @renovate[bot] in #579
- Update gcr.io/distroless/static Docker digest to 5813399 by @renovate[bot] in #577
- Update kubernetes patches by @renovate[bot] in #578
- fix(object): skip SSA manager migration when target is gone by @jonasz-lasut in #581
New Contributors
Full Changelog: v1.3.1...v1.4.0