github crossplane-contrib/provider-kubernetes v1.4.0

6 hours ago

v1.4.0

Important

This release changes some defaults. Review these before upgrading:

  • Watches are enabled by default (#569): --enable-watches now defaults to true, which increases the provider's resource consumption. Set --enable-watches=false through a DeploymentRuntimeConfig to 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-rate and 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 EnableAlphaWatches is now EnableBetaWatches) and --enable-watches now defaults to true, so Objects with spec.watch: true react 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 ProviderConfig and ClusterProviderConfig objects, 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 exposes provider_kubernetes_client_cache_size, provider_kubernetes_client_cache_entries and provider_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 DeriveFromCelQuery readiness policy now supports .? and orValue(), so queries no longer need a has() 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-cache flag (default true, 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 ProviderConfigUsage so a ProviderConfig cannot be deleted while an Object that uses it is still terminating.

  • Configurable TLS certs directory and working make run (#532): A new --certs-dir flag (CERTS_DIR env) sets the TLS certificate directory; setting it to an empty string disables the conversion webhook. make run now 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): deletionPropagationPolicy is no longer serialized as an empty string, which made every Object created by an ObservedObjectCollection fail 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 Create failing 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 in status.atProvider.manifest even when Observe had just found it gone. An Object whose target was removed outside the provider after a client-side-apply provider version had observed it, for example a Job with ttlSecondsAfterFinished across an upgrade, failed every Create with cannot upgrade field managers: ... not found and 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 on Update is covered. Stuck Objects heal on the first reconcile after upgrading.

  • Do not create resources when the Create management policy is not set (#571): Consumes crossplane-runtime#1130, which skips Update and LateInitialize for non-existent resources. Because the provider uses server-side apply, the update path previously created the resource even when Create was excluded from managementPolicies (#542).

  • Document write-only field limitation (#534): The README now has a "Known limitations" section explaining why write-only fields such as Secret.stringData cannot be reconciled in Object manifests, and recommends round-trippable fields (e.g. base64 data) 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/errors is no longer a direct dependency (#566)
  • Go toolchain updated to v1.27.1
  • E2E tests run against Crossplane v2.4.2 and now cover ObservedObjectCollection and CEL optional readiness queries

Contributors

Thank you to everyone who contributed to this release:

What's Changed

New Contributors

Full Changelog: v1.3.1...v1.4.0

Don't miss a new provider-kubernetes release

NewReleases is sending notifications on new releases.