From 8d996a58bcb86de775953cb6bb7b69631c9dcb3b Mon Sep 17 00:00:00 2001 From: Christopher Haar Date: Mon, 11 May 2026 13:58:32 +0200 Subject: [PATCH] feat(protection): document new provider deletion protection with clusterusages Signed-off-by: Christopher Haar --- content/master/get-started/install.md | 1 + content/master/managed-resources/usages.md | 28 ++++--- content/master/packages/providers.md | 93 ++++++++++++++++++++++ 3 files changed, 112 insertions(+), 10 deletions(-) diff --git a/content/master/get-started/install.md b/content/master/get-started/install.md index bc1b6b155..f7fd6cefc 100644 --- a/content/master/get-started/install.md +++ b/content/master/get-started/install.md @@ -110,6 +110,7 @@ at the table below. | Beta | `--enable-realtime-compositions` | Enable support for real time compositions. | | Alpha | `--enable-dependency-version-upgrades ` | Enable automatic version upgrades of dependencies when updating packages. | | Alpha | `--enable-function-response-cache` | Enable caching of composition function responses to improve performance. | +| Alpha | `--enable-provider-deletion-protection` | Enable automatic protection of Providers from deletion when they have active managed resources. Requires `--enable-usages`. | | Alpha | `--enable-signature-verification` | Enable support for package signature verification via ImageConfig API. | {{< /table >}} {{< /expand >}} diff --git a/content/master/managed-resources/usages.md b/content/master/managed-resources/usages.md index 69a94b4c3..81c212ebf 100644 --- a/content/master/managed-resources/usages.md +++ b/content/master/managed-resources/usages.md @@ -11,7 +11,7 @@ A `Usage` indicates a resource is in use. Two main use cases for Usages are as follows: 1. Protecting a resource from accidental deletion. -2. Deletion ordering by ensuring that a resource isn't deleted before the +2. Deletion ordering by ensuring that a resource isn't deleted before the deletion of its dependent resources. See the section [Usage for Deletion Protection](#usage-for-deletion-protection) for the @@ -23,9 +23,9 @@ for the second one. Usages are a beta feature. Crossplane enables beta features by default. -Disable `Usage` support by +Disable `Usage` support by [changing the Crossplane pod setting]({{}}) -and setting +and setting {{}}--enable-usages=false{{}} argument. @@ -46,8 +46,8 @@ spec: {{}} -The [Crossplane install guide]({{}}) -describes enabling feature flags like +The [Crossplane install guide]({{}}) +describes enabling feature flags like {{}}\-\-enable-usages{{}} with Helm. {{< /hint >}} @@ -60,7 +60,7 @@ with Helm. A {{}}Usage{{}} {{}}spec{{}} has a mandatory {{}}of{{}} field for defining the resource -in use or protected. The +in use or protected. The {{}}reason{{}} field defines the reason for protection and the {{}}by{{}} field defines the using resource. Both fields are optional, but at least one of them @@ -69,7 +69,7 @@ must be provided. ### Usage for deletion protection -The following example prevents the deletion of the +The following example prevents the deletion of the {{}}my-database{{}} resource by rejecting any deletion request with the {{}}reason{{}} defined. @@ -93,7 +93,7 @@ spec: The following example prevents the deletion of {{}}my-cluster{{}} resource by rejecting -any deletion request before the deletion of +any deletion request before the deletion of {{}}my-prometheus-chart{{}} resource. ```yaml {label="order"} @@ -146,7 +146,7 @@ spec: ``` After the `Usage` controller resolves the selectors, it persists the resource -name in the +name in the {{}}resourceRef.name{{}} field. The following example shows the `Usage` resource after the resolution of selectors. @@ -235,7 +235,7 @@ When there are multiple resources of same type in a Composition, the uniquely identify the resource in use or the using one. This could be accomplished by using extra labels and combining {{}}matchControllerRef{{}} -with a `matchLabels` selector. +with a `matchLabels` selector. {{< /hint >}} @@ -289,3 +289,11 @@ spec: name: importantresources.example.crossplane.io reason: "Very important CRD - should never be deleted!" ``` + +{{}} +Crossplane can automatically create `ClusterUsage` resources to protect +Providers from accidental deletion when they have active managed resources. +Enable this with the `--enable-provider-deletion-protection` alpha feature flag. +See [Provider deletion protection]({{}}) +for details. +{{< /hint >}} diff --git a/content/master/packages/providers.md b/content/master/packages/providers.md index 0ffcc3f54..a8f052d9d 100644 --- a/content/master/packages/providers.md +++ b/content/master/packages/providers.md @@ -457,6 +457,99 @@ removing their finalizers. For more information on deleting abandoned resources read the [Crossplane troubleshooting guide]({{}}). {{< /hint >}} +### Provider deletion protection + +{{}} +Provider deletion protection is an alpha feature. Crossplane disables alpha +features by default. + +Enable Provider deletion protection with the +`--enable-provider-deletion-protection` +[feature flag]({{}}). +This feature also requires +[Usages]({{}}) to be enabled (on by default). + +```shell {label="protection-helm"} +helm upgrade --install crossplane crossplane-stable/crossplane \ + --namespace crossplane-system \ + --set args='{"--enable-provider-deletion-protection"}' +``` +{{}} + +When Provider deletion protection is enabled, Crossplane automatically prevents +the deletion of Providers that still have active managed resources. This +protects against accidentally removing a Provider and orphaning its managed +resources. + +Crossplane watches for managed resources associated with each Provider. When +managed resources exist, Crossplane creates a +[ClusterUsage]({{}}) that +blocks deletion of the owning Provider. The `ClusterUsage` includes a +descriptive reason indicating which managed resource type is still active, +for example `"Provider has active managed resources of type +VPC.ec2.aws.upbound.io"`. + +When all managed resources of a given type are deleted, Crossplane automatically +removes the corresponding `ClusterUsage`, allowing the Provider to be deleted. + +List all provider protection `ClusterUsages` using the +`crossplane.io/provider-protection=true` label: + +```shell {copy-lines="1"} +kubectl get clusterusages -l crossplane.io/provider-protection=true +NAME AGE +provider-protection-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6 5m +``` + +{{}} +Crossplane generates `ClusterUsage` names using a hash of the +`ManagedResourceDefinition` name. Use the +`crossplane.io/provider-protection=true` label to find them. + +Each `ClusterUsage` also has labels for the Provider name +(`pkg.crossplane.io/package`) and the MRD name +(`apiextensions.crossplane.io/mrd`). +{{< /hint >}} + +Inspect a specific `ClusterUsage` to see which Provider it protects and why: + +```yaml +apiVersion: protection.crossplane.io/v1beta1 +kind: ClusterUsage +metadata: + name: provider-protection-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6 + labels: + crossplane.io/provider-protection: "true" + pkg.crossplane.io/package: crossplane-contrib-provider-aws-s3 + apiextensions.crossplane.io/mrd: buckets.s3.aws.upbound.io +spec: + of: + apiVersion: pkg.crossplane.io/v1 + kind: Provider + resourceRef: + name: crossplane-contrib-provider-aws-s3 + reason: "Provider has active managed resources of type Bucket.s3.aws.upbound.io" +``` + +Attempting to delete a Provider with active managed resources returns an error +from the Usage admission webhook: + +```shell +$ kubectl delete provider.pkg.crossplane.io/provider-aws-ec2 +Error from server (This resource is in-use by 3 usage(s), including the + *v1beta1.ClusterUsage "provider-protection-774712aa693d57a5e7ce09a7754d53f3 + ca5cc59f417083756b2a" with reason: "Provider has active managed resources of + type SecurityGroup.ec2.aws.m.upbound.io".): admission webhook + "nousages.protection.crossplane.io" denied the request: This resource is + in-use by 3 usage(s), including the *v1beta1.ClusterUsage + "provider-protection-774712aa693d57a5e7ce09a7754d53f3ca5cc59f417083756b2a" + with reason: "Provider has active managed resources of type + SecurityGroup.ec2.aws.m.upbound.io". +``` + +To delete a protected Provider, first remove all its managed resources, or +manually delete the `ClusterUsage` resource protecting it. + ## Verify a Provider Providers install their own APIs representing the managed resources they support.