|  | 
|  | 1 | +--- | 
|  | 2 | +title: Upgrade to Crossplane v2 | 
|  | 3 | +weight: 410 | 
|  | 4 | +description: "Upgrade from Crossplane v1 to v2" | 
|  | 5 | +--- | 
|  | 6 | + | 
|  | 7 | +Crossplane v2 introduces significant improvements while maintaining backward  | 
|  | 8 | +compatibility with most v1 configurations. This guide helps you upgrade from  | 
|  | 9 | +Crossplane v1.x to v2. | 
|  | 10 | + | 
|  | 11 | +Learn about [new features in Crossplane v2]({{<ref "../whats-new">}}) including  | 
|  | 12 | +namespaced resources, the ability to compose any Kubernetes resource, and new  | 
|  | 13 | +operational workflows. | 
|  | 14 | + | 
|  | 15 | +{{<hint "important">}} | 
|  | 16 | +Only upgrade to Crossplane v2 from Crossplane v1.20, the final v1.x release. | 
|  | 17 | +If you're running an earlier version, upgrade to v1.20 first. | 
|  | 18 | +{{</hint>}} | 
|  | 19 | + | 
|  | 20 | +{{<hint "note">}} | 
|  | 21 | +There's no automated tooling yet to migrate existing v1 cluster-scoped XRs and  | 
|  | 22 | +MRs to v2 namespaced style. You can upgrade to Crossplane v2 and  | 
|  | 23 | +start using the new namespaced features right away - your existing v1  | 
|  | 24 | +resources continue working unchanged. See  | 
|  | 25 | +[crossplane/crossplane#6726](https://github.com/crossplane/crossplane/issues/6726)  | 
|  | 26 | +for migration tooling progress. | 
|  | 27 | +{{</hint>}} | 
|  | 28 | + | 
|  | 29 | +## Prerequisites | 
|  | 30 | + | 
|  | 31 | +Before upgrading, ensure: | 
|  | 32 | + | 
|  | 33 | +* You're running Crossplane v1.20 | 
|  | 34 | +* You're not using deprecated features (see [removed features](#removed-features)) | 
|  | 35 | +* All packages use fully qualified image names | 
|  | 36 | +* [Helm](https://helm.sh/docs/intro/install/) version v3.2.0 or later | 
|  | 37 | + | 
|  | 38 | +## Removed features | 
|  | 39 | + | 
|  | 40 | +Crossplane v2 removes these deprecated features: | 
|  | 41 | + | 
|  | 42 | +* [Native patch and transform composition](#native-patch-and-transform-composition) | 
|  | 43 | +* [ControllerConfig type](#controllerconfig-type) | 
|  | 44 | +* [External secret stores](#external-secret-stores) | 
|  | 45 | +* [Default registry flag](#default-registry-flag) | 
|  | 46 | + | 
|  | 47 | +### Native patch and transform composition | 
|  | 48 | +**Deprecated in**: v1.17   | 
|  | 49 | +**Replaced by**: [Composition functions]({{<ref "../composition/compositions">}}) | 
|  | 50 | + | 
|  | 51 | +If you're using `spec.mode: Resources` in your Compositions, migrate to | 
|  | 52 | +composition functions before upgrading. | 
|  | 53 | + | 
|  | 54 | +**Migration help**: use the Crossplane v1.20 CLI to automatically convert your | 
|  | 55 | +Compositions: | 
|  | 56 | + | 
|  | 57 | +```shell | 
|  | 58 | +# Convert patch and transform to function pipelines   | 
|  | 59 | +crossplane beta convert pipeline-composition old-composition.yaml -o new-composition.yaml | 
|  | 60 | +``` | 
|  | 61 | + | 
|  | 62 | +<!-- vale Google.Headings = NO --> | 
|  | 63 | +### ControllerConfig type | 
|  | 64 | +<!-- vale Google.Headings = YES --> | 
|  | 65 | +**Deprecated in**: v1.11   | 
|  | 66 | +**Replaced by**: [DeploymentRuntimeConfig]({{<ref "../packages/providers#runtime-configuration">}}) | 
|  | 67 | + | 
|  | 68 | +Update any ControllerConfig resources to use DeploymentRuntimeConfig instead. | 
|  | 69 | + | 
|  | 70 | +**Migration help**: use the Crossplane v1.20 CLI to automatically convert your | 
|  | 71 | +ControllerConfigs: | 
|  | 72 | + | 
|  | 73 | +```shell | 
|  | 74 | +# Convert ControllerConfig to DeploymentRuntimeConfig | 
|  | 75 | +crossplane beta convert deployment-runtime controller-config.yaml -o deployment-runtime-config.yaml | 
|  | 76 | +``` | 
|  | 77 | + | 
|  | 78 | +### External secret stores | 
|  | 79 | +**Status**: alpha feature, unmaintained | 
|  | 80 | + | 
|  | 81 | +If you're using external secret stores, migrate to native Kubernetes secrets  | 
|  | 82 | +or [External Secrets Operator](https://external-secrets.io/latest/) before upgrading. | 
|  | 83 | + | 
|  | 84 | +### Default registry flag | 
|  | 85 | +**Removed**: `--registry` flag for default package registry | 
|  | 86 | + | 
|  | 87 | +All packages must now use fully qualified names including the registry  | 
|  | 88 | +host name. Check your packages with: | 
|  | 89 | + | 
|  | 90 | +```shell | 
|  | 91 | +kubectl get pkg -o wide | 
|  | 92 | +``` | 
|  | 93 | + | 
|  | 94 | +Update any packages without registry host names before upgrading. For example: | 
|  | 95 | +- ❌ `crossplane-contrib/provider-aws-s3:v1.23.0`  | 
|  | 96 | +- ✅ `xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v1.23.0` | 
|  | 97 | + | 
|  | 98 | +## Who can upgrade | 
|  | 99 | + | 
|  | 100 | +You can upgrade to Crossplane v2 if you meet these criteria: | 
|  | 101 | + | 
|  | 102 | +* ✅ Running Crossplane v1.20 | 
|  | 103 | +* ✅ Not using native patch and transform composition | 
|  | 104 | +* ✅ Not using ControllerConfig resources | 
|  | 105 | +* ✅ Not using external secret stores | 
|  | 106 | +* ✅ All packages use fully qualified image names | 
|  | 107 | + | 
|  | 108 | +If you're using any removed features, migrate away from them first. | 
|  | 109 | + | 
|  | 110 | +## Upgrade approach | 
|  | 111 | + | 
|  | 112 | +The recommended upgrade approach: | 
|  | 113 | + | 
|  | 114 | +1. [Prepare for upgrade](#1-prepare-for-upgrade) | 
|  | 115 | +2. [Upgrade Crossplane core](#2-upgrade-crossplane-core)   | 
|  | 116 | +3. [Configure managed resource activation policies](#3-configure-managed-resource-activation-policies) | 
|  | 117 | +4. [Upgrade providers](#4-upgrade-providers) | 
|  | 118 | +5. [Start using v2 features](#5-start-using-v2-features) | 
|  | 119 | + | 
|  | 120 | +### 1. Prepare for upgrade | 
|  | 121 | + | 
|  | 122 | +Review your cluster for [removed features](#removed-features) and address any | 
|  | 123 | +that you're using. Each removed feature section includes commands to inspect | 
|  | 124 | +your cluster and migration tools to help convert resources. | 
|  | 125 | + | 
|  | 126 | +### 2. Upgrade Crossplane core | 
|  | 127 | + | 
|  | 128 | +Add the Crossplane Helm repository: | 
|  | 129 | + | 
|  | 130 | +```shell | 
|  | 131 | +helm repo add crossplane-stable https://charts.crossplane.io/stable | 
|  | 132 | +helm repo update | 
|  | 133 | +``` | 
|  | 134 | + | 
|  | 135 | +Upgrade to Crossplane v2: | 
|  | 136 | + | 
|  | 137 | +```shell | 
|  | 138 | +helm upgrade crossplane \ | 
|  | 139 | +  --namespace crossplane-system \ | 
|  | 140 | +  crossplane-stable/crossplane | 
|  | 141 | +``` | 
|  | 142 | + | 
|  | 143 | +Verify the upgrade: | 
|  | 144 | + | 
|  | 145 | +```shell | 
|  | 146 | +kubectl get pods -n crossplane-system | 
|  | 147 | +``` | 
|  | 148 | + | 
|  | 149 | +### 3. Configure managed resource activation policies | 
|  | 150 | + | 
|  | 151 | +Crossplane v2 automatically creates a default [MRAP]({{<ref "../managed-resources/managed-resource-activation-policies">}}) that activates all managed  | 
|  | 152 | +resources (`*`). Before installing v2 providers, you can optionally customize | 
|  | 153 | +this for better cluster resource efficiency. | 
|  | 154 | + | 
|  | 155 | +Check what managed resources you use: | 
|  | 156 | + | 
|  | 157 | +```shell | 
|  | 158 | +# See your managed resource types | 
|  | 159 | +kubectl get managed | 
|  | 160 | +``` | 
|  | 161 | + | 
|  | 162 | +Optionally, replace the default MRAP with a targeted one that activates only  | 
|  | 163 | +the resources you need: | 
|  | 164 | + | 
|  | 165 | +```shell | 
|  | 166 | +# Delete the default catch-all MRAP | 
|  | 167 | +kubectl delete mrap default | 
|  | 168 | +``` | 
|  | 169 | + | 
|  | 170 | +Create a targeted MRAP: | 
|  | 171 | + | 
|  | 172 | +```yaml | 
|  | 173 | +apiVersion: apiextensions.crossplane.io/v1alpha1 | 
|  | 174 | +kind: ManagedResourceActivationPolicy | 
|  | 175 | +metadata: | 
|  | 176 | +  name: my-resources | 
|  | 177 | +spec: | 
|  | 178 | +  activate: | 
|  | 179 | +  # Legacy cluster-scoped resources (existing v1 resources) | 
|  | 180 | +  - buckets.s3.aws.upbound.io | 
|  | 181 | +  - instances.ec2.aws.upbound.io | 
|  | 182 | +   | 
|  | 183 | +  # Modern namespaced resources (new v2 resources)   | 
|  | 184 | +  - buckets.s3.aws.m.upbound.io | 
|  | 185 | +  - instances.ec2.aws.m.upbound.io | 
|  | 186 | +``` | 
|  | 187 | +
 | 
|  | 188 | +{{<hint "tip">}} | 
|  | 189 | +Notice the distinction: `s3.aws.upbound.io` (legacy cluster-scoped) vs  | 
|  | 190 | +`s3.aws.m.upbound.io` (v2 namespaced). The `.m.` indicates modern  | 
|  | 191 | +namespaced managed resources. | 
|  | 192 | +{{</hint>}} | 
|  | 193 | + | 
|  | 194 | +### 4. Upgrade providers | 
|  | 195 | + | 
|  | 196 | +Upgrade your providers to versions that support both namespaced and  | 
|  | 197 | +cluster-scoped managed resources: | 
|  | 198 | + | 
|  | 199 | +```shell | 
|  | 200 | +# Check current provider versions | 
|  | 201 | +kubectl get providers | 
|  | 202 | +``` | 
|  | 203 | + | 
|  | 204 | +Update your provider manifests to use v2 versions: | 
|  | 205 | + | 
|  | 206 | +```yaml | 
|  | 207 | +apiVersion: pkg.crossplane.io/v1 | 
|  | 208 | +kind: Provider | 
|  | 209 | +metadata: | 
|  | 210 | +  name: crossplane-contrib-provider-aws-s3 | 
|  | 211 | +spec: | 
|  | 212 | +  package: xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v2.0.0 | 
|  | 213 | +``` | 
|  | 214 | + | 
|  | 215 | +{{<hint "note">}} | 
|  | 216 | +Provider v2 releases support both legacy cluster-scoped and new namespaced | 
|  | 217 | +managed resources. Your existing cluster-scoped MRs continue working unchanged. | 
|  | 218 | +{{</hint>}} | 
|  | 219 | + | 
|  | 220 | +### 5. Start using v2 features | 
|  | 221 | + | 
|  | 222 | +After upgrading, you can begin using Crossplane v2 features: | 
|  | 223 | + | 
|  | 224 | +- **Namespaced managed resources**: Try the [managed resources getting started guide]({{<ref "../get-started/get-started-with-managed-resources">}}) | 
|  | 225 | +- **Composition functions**: Follow the [composition getting started guide]({{<ref "../get-started/get-started-with-composition">}}) | 
|  | 226 | +- **Operations**: Explore the [operations getting started guide]({{<ref "../get-started/get-started-with-operations">}}) | 
|  | 227 | +- **Managed resource definitions**: See the [MRDs guide]({{<ref "./disabling-unused-managed-resources">}}) | 
|  | 228 | + | 
|  | 229 | +## Updating compositions for v2 | 
|  | 230 | + | 
|  | 231 | +Existing Compositions work with Crossplane v2 with minimal changes. v2 managed | 
|  | 232 | +resources are schematically identical to v1 managed resources - they're just | 
|  | 233 | +namespaced. | 
|  | 234 | + | 
|  | 235 | +To use v2 namespaced managed resources in compositions: | 
|  | 236 | + | 
|  | 237 | +1. **Update the API group** from `.crossplane.io` to `.m.crossplane.io` | 
|  | 238 | +2. **Check the API version** - v2 namespaced providers often reset the API | 
|  | 239 | +   version to `v1beta1` | 
|  | 240 | + | 
|  | 241 | +For example `provider-aws-s3:v2.0.0` has two `Bucket` MRs: | 
|  | 242 | + | 
|  | 243 | +* `apiVersion: s3.aws.upbound.io/v1beta2` - Legacy, cluster scoped | 
|  | 244 | +* `apiVersion: s3.aws.m.upbound.io/v1beta1` - Namespaced | 
|  | 245 | + | 
|  | 246 | +The `spec.forProvider` and `status.atProvider` fields are schematically | 
|  | 247 | +identical. | 
|  | 248 | + | 
|  | 249 | +{{<hint "tip">}} | 
|  | 250 | +Use `kubectl get mrds` to see available MR API versions. | 
|  | 251 | +{{</hint>}} | 
|  | 252 | + | 
|  | 253 | +{{<hint "note">}} | 
|  | 254 | +Not all providers use `.crossplane.io` domains. For example, `provider-aws-s3` | 
|  | 255 | +uses `.upbound.io` domains for historical reasons. The general pattern for | 
|  | 256 | +namespaced resources is adding `.m` to the existing domain: `<domain>` becomes | 
|  | 257 | +`m.<domain>` (like `upbound.io` → `m.upbound.io` or `crossplane.io` → | 
|  | 258 | +`m.crossplane.io`). | 
|  | 259 | +{{</hint>}} | 
|  | 260 | + | 
|  | 261 | +**Before (v1 cluster-scoped)**: | 
|  | 262 | +```yaml | 
|  | 263 | +apiVersion: apiextensions.crossplane.io/v1 | 
|  | 264 | +kind: Composition | 
|  | 265 | +metadata: | 
|  | 266 | +  name: my-app | 
|  | 267 | +spec: | 
|  | 268 | +  compositeTypeRef: | 
|  | 269 | +    apiVersion: example.crossplane.io/v1 | 
|  | 270 | +    kind: XBucket | 
|  | 271 | +  mode: Pipeline | 
|  | 272 | +  pipeline: | 
|  | 273 | +  - step: create-bucket | 
|  | 274 | +    functionRef: | 
|  | 275 | +      name: crossplane-contrib-function-go-templating | 
|  | 276 | +    input: | 
|  | 277 | +      apiVersion: gotemplating.fn.crossplane.io/v1beta1 | 
|  | 278 | +      kind: GoTemplate | 
|  | 279 | +      source: Inline | 
|  | 280 | +      inline: | 
|  | 281 | +        template: | | 
|  | 282 | +          apiVersion: s3.aws.upbound.io/v1beta2 | 
|  | 283 | +          kind: Bucket | 
|  | 284 | +          metadata: | 
|  | 285 | +            name: {{ .observed.composite.resource.metadata.name }} | 
|  | 286 | +          spec: | 
|  | 287 | +            forProvider: | 
|  | 288 | +              region: us-east-2 | 
|  | 289 | +``` | 
|  | 290 | + | 
|  | 291 | +**After (v2 namespaced)**: | 
|  | 292 | +```yaml | 
|  | 293 | +apiVersion: apiextensions.crossplane.io/v1 | 
|  | 294 | +kind: Composition | 
|  | 295 | +metadata: | 
|  | 296 | +  name: my-app | 
|  | 297 | +spec: | 
|  | 298 | +  compositeTypeRef: | 
|  | 299 | +    apiVersion: example.crossplane.io/v1 | 
|  | 300 | +    kind: Bucket | 
|  | 301 | +  mode: Pipeline | 
|  | 302 | +  pipeline: | 
|  | 303 | +  - step: create-bucket | 
|  | 304 | +    functionRef: | 
|  | 305 | +      name: crossplane-contrib-function-go-templating | 
|  | 306 | +    input: | 
|  | 307 | +      apiVersion: gotemplating.fn.crossplane.io/v1beta1 | 
|  | 308 | +      kind: GoTemplate | 
|  | 309 | +      source: Inline | 
|  | 310 | +      inline: | 
|  | 311 | +        template: | | 
|  | 312 | +          apiVersion: s3.aws.m.upbound.io/v1beta1  # Added .m, reset to v1beta1 | 
|  | 313 | +          kind: Bucket | 
|  | 314 | +          metadata: | 
|  | 315 | +            name: {{ .observed.composite.resource.metadata.name }} | 
|  | 316 | +          spec: | 
|  | 317 | +            forProvider: | 
|  | 318 | +              region: us-east-2 | 
|  | 319 | +``` | 
|  | 320 | + | 
|  | 321 | +{{<hint "tip">}} | 
|  | 322 | +**Namespace handling in compositions**: | 
|  | 323 | +- **Namespaced XRs**: Don't specify `metadata.namespace` in templates. | 
|  | 324 | +  Crossplane ignores template namespaces and uses the XR's namespace. | 
|  | 325 | +- **Modern cluster-scoped XRs** (`scope: Cluster`): Can compose resources in any | 
|  | 326 | +  namespace. Include `metadata.namespace` in templates to specify the target | 
|  | 327 | +  namespace. | 
|  | 328 | +- **Legacy cluster-scoped XRs** (`scope: LegacyCluster`): Can't compose | 
|  | 329 | +  namespaced resources. | 
|  | 330 | +{{</hint>}} | 
|  | 331 | + | 
|  | 332 | +## Legacy resource behavior | 
|  | 333 | + | 
|  | 334 | +Your existing v1 resources continue working in Crossplane v2: | 
|  | 335 | + | 
|  | 336 | +* **Legacy cluster-scoped XRs**: Continue working with claims support | 
|  | 337 | +* **Legacy cluster-scoped MRs**: Continue working unchanged | 
|  | 338 | +* **Existing Compositions**: Continue working with legacy XRs | 
|  | 339 | + | 
|  | 340 | +These resources use `LegacyCluster` scope internally and maintain full  | 
|  | 341 | +backward compatibility. | 
|  | 342 | + | 
|  | 343 | +For example, existing v1-style XRDs continue working with claims: | 
|  | 344 | + | 
|  | 345 | +```yaml | 
|  | 346 | +apiVersion: apiextensions.crossplane.io/v1 | 
|  | 347 | +kind: CompositeResourceDefinition | 
|  | 348 | +metadata: | 
|  | 349 | +  name: xdatabases.example.crossplane.io | 
|  | 350 | +spec: | 
|  | 351 | +  # v1 XRDs default to LegacyCluster scope (shown explicitly) | 
|  | 352 | +  scope: LegacyCluster | 
|  | 353 | +  group: example.crossplane.io | 
|  | 354 | +  names: | 
|  | 355 | +    kind: XDatabase | 
|  | 356 | +    plural: xdatabases | 
|  | 357 | +  claimNames: | 
|  | 358 | +    kind: Database | 
|  | 359 | +    plural: databases | 
|  | 360 | +  # schema definition... | 
|  | 361 | +``` | 
|  | 362 | + | 
|  | 363 | +Users can create claims that work as before: | 
|  | 364 | + | 
|  | 365 | +```yaml | 
|  | 366 | +apiVersion: example.crossplane.io/v1 | 
|  | 367 | +kind: Database | 
|  | 368 | +metadata: | 
|  | 369 | +  name: my-database | 
|  | 370 | +  namespace: production | 
|  | 371 | +spec: | 
|  | 372 | +  engine: postgres | 
|  | 373 | +  size: large | 
|  | 374 | +``` | 
|  | 375 | + | 
|  | 376 | + | 
|  | 377 | +## Next steps | 
|  | 378 | + | 
|  | 379 | +After upgrading: | 
|  | 380 | + | 
|  | 381 | +1. **Explore namespaced resources**: Try creating XRs and MRs in namespaces | 
|  | 382 | +2. **Build app compositions**: Use v2's ability to compose any Kubernetes resource | 
|  | 383 | +3. **Try Operations**: Experiment with operational workflows | 
|  | 384 | +4. **Plan migration**: Consider which existing resources to migrate to v2 patterns | 
|  | 385 | + | 
|  | 386 | +Read more about [what's new in v2]({{<ref "../whats-new">}}) and explore the  | 
|  | 387 | +updated [composition documentation]({{<ref "../composition/compositions">}}). | 
0 commit comments