mirror of https://github.com/crossplane/docs.git
Merge ed31ce59ef into 469b94324a
This commit is contained in:
commit
8fe17f1aa0
|
|
@ -0,0 +1,403 @@
|
||||||
|
---
|
||||||
|
title: Change Provider Registries
|
||||||
|
weight: 415
|
||||||
|
description: "Change from one provider to a compatible provider in a different registry"
|
||||||
|
---
|
||||||
|
|
||||||
|
When you change a provider's OCI reference to a different registry, Crossplane
|
||||||
|
updates the provider itself with a new revision. Crossplane treats any
|
||||||
|
**dependencies it automatically installs** (like family providers) as entirely
|
||||||
|
separate packages. These require careful coordination.
|
||||||
|
|
||||||
|
This problem affects:
|
||||||
|
|
||||||
|
* **Providers with family dependencies**: Most cloud providers depend on a
|
||||||
|
family provider (like `provider-gcp-compute` depending on `provider-family-gcp`)
|
||||||
|
* **Providers installed as Configuration dependencies**: When a Configuration
|
||||||
|
package lists providers as dependencies
|
||||||
|
|
||||||
|
**Single providers without dependencies change automatically** - no manual
|
||||||
|
intervention needed.
|
||||||
|
|
||||||
|
The most common conflict occurs with **family provider dependencies**. For
|
||||||
|
example, when changing `provider-gcp-compute` from Upbound to Crossplane
|
||||||
|
Contrib, both versions depend on different family providers:
|
||||||
|
|
||||||
|
* Old: `xpkg.upbound.io/upbound/provider-gcp-compute` → depends on `upbound/provider-family-gcp`
|
||||||
|
* New: `xpkg.crossplane.io/crossplane-contrib/provider-gcp-compute` → depends on `crossplane-contrib/provider-family-gcp`
|
||||||
|
|
||||||
|
This creates two active family providers competing for the same resources,
|
||||||
|
causing errors like:
|
||||||
|
|
||||||
|
```console
|
||||||
|
cannot establish control of object: providerconfigusages.gcp.upbound.io is already controlled by ProviderRevision upbound-provider-family-gcp-f0aa3640a6a9
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Before changing providers, ensure:
|
||||||
|
|
||||||
|
* Crossplane v2.0 or later
|
||||||
|
* `kubectl` access to your cluster
|
||||||
|
* Understanding of your current provider setup
|
||||||
|
* Time for testing and validation
|
||||||
|
* Backup of critical resources
|
||||||
|
|
||||||
|
{{<hint "tip">}}
|
||||||
|
Test this change in a staging environment first. The process is safe but
|
||||||
|
requires careful verification at each step.
|
||||||
|
{{</hint>}}
|
||||||
|
|
||||||
|
## Why manual coordination works best
|
||||||
|
|
||||||
|
Crossplane names package dependencies using OCI repository paths. It uses the
|
||||||
|
pattern `<org>-<repo>`. When you change from `upbound/provider-gcp-compute` to
|
||||||
|
`crossplane-contrib/provider-gcp-compute`, Crossplane sees these as separate
|
||||||
|
providers and creates both:
|
||||||
|
|
||||||
|
* `upbound-provider-family-gcp` (old, still active)
|
||||||
|
* `crossplane-contrib-provider-family-gcp` (new, requires ownership coordination)
|
||||||
|
|
||||||
|
Both family providers manage the same CRDs and MRDs, requiring careful
|
||||||
|
coordination of ownership transfer.
|
||||||
|
|
||||||
|
Crossplane takes this approach because determining package equivalence is
|
||||||
|
complex. For example, an older Upbound provider version might differ from a
|
||||||
|
newer Crossplane Contrib version - with more CRDs, different controller
|
||||||
|
behavior, or updated APIs. Automatically replacing dependencies could break
|
||||||
|
existing resources or introduce unexpected behavior.
|
||||||
|
|
||||||
|
Manual coordination gives you explicit control to transition ownership
|
||||||
|
from old to new providers with full visibility into each step.
|
||||||
|
|
||||||
|
## Process overview
|
||||||
|
|
||||||
|
The manual process follows this safe sequence:
|
||||||
|
|
||||||
|
1. **Update provider package** - Change the provider's OCI reference
|
||||||
|
2. **Identify conflicts** - Find which family provider has conflicts
|
||||||
|
3. **Set manual activation** - Prevent the old family provider from staying active
|
||||||
|
4. **Deactivate old revision** - Stop the old family provider from managing resources
|
||||||
|
5. **Verify transition** - Ensure the new family provider manages all resources
|
||||||
|
6. **Clean up** - Remove the old family provider
|
||||||
|
|
||||||
|
This deliberate approach gives you full control over the timing and
|
||||||
|
validation, prevents orphaning resources, and provides clear rollback
|
||||||
|
points.
|
||||||
|
|
||||||
|
## Step-by-step process
|
||||||
|
|
||||||
|
This example changes from Upbound's GCP Compute provider to the Crossplane
|
||||||
|
community version, which demonstrates the family provider dependency issue:
|
||||||
|
|
||||||
|
* **From**: `xpkg.upbound.io/upbound/provider-gcp-compute:v1.14.1`
|
||||||
|
* **To**: `xpkg.crossplane.io/crossplane-contrib/provider-gcp-compute:v2.0.0`
|
||||||
|
|
||||||
|
This change requires coordinating multiple package dependencies because each
|
||||||
|
version depends on a different family provider.
|
||||||
|
|
||||||
|
### Step 1: Inventory current providers
|
||||||
|
|
||||||
|
Check your current provider setup:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get providers
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
NAME INSTALLED HEALTHY PACKAGE AGE
|
||||||
|
upbound-provider-family-gcp True True xpkg.upbound.io/upbound/provider-family-gcp:v1.14.1 30d
|
||||||
|
provider-gcp-compute True True xpkg.upbound.io/upbound/provider-gcp-compute:v1.14.1 30d
|
||||||
|
```
|
||||||
|
|
||||||
|
List managed resources to understand what the provider manages:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get managed
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||||
|
address.compute.gcp.upbound.io/my-address True True my-address-abc123 5d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Update the provider package
|
||||||
|
|
||||||
|
Edit the existing provider to change its package reference:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl patch provider provider-gcp-compute --type=merge \
|
||||||
|
-p='{"spec":{"package":"xpkg.crossplane.io/crossplane-contrib/provider-gcp-compute:v2.0.0"}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a new family provider dependency. Check what providers exist:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get providers
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
NAME INSTALLED HEALTHY PACKAGE AGE
|
||||||
|
crossplane-contrib-provider-family-gcp True False xpkg.crossplane.io/crossplane-contrib/provider-family-gcp:v2.0.0 2m
|
||||||
|
upbound-provider-family-gcp True True xpkg.upbound.io/upbound/provider-family-gcp:v1.14.1 30d
|
||||||
|
provider-gcp-compute True True xpkg.crossplane.io/crossplane-contrib/provider-gcp-compute:v2.0.0 2m
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice the new family provider is `HEALTHY=False` due to the ownership conflict.
|
||||||
|
|
||||||
|
### Step 3: Set old family provider to manual activation
|
||||||
|
|
||||||
|
Prevent the old family provider from automatically activating its revisions:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl patch provider upbound-provider-family-gcp --type=merge \
|
||||||
|
-p='{"spec":{"revisionActivationPolicy":"Manual"}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify the change:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get provider upbound-provider-family-gcp -o yaml | grep revisionActivationPolicy
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
revisionActivationPolicy: Manual
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Deactivate old family provider revision
|
||||||
|
|
||||||
|
Find the current revision of the old family provider:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get providerrevisions | grep upbound-provider-family-gcp
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
NAME HEALTHY REVISION IMAGE STATE DEP-FOUND DEP-INSTALLED AGE
|
||||||
|
upbound-provider-family-gcp-f0aa3640a6a9 True 1 xpkg.upbound.io/upbound/provider-family-gcp:v1.14.1 Active 0 0 30d
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the old family provider revision to inactive:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl patch providerrevision upbound-provider-family-gcp-f0aa3640a6a9 --type=merge \
|
||||||
|
-p='{"spec":{"desiredState":"Inactive"}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Verify the new family provider becomes healthy
|
||||||
|
|
||||||
|
Check that the new family provider can now establish control:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get providers
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
NAME INSTALLED HEALTHY PACKAGE AGE
|
||||||
|
crossplane-contrib-provider-family-gcp True True xpkg.crossplane.io/crossplane-contrib/provider-family-gcp:v2.0.0 5m
|
||||||
|
upbound-provider-family-gcp True True xpkg.upbound.io/upbound/provider-family-gcp:v1.14.1 30d
|
||||||
|
provider-gcp-compute True True xpkg.crossplane.io/crossplane-contrib/provider-gcp-compute:v2.0.0 5m
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify the old family provider revision is inactive:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get providerrevisions | grep upbound-provider-family-gcp
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
NAME HEALTHY REVISION IMAGE STATE DEP-FOUND DEP-INSTALLED AGE
|
||||||
|
upbound-provider-family-gcp-f0aa3640a6a9 True 1 xpkg.upbound.io/upbound/provider-family-gcp:v1.14.1 Inactive 0 0 30d
|
||||||
|
```
|
||||||
|
|
||||||
|
Check that managed resources are still healthy:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get managed
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||||
|
address.compute.gcp.upbound.io/my-address True True my-address-abc123 5d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 6: Delete the old family provider
|
||||||
|
|
||||||
|
After verifying everything works, remove the old family provider:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl delete provider upbound-provider-family-gcp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 7: Final verification
|
||||||
|
|
||||||
|
Confirm only the new providers remain:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get providers
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
NAME INSTALLED HEALTHY PACKAGE AGE
|
||||||
|
crossplane-contrib-provider-family-gcp True True xpkg.crossplane.io/crossplane-contrib/provider-family-gcp:v2.0.0 10m
|
||||||
|
provider-gcp-compute True True xpkg.crossplane.io/crossplane-contrib/provider-gcp-compute:v2.0.0 10m
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify managed resources are still healthy:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get managed
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||||
|
address.compute.gcp.upbound.io/my-address True True my-address-abc123 5d
|
||||||
|
```
|
||||||
|
|
||||||
|
## Other common scenarios
|
||||||
|
|
||||||
|
### Providers without dependencies
|
||||||
|
|
||||||
|
For providers that don't depend on other packages (like `provider-helm`,
|
||||||
|
`provider-kubernetes`, or standalone providers), the change happens automatically:
|
||||||
|
|
||||||
|
1. Update the provider's `spec.package`
|
||||||
|
2. Crossplane creates a new revision with the new package
|
||||||
|
3. The old revision automatically becomes inactive
|
||||||
|
4. No conflicts occur because there are no dependencies
|
||||||
|
|
||||||
|
Examples of providers that typically change automatically:
|
||||||
|
|
||||||
|
* `provider-helm`
|
||||||
|
* `provider-kubernetes`
|
||||||
|
* `provider-sql`
|
||||||
|
|
||||||
|
{{<hint "tip">}}
|
||||||
|
<!-- vale Google.WordList = NO -->
|
||||||
|
You can check which providers have dependencies by inspecting the package lock:
|
||||||
|
<!-- vale Google.WordList = YES -->
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get lock lock -o yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Look for providers with non-empty `dependencies` arrays. For example:
|
||||||
|
```yaml
|
||||||
|
- name: provider-gcp-compute-a41e4ba551fc
|
||||||
|
dependencies:
|
||||||
|
- constraints: '>= 0.0.0'
|
||||||
|
package: xpkg.crossplane.io/crossplane-contrib/provider-family-gcp
|
||||||
|
type: Provider
|
||||||
|
```
|
||||||
|
|
||||||
|
Providers with empty `dependencies: []` change automatically.
|
||||||
|
{{</hint>}}
|
||||||
|
|
||||||
|
### Configuration package dependencies
|
||||||
|
|
||||||
|
When changing providers that are dependencies of Configuration packages, the
|
||||||
|
same conflicts can occur. The Configuration creates provider dependencies based
|
||||||
|
on OCI references, so changing registries creates duplicate providers.
|
||||||
|
|
||||||
|
To change providers in this scenario:
|
||||||
|
1. Update the Configuration's package OCI reference
|
||||||
|
2. Follow the same manual coordination steps for any conflicted providers
|
||||||
|
3. Verify all providers the Configuration depends on are healthy
|
||||||
|
|
||||||
|
### Rollback procedure
|
||||||
|
|
||||||
|
If you need to rollback during the process:
|
||||||
|
|
||||||
|
1. **Before deleting the old provider (step 6)**: Reactivate the old family
|
||||||
|
provider revision:
|
||||||
|
```shell
|
||||||
|
kubectl patch providerrevision upbound-provider-family-gcp-f0aa3640a6a9 --type=merge \
|
||||||
|
-p='{"spec":{"desiredState":"Active"}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then deactivate the new family provider revision and delete the new provider.
|
||||||
|
|
||||||
|
2. **After deleting the old provider**: You must recreate the old provider
|
||||||
|
because Crossplane automatically deletes all revisions when you delete a
|
||||||
|
provider. Create this manifest:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: pkg.crossplane.io/v1
|
||||||
|
kind: Provider
|
||||||
|
metadata:
|
||||||
|
name: upbound-provider-family-gcp
|
||||||
|
spec:
|
||||||
|
package: xpkg.upbound.io/upbound/provider-family-gcp:v1.14.1
|
||||||
|
```
|
||||||
|
|
||||||
|
Save as `rollback-provider.yaml` and apply:
|
||||||
|
```shell
|
||||||
|
kubectl apply -f rollback-provider.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Then follow the process in reverse to switch back.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### New family provider stays unhealthy
|
||||||
|
|
||||||
|
If the new family provider remains `HEALTHY=False` after deactivating the old one:
|
||||||
|
|
||||||
|
1. Check the provider revision status:
|
||||||
|
```shell
|
||||||
|
kubectl get providerrevisions | grep crossplane-contrib-provider-family
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Look for ownership conflict errors in the provider logs:
|
||||||
|
```shell
|
||||||
|
kubectl logs -n crossplane-system -l pkg.crossplane.io/provider=crossplane-contrib-provider-family-gcp
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verify the old revision is truly inactive:
|
||||||
|
```shell
|
||||||
|
kubectl describe providerrevision upbound-provider-family-gcp-f0aa3640a6a9
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ownership conflicts persist
|
||||||
|
|
||||||
|
If you see persistent ownership conflicts:
|
||||||
|
|
||||||
|
```console
|
||||||
|
cannot establish control of object: providerconfigusages.gcp.upbound.io is already controlled by ProviderRevision upbound-provider-family-gcp-f0aa3640a6a9
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- vale Google.WordList = NO -->
|
||||||
|
This means the old revision is still active. Double-check:
|
||||||
|
<!-- vale Google.WordList = YES -->
|
||||||
|
|
||||||
|
1. The old provider has `revisionActivationPolicy: Manual`
|
||||||
|
2. The old revision has `desiredState: Inactive`
|
||||||
|
3. Wait a moment for the change to propagate
|
||||||
|
|
||||||
|
### Provider doesn't deactivate
|
||||||
|
|
||||||
|
If the old provider revision doesn't become inactive:
|
||||||
|
|
||||||
|
<!-- vale Google.WordList = NO -->
|
||||||
|
1. Check for active managed resources preventing deactivation
|
||||||
|
<!-- vale Google.WordList = YES -->
|
||||||
|
2. Verify the patch command succeeded
|
||||||
|
3. Check provider logs for errors:
|
||||||
|
<!-- vale Google.WordList = YES -->
|
||||||
|
```shell
|
||||||
|
kubectl logs -n crossplane-system -l pkg.crossplane.io/provider=upbound-provider-family-gcp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Next steps
|
||||||
|
|
||||||
|
After successfully changing providers:
|
||||||
|
|
||||||
|
* Update any documentation referencing the old provider
|
||||||
|
* Consider changing to v2 namespaced resources if using Crossplane v2
|
||||||
|
* Review other providers for potential registry changes
|
||||||
|
* Share your experience with the Crossplane community
|
||||||
|
|
||||||
|
For more information:
|
||||||
|
* [Provider documentation]({{<ref "../packages/providers">}})
|
||||||
|
* [Troubleshooting guide]({{<ref "troubleshoot-crossplane">}})
|
||||||
|
* [Crossplane community](https://crossplane.io/community/)
|
||||||
|
|
@ -217,6 +217,14 @@ Provider v2 releases support both legacy cluster-scoped and new namespaced
|
||||||
managed resources. Your existing cluster-scoped MRs continue working unchanged.
|
managed resources. Your existing cluster-scoped MRs continue working unchanged.
|
||||||
{{</hint>}}
|
{{</hint>}}
|
||||||
|
|
||||||
|
{{<hint "tip">}}
|
||||||
|
If you're switching from Upbound family providers (like
|
||||||
|
`xpkg.upbound.io/upbound/provider-gcp-compute`) to Crossplane Contrib family
|
||||||
|
providers (like `xpkg.crossplane.io/crossplane-contrib/provider-gcp-compute`),
|
||||||
|
see the [changing provider registries guide]({{<ref "change-provider-registries">}}) for
|
||||||
|
step-by-step instructions to handle family provider dependencies.
|
||||||
|
{{</hint>}}
|
||||||
|
|
||||||
### 5. Start using v2 features
|
### 5. Start using v2 features
|
||||||
|
|
||||||
After upgrading, you can begin using Crossplane v2 features:
|
After upgrading, you can begin using Crossplane v2 features:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue