From 3fcc4473a90fce573d9cb3fa18ebd23dae7a24c6 Mon Sep 17 00:00:00 2001 From: Scott Nichols Date: Thu, 7 Aug 2025 11:25:54 -0700 Subject: [PATCH] first draft of MRD documentation based on the spec and PRs related to MRD/MRAP/SafeStart Signed-off-by: Scott Nichols --- .../get-started/get-started-with-mrds.md | 530 +++++++++++++ .../master/guides/implementing-safestart.md | 714 ++++++++++++++++++ .../master/guides/mrd-activation-policies.md | 691 +++++++++++++++++ .../managed-resource-definitions.md | 237 ++++++ .../master/packages/provider-capabilities.md | 372 +++++++++ content/master/whats-new/_index.md | 60 +- .../styles/Crossplane/crossplane-words.txt | 10 + .../styles/Crossplane/spelling-exceptions.txt | 21 + 8 files changed, 2633 insertions(+), 2 deletions(-) create mode 100644 content/master/get-started/get-started-with-mrds.md create mode 100644 content/master/guides/implementing-safestart.md create mode 100644 content/master/guides/mrd-activation-policies.md create mode 100644 content/master/managed-resources/managed-resource-definitions.md create mode 100644 content/master/packages/provider-capabilities.md diff --git a/content/master/get-started/get-started-with-mrds.md b/content/master/get-started/get-started-with-mrds.md new file mode 100644 index 00000000..7a7f4ef1 --- /dev/null +++ b/content/master/get-started/get-started-with-mrds.md @@ -0,0 +1,530 @@ +--- +title: Get Started with Managed Resource Definitions +weight: 220 +description: Learn how to use MRDs and activation policies to optimize your Crossplane installation +--- + +This guide shows how to use Managed Resource Definitions (MRDs) and activation +policies to control which managed resources are available in your cluster. +You install a provider, examine its MRDs, and use policies to activate only +the resources you need. + +{{< hint "tip" >}} +This guide demonstrates the performance and discovery benefits of MRDs by +working with a subset of AWS resources rather than installing hundreds of CRDs. +{{< /hint >}} + +By the end of this guide, you understand how to: +* Examine MRDs created by provider packages +* Use activation policies to control resource availability +* Discover connection details through MRD schemas +* Optimize cluster performance by activating only needed resources + +## Prerequisites + +This guide requires: + +* A Kubernetes cluster with at least 2 GB of RAM +* Crossplane v2.0+ [installed on the cluster]({{< ref "install" >}}) +* `kubectl` configured to access your cluster + +## Understand the default activation policy + +Before installing providers, it's important to understand Crossplane's default +activation behavior. Crossplane creates a default ManagedResourceActivationPolicy +that, by default, activates **all** managed resources with a `"*"` pattern. + +{{< hint "important" >}} +The default `"*"` activation pattern defeats the performance benefits of +SafeStart by activating all resources. For this tutorial, we work with the +default behavior, but production setups should use more selective activation. +{{< /hint >}} + +Check if you have a default activation policy: + +```shell +kubectl get mrap crossplane-default-activation-policy -o yaml +``` + +You can modify the default activation policy directly: + +{{< tabs >}} +{{< tab "Edit Existing Policy" >}} +```shell +# Permanently disable by using a non-matching pattern +kubectl patch mrap crossplane-default-activation-policy --type='merge' \ + -p='{"spec":{"activations":["nonexistent.example.com"]}}' + +# Or remove all activations entirely +kubectl patch mrap crossplane-default-activation-policy --type='merge' \ + -p='{"spec":{"activations":[]}}' +``` + +{{< hint "note" >}} +Changes to the default policy are permanent. After the policy exists, Crossplane +won't modify it, even if you change Helm values. +{{< /hint >}} +{{< /tab >}} + +{{< tab "Reset with Helm Values" >}} +```shell +# Delete the default policy and restart Crossplane to recreate from Helm values +kubectl delete mrap crossplane-default-activation-policy +helm upgrade crossplane crossplane-stable/crossplane \ + --set provider.defaultActivations=null \ + --namespace crossplane-system --reuse-values +kubectl rollout restart deployment/crossplane -n crossplane-system +``` + +This approach lets you use Helm chart values to control the default policy. +{{< /tab >}} +{{< /tabs >}} + +{{< hint "tip" >}} +Learn more about configuring default activation policies during installation +and best practices in the [MRD activation policies guide]({{< ref "../guides/mrd-activation-policies#default-activation-policy" >}}). +{{< /hint >}} + +## Install a SafeStart provider + +Now install a provider that supports SafeStart. This provider creates MRDs +that activation policies control. + +```yaml +apiVersion: pkg.crossplane.io/v1 +kind: Provider +metadata: + name: provider-aws +spec: + package: xpkg.upbound.io/crossplane-contrib/provider-aws:v0.45.0 +``` + +Apply this configuration: + +```shell +kubectl apply -f - <}} +{{< tab "With Default Activation (default)" >}} +If you kept the default `"*"` activation pattern: + +```shell +NAME STATE AGE +buckets.s3.aws.crossplane.io Active 2m +instances.ec2.aws.crossplane.io Active 2m +databases.rds.aws.crossplane.io Active 2m +clusters.eks.aws.crossplane.io Active 2m +# ... many more, all Active +``` + +The default policy activates all MRDs, so SafeStart providers behave like +traditional providers. +{{< /tab >}} + +{{< tab "With Disabled Default Activation" >}} +If you disabled default activation: + +```shell +NAME STATE AGE +buckets.s3.aws.crossplane.io Inactive 2m +instances.ec2.aws.crossplane.io Inactive 2m +databases.rds.aws.crossplane.io Inactive 2m +clusters.eks.aws.crossplane.io Inactive 2m +# ... many more, all Inactive +``` + +This demonstrates true SafeStart behavior where resources must be explicitly +activated. +{{< /tab >}} +{{< /tabs >}} + +{{< hint "note" >}} +For the rest of this tutorial, we assume you have default activation +disabled to demonstrate selective activation. If you have default activation +enabled, the MRDs are already active. +{{< /hint >}} + +Examine a specific MRD to understand its schema and connection details: + +```shell +kubectl get mrd instances.ec2.aws.crossplane.io -o yaml +``` + +Look for the `connectionDetails` section: + +```yaml +spec: + connectionDetails: + - description: The public IP address assigned to the instance + name: public_ip + type: string + - description: The private IP address assigned to the instance + name: private_ip + type: string + - description: The public DNS name assigned to the instance + name: public_dns + type: string +``` + +## Verify CRD creation behavior + +The presence of CRDs depends on whether MRDs are active: + +{{< tabs >}} +{{< tab "With Default Activation (default)" >}} +Because MRDs are active due to the default `"*"` policy, CRDs exist: + +```shell +kubectl get crds | grep aws.crossplane.io | wc -l +``` + +This shows many CRDs (100+), demonstrating that active MRDs +create CRDs immediately. +{{< /tab >}} + +{{< tab "With Disabled Default Activation" >}} +Because the MRDs are inactive, no CRDs should exist for AWS resources: + +```shell +kubectl get crds | grep aws.crossplane.io +``` + +This should return no results, demonstrating that inactive MRDs don't create +CRDs in your cluster. +{{< /tab >}} +{{< /tabs >}} + +## Create an activation policy + +Create a ManagedResourceActivationPolicy to activate specific AWS resources: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: aws-demo-resources +spec: + activations: + - instances.ec2.aws.crossplane.io + - buckets.s3.aws.crossplane.io + - "*.rds.aws.crossplane.io" +``` + +Apply the policy: + +```shell +kubectl apply -f - <}} +This example assumes you have AWS credentials configured. See the +[AWS Provider documentation]({{< ref "../guides/aws-provider" >}}) for +authentication setup. +{{< /hint >}} + +```shell +kubectl apply -f - <}}) - Comprehensive guide including default policy configuration +* [Managed Resource Definitions concepts]({{< ref "managed-resource-definitions" >}}) +* [Provider capabilities and SafeStart]({{< ref "../packages/provider-capabilities" >}}) \ No newline at end of file diff --git a/content/master/guides/implementing-safestart.md b/content/master/guides/implementing-safestart.md new file mode 100644 index 00000000..c28e3606 --- /dev/null +++ b/content/master/guides/implementing-safestart.md @@ -0,0 +1,714 @@ +--- +title: Implementing SafeStart in Providers +weight: 160 +description: Guide for provider developers to implement SafeStart capability +--- + +This guide shows provider developers how to implement SafeStart capability in +their Crossplane providers. SafeStart enables selective resource activation +through Managed Resource Definitions (MRDs), improving performance and resource +management. + +{{< hint "important" >}} +SafeStart requires Crossplane v2.0+ and involves significant provider changes. +Plan for breaking changes and thorough testing before implementing. +{{< /hint >}} + +## What SafeStart provides + +SafeStart transforms how your provider handles resource installation: + +**Without SafeStart:** +- All managed resources become CRDs immediately when provider installs +- Users get all ~200 AWS resources even if they need only 5 +- Higher memory usage and slower API server responses + +**With SafeStart:** +- All managed resources become inactive MRDs when provider installs +- Users activate only needed resources through policies +- Lower resource overhead and better performance + +## Prerequisites + +Before implementing SafeStart, ensure you have: + +* Provider built with Crossplane v2.0+ runtime +* Understanding of [MRDs and activation policies]({{< ref "mrd-activation-policies" >}}) +* Test environment with Crossplane v2.0+ +* CI/CD pipeline that can build and test provider changes + +## Implementation steps + +### Step 1: Update provider metadata + +Declare SafeStart capability in your provider package metadata: + +```yaml +apiVersion: meta.pkg.crossplane.io/v1 +kind: Provider +metadata: + name: provider-example +spec: + package: registry.example.com/provider-example:v1.0.0 + capabilities: + - name: SafeStart +``` + +{{< hint "tip" >}} +Crossplane supports flexible capability matching. `SafeStart`, `safestart`, +and `safe-start` are all recognized as the same capability. +{{< /hint >}} + +### Step 2: Enhance MRD generation + +Update your MRD generation to include connection details documentation: + +{{< tabs >}} +{{< tab "Go Controller Runtime" >}} +```go +// In your MRD generation code +type ManagedResourceDefinition struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ManagedResourceDefinitionSpec `json:"spec"` + Status ManagedResourceDefinitionStatus `json:"status,omitempty"` +} + +type ManagedResourceDefinitionSpec struct { + // Standard CRD fields + Group string `json:"group"` + Names Names `json:"names"` + Scope string `json:"scope"` + + // SafeStart-specific fields + ConnectionDetails []ConnectionDetail `json:"connectionDetails,omitempty"` + State ResourceState `json:"state,omitempty"` +} + +type ConnectionDetail struct { + Name string `json:"name"` + Description string `json:"description"` + Type string `json:"type"` + FromConnectionSecretKey string `json:"fromConnectionSecretKey,omitempty"` +} +``` +{{< /tab >}} + +{{< tab "Terrajet/Upjet Provider" >}} +```go +// In your provider configuration +func GetProvider() *ujconfig.Provider { + pc := ujconfig.NewProvider([]byte(providerSchema), resourcePrefix, modulePath, + ujconfig.WithIncludeList(ExternalNameConfigured()), + ujconfig.WithDefaultResourceOptions( + ExternalNameConfigurations(), + SafeStartConfiguration(), // Add SafeStart config + )) + + // Configure SafeStart for specific resources + for _, configure := range []func(provider *ujconfig.Provider){ + configureConnectionDetails, + configureMRDDocumentation, + } { + configure(pc) + } + + return pc +} + +func configureConnectionDetails(p *ujconfig.Provider) { + // Example: RDS Instance connection details + p.AddResourceConfigurator("aws_db_instance", func(r *ujconfig.Resource) { + r.ConnectionDetails = map[string]ujconfig.ConnectionDetail{ + "endpoint": { + Description: "The RDS instance endpoint", + Type: "string", + FromConnectionSecretKey: "endpoint", + }, + "port": { + Description: "The port on which the DB accepts connections", + Type: "integer", + FromConnectionSecretKey: "port", + }, + "username": { + Description: "The master username for the database", + Type: "string", + FromConnectionSecretKey: "username", + }, + "password": { + Description: "The master password for the database", + Type: "string", + FromConnectionSecretKey: "password", + }, + } + }) +} +``` +{{< /tab >}} +{{< /tabs >}} + +### Step 3: Handle namespaced resources + +SafeStart works best with namespaced managed resources. Update your resources +to support both cluster and namespaced scopes: + +```go +// Update resource definitions to support namespacing +type Database struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec DatabaseSpec `json:"spec"` + Status DatabaseStatus `json:"status,omitempty"` +} + +// Update your CRD generation +//+kubebuilder:resource:scope=Namespaced +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +type Database struct { + // ... resource definition +} + +// Optionally create cluster-scoped variants +//+kubebuilder:resource:scope=Cluster +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +type ClusterDatabase struct { + // ... same spec but cluster scoped +} +``` + +### Step 4: Update RBAC permissions + +SafeStart providers need additional permissions to manage CRDs dynamically: + +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: provider-example-system +rules: +# Existing provider permissions +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "update", "patch"] +- apiGroups: ["example.crossplane.io"] + resources: ["*"] + verbs: ["*"] + +# Additional SafeStart permissions +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["apiextensions.crossplane.io"] + resources: ["managedresourcedefinitions"] + verbs: ["get", "list", "watch", "update", "patch"] +``` + +### Step 5: Implement MRD controller logic + +Add controller logic to handle MRD activation and CRD lifecycle: + +```go +package controller + +import ( + "context" + + apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + xpv1alpha1 "github.com/crossplane/crossplane/apis/apiextensions/v1alpha1" +) + +// MRDReconciler handles MRD activation +type MRDReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +func (r *MRDReconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { + mrd := &xpv1alpha1.ManagedResourceDefinition{} + if err := r.Get(ctx, req.NamespacedName, mrd); err != nil { + return reconcile.Result{}, client.IgnoreNotFound(err) + } + + // Check if MRD should be active + if mrd.Spec.State != nil && *mrd.Spec.State == xpv1alpha1.ResourceStateActive { + return r.ensureCRDExists(ctx, mrd) + } + + // If inactive, ensure CRD is removed + return r.ensureCRDRemoved(ctx, mrd) +} + +func (r *MRDReconciler) ensureCRDExists(ctx context.Context, mrd *xpv1alpha1.ManagedResourceDefinition) (reconcile.Result, error) { + crd := &apiextv1.CustomResourceDefinition{} + crdName := mrd.Spec.Names.Plural + "." + mrd.Spec.Group + + err := r.Get(ctx, types.NamespacedName{Name: crdName}, crd) + if client.IgnoreNotFound(err) != nil { + return reconcile.Result{}, err + } + + if err != nil { // CRD doesn't exist + return r.createCRD(ctx, mrd) + } + + // CRD exists, ensure it's up to date + return r.updateCRD(ctx, mrd, crd) +} + +func (r *MRDReconciler) createCRD(ctx context.Context, mrd *xpv1alpha1.ManagedResourceDefinition) (reconcile.Result, error) { + crd := &apiextv1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: mrd.Spec.Names.Plural + "." + mrd.Spec.Group, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: mrd.APIVersion, + Kind: mrd.Kind, + Name: mrd.Name, + UID: mrd.UID, + Controller: pointer.Bool(true), + }}, + }, + Spec: mrd.Spec.CustomResourceDefinitionSpec, + } + + return reconcile.Result{}, r.Create(ctx, crd) +} +``` + +### Step 6: Update build and CI processes + +Update your build process to generate MRDs alongside CRDs: + +{{< tabs >}} +{{< tab "Makefile" >}} +```makefile +# Update your Makefile to generate both CRDs and MRDs +.PHONY: generate +generate: controller-gen + $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." + $(CONTROLLER_GEN) crd:allowDangerousTypes=true paths="./..." output:crd:artifacts:config=package/crds + $(CONTROLLER_GEN) mrd:allowDangerousTypes=true paths="./..." output:mrd:artifacts:config=package/mrds + +# Add MRD generation tool +MRD_GEN = $(shell pwd)/bin/mrd-gen +.PHONY: mrd-gen +mrd-gen: ## Download mrd-gen locally if necessary. + $(call go-get-tool,$(MRD_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.13.0) + +# Update package generation to include MRDs +.PHONY: build-package +build-package: generate + mkdir -p package/ + cp package/crds/*.yaml package/ + cp package/mrds/*.yaml package/ + echo "# Package metadata with SafeStart capability" > package/provider.yaml + echo "apiVersion: meta.pkg.crossplane.io/v1" >> package/provider.yaml + echo "kind: Provider" >> package/provider.yaml + echo "spec:" >> package/provider.yaml + echo " capabilities:" >> package/provider.yaml + echo " - name: SafeStart" >> package/provider.yaml +``` +{{< /tab >}} + +{{< tab "GitHub Actions" >}} +```yaml +name: Build and Test SafeStart Provider + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + test-safestart: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v4 + with: + go-version: '1.21' + + - name: Run Tests + run: make test + + - name: Generate MRDs + run: make generate + + - name: Verify MRD Generation + run: | + if [ ! -d "package/mrds" ]; then + echo "MRD generation failed" + exit 1 + fi + echo "Generated MRDs:" + ls -la package/mrds/ + + - name: Test SafeStart Integration + run: | + # Start local cluster + make kind-up + make install-crossplane-v2 + + # Install provider with SafeStart + make install-provider + + # Verify MRDs created but inactive + kubectl get mrds + kubectl get mrds -o jsonpath='{.items[*].spec.state}' | grep -q "Inactive" + + # Test activation policy + kubectl apply -f examples/activation-policy.yaml + + # Verify resources activate + sleep 30 + kubectl get mrds -o jsonpath='{.items[*].spec.state}' | grep -q "Active" + + # Test resource creation + kubectl apply -f examples/example-resource.yaml + kubectl wait --for=condition=Ready --timeout=300s -f examples/example-resource.yaml +``` +{{< /tab >}} +{{< /tabs >}} + +### Step 7: Add connection details documentation + +Document connection details in your MRDs to help users understand resource +capabilities: + +```yaml +# Example generated MRD with connection details +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceDefinition +metadata: + name: databases.rds.aws.example.io +spec: + group: rds.aws.example.io + names: + kind: Database + plural: databases + scope: Namespaced + + # SafeStart-specific fields + connectionDetails: + - name: endpoint + description: "The RDS instance connection endpoint" + type: string + fromConnectionSecretKey: endpoint + - name: port + description: "The port number for database connections" + type: integer + fromConnectionSecretKey: port + - name: username + description: "The master username for the database" + type: string + fromConnectionSecretKey: username + - name: password + description: "The master password for the database" + type: string + fromConnectionSecretKey: password + - name: ca_certificate + description: "The CA certificate for SSL connections" + type: string + fromConnectionSecretKey: ca_certificate + + # Standard CRD specification + versions: + - name: v1alpha1 + served: true + storage: true + # ... rest of CRD spec +``` + +## Testing SafeStart implementation + +### Unit testing + +Test your MRD generation and controller logic: + +```go +func TestMRDGeneration(t *testing.T) { + // Test that MRDs are generated with correct connection details + mrd := generateMRDForResource("Database") + + assert.Equal(t, "databases.rds.aws.example.io", mrd.Name) + assert.NotEmpty(t, mrd.Spec.ConnectionDetails) + + // Verify specific connection details + endpointDetail := findConnectionDetail(mrd, "endpoint") + assert.NotNil(t, endpointDetail) + assert.Equal(t, "string", endpointDetail.Type) + assert.Contains(t, endpointDetail.Description, "endpoint") +} + +func TestMRDActivation(t *testing.T) { + // Test MRD activation creates CRD + ctx := context.Background() + mrd := &v1alpha1.ManagedResourceDefinition{ + Spec: v1alpha1.ManagedResourceDefinitionSpec{ + State: &[]v1alpha1.ResourceState{v1alpha1.ResourceStateActive}[0], + }, + } + + reconciler := &MRDReconciler{Client: fakeClient} + result, err := reconciler.Reconcile(ctx, reconcile.Request{}) + + assert.NoError(t, err) + assert.False(t, result.Requeue) + + // Verify CRD was created + crd := &apiextv1.CustomResourceDefinition{} + err = fakeClient.Get(ctx, types.NamespacedName{Name: "databases.rds.aws.example.io"}, crd) + assert.NoError(t, err) +} +``` + +### Integration testing + +Test SafeStart behavior in a real cluster: + +```bash +#!/bin/bash +set -e + +echo "Starting SafeStart integration test..." + +# Install Crossplane v2.0 +kubectl create namespace crossplane-system +helm install crossplane crossplane-stable/crossplane \ + --namespace crossplane-system \ + --version v2.0.0 \ + --wait + +# Install provider with SafeStart +kubectl apply -f - <20 resources +- Document recommended activation patterns for common use cases +- Provide environment-specific activation policy examples + +### User experience +- Include helpful error messages when resources aren't activated +- Provide clear migration guides for existing users +- Document connection details thoroughly + +### Testing strategy +- Test both with and without SafeStart in CI +- Verify activation/deactivation cycles work correctly +- Test resource creation after activation + +SafeStart provides significant value for large providers and improves the +overall Crossplane user experience. Following this guide helps ensure your +implementation is robust, well-documented, and user-friendly. \ No newline at end of file diff --git a/content/master/guides/mrd-activation-policies.md b/content/master/guides/mrd-activation-policies.md new file mode 100644 index 00000000..804a85a3 --- /dev/null +++ b/content/master/guides/mrd-activation-policies.md @@ -0,0 +1,691 @@ +--- +title: Writing MRD Activation Policies +weight: 150 +description: Learn how to create effective activation policies for managed resources +--- + +ManagedResourceActivationPolicy (MRAP) provides powerful pattern-based control +over which Managed Resource Definitions (MRDs) become active in your cluster. +This guide shows how to write effective activation policies for different +scenarios. + +## Default activation policy + +Crossplane automatically creates a default ManagedResourceActivationPolicy when +installed. Understanding and configuring this default policy is crucial for +effective MRD management. + +### What is the default MRAP? + +The default MRAP is automatically created by Crossplane and activates managed +resources according to configurable patterns. By default, it uses a wildcard +pattern that activates **all** managed resources: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: crossplane-default-activation-policy +spec: + activations: + - "*" # Activates all managed resources +``` + +{{< hint "important" >}} +The default `"*"` pattern means SafeStart providers will still create all CRDs, +defeating the performance benefits. Most users should customize this behavior. +{{< /hint >}} + +### Configuring default activation with Helm + +Configure the default activation policy during Crossplane installation: + +```yaml +# values.yaml for Crossplane Helm installation +provider: + defaultActivations: + - "*" # Default: activate everything (not recommended for large providers) +``` + +**Recommended configurations:** + +{{< tabs >}} +{{< tab "Production (Selective)" >}} +```yaml +# Recommended: Disable default activation, use targeted policies +provider: + defaultActivations: null # or [] + +# Then create provider-specific MRAPs +# This provides better control and performance +``` +{{< /tab >}} + +{{< tab "Development (Permissive)" >}} +```yaml +# For development environments where you want broad access +provider: + defaultActivations: + - "*.aws.crossplane.io" + - "*.gcp.crossplane.io" + - "*.azure.crossplane.io" +``` +{{< /tab >}} + +{{< tab "Service-Specific" >}} +```yaml +# Activate only specific service categories +provider: + defaultActivations: + - "*.rds.aws.crossplane.io" # All RDS resources + - "*.s3.aws.crossplane.io" # All S3 resources + - "instances.ec2.aws.crossplane.io" # Only EC2 instances +``` +{{< /tab >}} +{{< /tabs >}} + +### Modifying the default policy after installation + +The default activation policy can be modified directly and changes will persist: + +```shell +# View current default policy +kubectl get mrap crossplane-default-activation-policy -o yaml + +# Permanently modify to disable default activation +kubectl patch mrap crossplane-default-activation-policy --type='merge' \ + -p='{"spec":{"activations":["nonexistent.example.com"]}}' + +# Or remove all activations +kubectl patch mrap crossplane-default-activation-policy --type='merge' \ + -p='{"spec":{"activations":[]}}' + +# Or delete the default policy entirely +kubectl delete mrap crossplane-default-activation-policy +``` + +{{< hint "note" >}} +**Changes to the default policy are permanent.** Once the default MRAP exists, +Crossplane will not modify it. The Helm chart `provider.defaultActivations` +value is only used when creating the policy if it doesn't already exist. +{{< /hint >}} + +### Controlling default activation for new installations + +The Helm chart value only affects the **initial creation** of the default policy: + +```shell +# This only matters for NEW installations or when the default policy doesn't exist +helm upgrade crossplane crossplane-stable/crossplane \ + --set provider.defaultActivations=null \ + --namespace crossplane-system --reuse-values +``` + +If you want to reset the default policy to match new Helm values: + +```shell +# Delete existing policy so Crossplane recreates it from Helm values +kubectl delete mrap crossplane-default-activation-policy + +# Restart Crossplane to recreate the policy with current Helm values +kubectl rollout restart deployment/crossplane -n crossplane-system +``` + +### Best practices for default activation + +**Recommended approach:** +1. **Disable default activation** by setting `provider.defaultActivations: null` +2. **Create targeted MRAPs** for each provider or service category +3. **Use specific patterns** rather than wildcards when possible + +```shell +# 1. Install Crossplane with no default activation +helm install crossplane crossplane-stable/crossplane \ + --set provider.defaultActivations=null + +# 2. Create provider-specific activation policies +kubectl apply -f - <}} +Multiple activation policies can exist simultaneously. Their activations are +combined, so any MRD matched by any policy becomes active. +{{< /hint >}} + +## Activation patterns + +### Exact matching + +Activate specific MRDs by their full name: + +```yaml +spec: + activations: + - instances.ec2.aws.crossplane.io + - buckets.s3.aws.crossplane.io + - databases.rds.aws.crossplane.io +``` + +Use exact matching when: +* You know exactly which resources you need +* You want fine-grained control over individual resources +* Security policies require explicit resource approval + +### Wildcard matching + +Use wildcards to activate groups of related resources: + +```yaml +spec: + activations: + - "*.rds.aws.crossplane.io" # All RDS resources + - "*.storage.gcp.crossplane.io" # All GCP storage resources + - "*.compute.azure.crossplane.io" # All Azure compute resources +``` + +{{< hint "tip" >}} +Wildcard patterns only support prefix matching. The `*` must be at the +beginning of the pattern and match one or more DNS label components. +{{< /hint >}} + +### Provider-wide activation + +Activate all resources from a specific provider: + +```yaml +spec: + activations: + - "*.aws.crossplane.io" # All AWS resources + - "*.gcp.crossplane.io" # All GCP resources + - "*.azure.crossplane.io" # All Azure resources +``` + +Use provider-wide activation when: +* You're migrating from non-SafeStart providers +* Your applications use diverse resources from a single provider +* Development environments need broad resource access + +## Environment-based policies + +### Development environment + +Activate minimal resources for development: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: development-resources + namespace: development +spec: + activations: + # Basic compute + - instances.ec2.aws.crossplane.io + - "*.compute.gcp.crossplane.io" + + # Storage + - buckets.s3.aws.crossplane.io + - "*.storage.azure.crossplane.io" + + # Databases + - "*.rds.aws.crossplane.io" + - instances.sql.gcp.crossplane.io +``` + +### Staging environment + +Include additional resources for integration testing: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: staging-resources + namespace: staging +spec: + activations: + # Everything from development + - instances.ec2.aws.crossplane.io + - "*.compute.gcp.crossplane.io" + - buckets.s3.aws.crossplane.io + - "*.storage.azure.crossplane.io" + - "*.rds.aws.crossplane.io" + - instances.sql.gcp.crossplane.io + + # Additional staging needs + - "*.networking.aws.crossplane.io" + - "*.iam.aws.crossplane.io" + - clusters.eks.aws.crossplane.io + - "*.monitoring.gcp.crossplane.io" +``` + +### Production environment + +Activate all necessary resources: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: production-resources + namespace: production +spec: + activations: + # Broad activation for production flexibility + - "*.aws.crossplane.io" + - "*.gcp.crossplane.io" + - "*.azure.crossplane.io" +``` + +## Service-based policies + +### Database services + +Create policies focused on specific service categories: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: database-services +spec: + activations: + # Relational databases + - "*.rds.aws.crossplane.io" + - instances.sql.gcp.crossplane.io + - servers.postgresql.azure.crossplane.io + - servers.mysql.azure.crossplane.io + + # NoSQL databases + - tables.dynamodb.aws.crossplane.io + - instances.spanner.gcp.crossplane.io + - accounts.cosmosdb.azure.crossplane.io + + # Caching + - clusters.elasticache.aws.crossplane.io + - instances.memorystore.gcp.crossplane.io + - caches.redis.azure.crossplane.io +``` + +### Networking services + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: networking-services +spec: + activations: + # Core networking + - vpcs.ec2.aws.crossplane.io + - subnets.ec2.aws.crossplane.io + - networks.compute.gcp.crossplane.io + - subnetworks.compute.gcp.crossplane.io + - virtualnetworks.network.azure.crossplane.io + + # Load balancing + - "*.elbv2.aws.crossplane.io" + - "*.compute.gcp.crossplane.io" + - loadbalancers.network.azure.crossplane.io + + # DNS and routing + - "*.route53.aws.crossplane.io" + - "*.dns.gcp.crossplane.io" + - zones.dns.azure.crossplane.io +``` + +## Team-based policies + +### Platform team + +Broad access for platform engineering: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: platform-team-resources +spec: + activations: + # Infrastructure management + - "*.iam.aws.crossplane.io" + - "*.iam.gcp.crossplane.io" + - "*.authorization.azure.crossplane.io" + + # Networking and security + - "*.ec2.aws.crossplane.io" + - "*.compute.gcp.crossplane.io" + - "*.network.azure.crossplane.io" + + # Monitoring and logging + - "*.cloudwatch.aws.crossplane.io" + - "*.monitoring.gcp.crossplane.io" + - "*.insights.azure.crossplane.io" +``` + +### Application team + +Resources needed by application developers: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: app-team-resources +spec: + activations: + # Compute resources + - instances.ec2.aws.crossplane.io + - clusters.eks.aws.crossplane.io + - clusters.gke.gcp.crossplane.io + + # Storage + - buckets.s3.aws.crossplane.io + - buckets.storage.gcp.crossplane.io + - accounts.storage.azure.crossplane.io + + # Databases (read-only access through compositions) + - "*.rds.aws.crossplane.io" + - instances.sql.gcp.crossplane.io +``` + +## Dynamic activation patterns + +### Conditional activation + +Use multiple policies to create conditional resource activation: + +```yaml +# Base resources always active +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: base-resources +spec: + activations: + - instances.ec2.aws.crossplane.io + - buckets.s3.aws.crossplane.io + +--- +# Optional resources for advanced features +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: advanced-resources +spec: + activations: + - clusters.eks.aws.crossplane.io + - "*.lambda.aws.crossplane.io" +``` + +You can delete the `advanced-resources` policy to quickly deactivate optional +resources while keeping base functionality. + +### Feature flag patterns + +Use labels and naming to create feature flag-like behavior: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: feature-ml-services + labels: + feature: machine-learning + environment: production +spec: + activations: + - "*.sagemaker.aws.crossplane.io" + - "*.ml.gcp.crossplane.io" + - "*.cognitiveservices.azure.crossplane.io" +``` + +## Validation and testing + +### Check activation status + +Verify your policies are working correctly: + +```shell +# List all activation policies +kubectl get mrap + +# Check specific policy status +kubectl describe mrap my-policy + +# See which MRDs are currently active +kubectl get mrds --field-selector spec.state=Active + +# Count active MRDs by provider +kubectl get mrds -l crossplane.io/provider=provider-aws --field-selector spec.state=Active | wc -l +``` + +### Test resource creation + +Verify activated resources work correctly: + +```shell +# Try creating a managed resource +kubectl apply -f - <}} +{{< tab "Multiple Small Policies (Recommended)" >}} +```yaml +# Easier to manage and understand +--- +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: compute-resources +spec: + activations: + - "*.ec2.aws.crossplane.io" + - "*.compute.gcp.crossplane.io" + +--- +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: storage-resources +spec: + activations: + - "*.s3.aws.crossplane.io" + - "*.storage.gcp.crossplane.io" +``` +{{< /tab >}} + +{{< tab "Single Large Policy" >}} +```yaml +# Harder to manage but fewer resources +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: all-resources +spec: + activations: + - "*.ec2.aws.crossplane.io" + - "*.compute.gcp.crossplane.io" + - "*.s3.aws.crossplane.io" + - "*.storage.gcp.crossplane.io" + # ... many more activations +``` +{{< /tab >}} +{{< /tabs >}} + +## Policy lifecycle management + +### GitOps workflow + +Store activation policies in Git for proper change management: + +```yaml +# clusters/production/activation-policies/ +production-compute.yaml +production-storage.yaml +production-networking.yaml + +# clusters/staging/activation-policies/ +staging-core.yaml +staging-experimental.yaml + +# clusters/development/activation-policies/ +development-minimal.yaml +``` + +### Versioning strategies + +Use metadata to track policy versions: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: production-resources + labels: + version: "v2.1.0" + environment: production + team: platform-engineering + annotations: + policy.crossplane.io/description: "Production resource activation policy" + policy.crossplane.io/last-updated: "2024-01-15" + policy.crossplane.io/approved-by: "platform-team" +spec: + activations: + - "*.aws.crossplane.io" +``` + +## Integration with compositions + +### Composition compatibility + +Compositions work with both active and inactive MRDs, but resource creation +only succeeds when MRDs are active: + +```yaml +# This composition can exist regardless of MRD state +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: webapp-stack +spec: + compositeTypeRef: + apiVersion: platform.example.com/v1alpha1 + kind: WebApp + resources: + - name: database + base: + apiVersion: rds.aws.crossplane.io/v1alpha1 + kind: DBInstance + # This only works if RDS MRDs are active + - name: storage + base: + apiVersion: s3.aws.crossplane.io/v1alpha1 + kind: Bucket + # This only works if S3 MRDs are active +``` + +### Activation dependencies + +Document activation requirements in compositions: + +```yaml +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: ml-pipeline + annotations: + composition.crossplane.io/required-mrds: | + - "*.sagemaker.aws.crossplane.io" + - "*.s3.aws.crossplane.io" + - "*.iam.aws.crossplane.io" +spec: + # ... composition definition +``` + +This helps operators understand which activation policies are needed for +specific compositions to work correctly. \ No newline at end of file diff --git a/content/master/managed-resources/managed-resource-definitions.md b/content/master/managed-resources/managed-resource-definitions.md new file mode 100644 index 00000000..ea2af556 --- /dev/null +++ b/content/master/managed-resources/managed-resource-definitions.md @@ -0,0 +1,237 @@ +--- +title: Managed Resource Definitions +weight: 10 +description: Understand Managed Resource Definitions (MRDs) and selective resource activation +--- + +Managed Resource Definitions (MRDs) provide a lightweight abstraction over +Kubernetes Custom Resource Definitions (CRDs) that enables selective +installation and better documentation of managed resources. + +{{< hint "note" >}} +MRDs are available in Crossplane v2.0+ as an alpha feature. +{{< /hint >}} + +## What are managed resource definitions? + +A Managed Resource Definition (MRD) is essentially a CRD with additional +metadata that provides: + +* **Connection details schema** - Documents what connection details the + managed resource provides +* **Activation control** - Controls whether the underlying CRD gets installed + in your cluster +* **Resource discovery** - Makes it easier to understand what resources are + available + +**Every managed resource in a provider package has an associated MRD.** The MRD +contains the same schema as the CRD, plus additional Crossplane-specific +metadata. + +```mermaid +flowchart LR + provider(Provider Package) + mrd(MRD) + crd(CRD) + mr(Managed Resource) + + provider --> mrd + mrd --"when active"--> crd + crd --> mr + + style mrd fill:#e1f5fe + style crd fill:#f3e5f5 +``` + +## Why use managed resource definitions? + +MRDs solve several challenges with traditional provider packages: + +### Performance optimization +Installing a provider creates CRDs for _every_ managed resource the provider +supports. For large providers like AWS, this can mean hundreds of CRDs that +you may never use. + +**MRDs let you install only the CRDs you need**, reducing Kubernetes API +server overhead and improving cluster performance. + +### Connection details discovery +Understanding what connection details a managed resource provides requires +reading provider source code or trial-and-error testing. + +**MRDs document connection details in the schema**, making it clear what +credentials and endpoints each resource provides. + +### Selective installation +Different environments may need different subsets of managed resources. A +development environment might only need basic resources, while production +needs the full set. + +**MRDs enable environment-specific resource activation** through policies. + +## How MRDs work + +When you install a provider package, Crossplane creates: + +1. **MRDs for all resources** - Every managed resource gets an MRD +2. **CRDs only when activated** - Crossplane creates CRDs only for active MRDs +3. **Activation policies** - ManagedResourceActivationPolicy controls which + MRDs become active + +### MRD lifecycle + +```mermaid +flowchart TD + install[Install Provider] + createMRD[Create MRDs] + checkPolicy{Activation Policy
Matches?} + activate[Activate MRD] + createCRD[Create CRD] + inactive[MRD Inactive] + + install --> createMRD + createMRD --> checkPolicy + checkPolicy -->|Yes| activate + checkPolicy -->|No| inactive + activate --> createCRD + + style activate fill:#c8e6c9 + style inactive fill:#ffcdd2 +``` + +### MRD states + +MRDs can be in one of two states: + +* **Active** - The underlying CRD exists and you can create managed resources +* **Inactive** - No CRD exists, managed resource creation fails + +You can change an MRD's state by: +* Editing the MRD directly (`spec.state: Active`) +* Using a ManagedResourceActivationPolicy +* Provider package capabilities (SafeStart) + +## Connection details schema + +MRDs document the connection details that managed resources provide. This makes +it easier to understand what credentials and endpoints you get when creating +resources. + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceDefinition +metadata: + name: instances.ec2.aws.crossplane.io +spec: + connectionDetails: + - name: endpoint + description: The connection endpoint for the database + type: string + - name: port + description: The port number for connections + type: integer + - name: username + description: The master username for the database + type: string + - name: password + description: The master password for the database + type: string + fromConnectionSecretKey: password +``` + +The `connectionDetails` field documents: +* **Connection detail names** - What keys appear in connection secrets +* **Descriptions** - What each connection detail contains +* **Types** - The data type of each detail +* **Source keys** - How details map from provider responses + +## Managed Resource Activation Policy + +ManagedResourceActivationPolicy (MRAP) provides pattern-based control over +which MRDs become active. This is more scalable than manually activating +individual MRDs. + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: aws-core-resources +spec: + activations: + - "instances.ec2.aws.crossplane.io" # Specific MRD + - "*.rds.aws.crossplane.io" # All RDS resources + - "buckets.s3.aws.crossplane.io" # S3 buckets +``` + +### Activation patterns + +MRAP supports several activation patterns: + +* **Exact match**: `instances.ec2.aws.crossplane.io` +* **Wildcard prefix**: `*.rds.aws.crossplane.io` (all RDS resources) +* **Provider wildcard**: `*.aws.crossplane.io` (all AWS resources) + +Multiple MRAPs can exist, and their activations are combined. + +## Provider capabilities + +Providers can declare capabilities that affect MRD behavior: + +### SafeStart capability +Providers with the `SafeStart` capability start with all MRDs inactive by +default. This prevents performance issues when installing large providers. + +Without SafeStart, all MRDs are active by default for backward compatibility. + +```yaml +# In provider package metadata +spec: + capabilities: + - name: SafeStart +``` + +{{< hint "note" >}} +Implementing SafeStart requires significant provider code changes. Provider +developers should follow the +[SafeStart implementation guide]({{< ref "../guides/implementing-safestart" >}}) +for detailed technical requirements and examples. +{{< /hint >}} + +### SafeStart implementation examples + +The Crossplane community has implemented SafeStart in several providers: + +* **provider-nop** - [Reference implementation](https://github.com/crossplane-contrib/provider-nop/pull/24) + showing SafeStart integration with both namespaced and cluster-scoped resources +* **provider-aws** - Large provider demonstrating SafeStart performance benefits + +These implementations provide real-world examples of: +- MRD controller integration +- Build process modifications +- Testing strategies for SafeStart behavior +- Migration approaches for existing users + +## Key concepts + +Understanding these terms helps when working with MRDs: + +* **MRD** - The definition that may or may not have an active CRD +* **MRAP** - Policy that controls which MRDs become active +* **Active state** - MRD has an underlying CRD, resources can be created +* **Inactive state** - No CRD exists, resource creation fails +* **SafeStart** - Provider capability that defaults MRDs to inactive +* **Connection details schema** - Documentation of what connection details + a managed resource provides + +## Relationship to other Crossplane features + +MRDs integrate with existing Crossplane concepts: + +* **Providers** - Create MRDs when installed +* **Managed resources** - Can only be created when their MRD is active +* **Compositions** - Can reference both active and inactive managed resources + (composition validation occurs at render time) +* **Claims** - Work normally once the underlying managed resources are active + +MRDs are backward compatible. Existing providers and compositions continue to +work without modification. \ No newline at end of file diff --git a/content/master/packages/provider-capabilities.md b/content/master/packages/provider-capabilities.md new file mode 100644 index 00000000..9a7d89d7 --- /dev/null +++ b/content/master/packages/provider-capabilities.md @@ -0,0 +1,372 @@ +--- +title: Provider Capabilities +weight: 20 +description: Understand provider capabilities and how they affect resource behavior +--- + +Provider capabilities are declarative features that providers can implement to +modify their behavior and integration with Crossplane. Capabilities enable +providers to opt into new features while maintaining backward compatibility. + +## What are provider capabilities? + +Provider capabilities are metadata declarations in provider packages that tell +Crossplane how the provider should behave. They're similar to feature flags +but are declared at the package level. + +```yaml +# In provider package metadata +apiVersion: meta.pkg.crossplane.io/v1alpha1 +kind: Provider +metadata: + name: provider-aws +spec: + capabilities: + - name: SafeStart + - name: CustomCapability +``` + +Crossplane reads these capabilities and modifies its behavior when installing +and managing the provider. + +## Available capabilities + +### SafeStart + +The `SafeStart` capability changes how Managed Resource Definitions (MRDs) are +activated when the provider is installed. + +**Without SafeStart:** +- All MRDs are automatically activated +- All corresponding CRDs are created immediately +- Compatible with legacy providers and existing workflows + +**With SafeStart:** +- All MRDs start in `Inactive` state +- No CRDs are created until MRDs are explicitly activated +- Reduces initial resource overhead and improves performance + +```yaml +spec: + capabilities: + - name: SafeStart +``` + +{{< hint "tip" >}} +SafeStart is particularly valuable for large providers like AWS that define +hundreds of managed resources. It prevents performance issues by avoiding the +creation of unused CRDs. +{{< /hint >}} + +#### When to use SafeStart + +Use SafeStart when: +* Your provider defines many managed resources (>50) +* Users typically need only a subset of available resources +* Installation performance and resource usage are concerns +* You want to provide better resource discovery through MRDs + +Don't use SafeStart when: +* Your provider has few managed resources (<20) +* Most users need all available resources +* Backward compatibility with existing installations is critical +* Your users aren't ready to manage resource activation + +## Capability matching + +Crossplane supports flexible matching for capability names: + +* **Exact match**: `SafeStart` +* **Case variations**: `safestart`, `safe-start`, `SafeStart` +* **Fuzzy matching**: Handles common spelling variations + +This flexibility prevents issues when providers use different naming conventions. + +## How capabilities affect installation + +The provider installation process changes based on declared capabilities: + +```mermaid +flowchart TD + install[Install Provider Package] + readCaps[Read Capabilities] + checkSafe{Has SafeStart?} + activateAll[Activate All MRDs] + keepInactive[Keep MRDs Inactive] + createCRDs[Create All CRDs] + waitPolicy[Wait for Activation Policy] + + install --> readCaps + readCaps --> checkSafe + checkSafe -->|No| activateAll + checkSafe -->|Yes| keepInactive + activateAll --> createCRDs + keepInactive --> waitPolicy + + style keepInactive fill:#c8e6c9 + style waitPolicy fill:#fff3e0 +``` + +## Provider compatibility + +### Legacy providers + +Providers without any capabilities work exactly as before: +* All MRDs are active by default +* All CRDs are created immediately +* No changes required for existing compositions or configurations + +### Modern providers + +Providers with SafeStart capability require additional setup: +* Create ManagedResourceActivationPolicy to activate needed resources +* Verify required CRDs exist before creating managed resources +* Use MRD connection details documentation for resource planning + +## Implementing SafeStart in providers + +SafeStart implementation requires several technical changes to provider code and +build processes. This section provides an overview - see the +[complete SafeStart implementation guide]({{< ref "../guides/implementing-safestart" >}}) +for detailed instructions. + +### Key implementation requirements + +**Code changes:** +- Add MRD controller logic to handle activation/deactivation +- Support both namespaced and cluster-scoped resources +- Generate MRDs with connection details documentation +- Implement CRD lifecycle management + +**Build process changes:** +- Update Makefile to generate MRDs alongside CRDs +- Modify CI/CD to test SafeStart behavior +- Include MRDs in provider package artifacts + +**RBAC updates:** +SafeStart providers need additional permissions to manage CRDs dynamically: + +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: my-provider-system +rules: +# Standard provider permissions +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "update", "patch"] + +# Additional SafeStart permissions +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["apiextensions.crossplane.io"] + resources: ["managedresourcedefinitions"] + verbs: ["get", "list", "watch", "update", "patch"] +``` + +### Provider package metadata + +Declare SafeStart capability in your provider package: + +```yaml +apiVersion: meta.pkg.crossplane.io/v1 +kind: Provider +metadata: + name: my-provider +spec: + package: registry.example.com/my-provider:v2.0.0 + capabilities: + - name: SafeStart +``` + +### MRD generation with connection details + +Generate MRDs that document connection details for better user experience: + +```yaml +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceDefinition +metadata: + name: databases.rds.aws.example.io +spec: + group: rds.aws.example.io + names: + kind: Database + plural: databases + scope: Namespaced + + # Connection details documentation + connectionDetails: + - name: endpoint + description: "The RDS instance connection endpoint" + type: string + fromConnectionSecretKey: endpoint + - name: port + description: "The port number for database connections" + type: integer + fromConnectionSecretKey: port + - name: username + description: "The master username for the database" + type: string + fromConnectionSecretKey: username + - name: password + description: "The master password for the database" + type: string + fromConnectionSecretKey: password +``` + +### Implementation examples + +The [provider-nop SafeStart implementation](https://github.com/crossplane-contrib/provider-nop/pull/24) +demonstrates: +- Adding both namespaced and cluster-scoped resource variants +- MRD controller integration +- Build process updates for SafeStart support +- Testing strategies for SafeStart behavior + +{{< hint "tip" >}} +See the [complete SafeStart implementation guide]({{< ref "../guides/implementing-safestart" >}}) +for step-by-step instructions, code examples, and testing strategies. +{{< /hint >}} + +### Migration considerations + +When adding SafeStart to existing providers: + +**Backward compatibility:** +- Existing provider installations continue working unchanged +- New installations start with inactive MRDs +- Provide migration documentation for users + +**Version strategy:** +```yaml +# Document version compatibility clearly +# Provider v1.x: Traditional CRD installation +# Provider v2.0+: SafeStart support with MRDs +``` + +## Best practices + +### For provider developers + +**Do use SafeStart when:** +* Your provider has >50 managed resources +* Resource activation patterns vary by environment +* Performance optimization is important + +**Document capabilities clearly:** +* Explain what each capability does +* Provide migration guides for existing users +* Include examples of activation policies + +**Test compatibility:** +* Verify behavior with and without capabilities +* Test with different Crossplane versions +* Validate RBAC permissions + +### For platform operators + +**Plan activation policies:** +```yaml +# Development environment - minimal resources +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: dev-resources +spec: + activations: + - "databases.*.example.com" + - "buckets.*.example.com" + +--- +# Production environment - comprehensive resources +apiVersion: apiextensions.crossplane.io/v1alpha1 +kind: ManagedResourceActivationPolicy +metadata: + name: prod-resources +spec: + activations: + - "*.example.com" # Activate all resources +``` + +**Monitor activation status:** +```shell +# Check which MRDs are active +kubectl get mrds -l provider=my-provider + +# Verify activation policies +kubectl get mrap -o wide + +# Monitor resource usage +kubectl top nodes +``` + +## Future capabilities + +The capability system is extensible. Future capabilities might include: + +* **ResourceQuotas** - Automatic resource limit management +* **NetworkPolicies** - Provider-specific network isolation +* **CustomValidation** - Enhanced resource validation +* **TelemetryOpt** - Telemetry and observability features + +## Troubleshooting capabilities + +### Common issues + +**MRDs not activating:** +```shell +# Check if provider has SafeStart capability +kubectl get provider my-provider -o yaml | grep -A5 capabilities + +# Verify activation policy exists and matches +kubectl get mrap +kubectl describe mrap my-policy +``` + +**CRDs not created:** +```shell +# Check MRD activation status +kubectl get mrd my-resource.example.com + +# Look for controller errors +kubectl logs -n crossplane-system deployment/crossplane +``` + +**Provider installation fails:** +```shell +# Check provider conditions +kubectl describe provider my-provider + +# Look for RBAC issues +kubectl get events --field-selector reason=FailedCreate +``` + +### Debug commands + +```shell +# List all providers and their capabilities +kubectl get providers -o jsonpath='{range .items[*]}{.metadata.name}: {.spec.capabilities[*].name}{"\n"}{end}' + +# Check MRD activation across providers +kubectl get mrds --show-labels + +# Verify CRD creation matches activation +kubectl get crds | grep example.com | wc -l +kubectl get mrds -l state=Active | wc -l +``` + +## Relationship to other features + +Provider capabilities integrate with: + +* **MRDs** - SafeStart controls default activation state +* **Activation policies** - Work together to control resource availability +* **Package manager** - Capabilities are read during package installation +* **RBAC** - Some capabilities require additional permissions +* **Compositions** - May need updates when capabilities change resource availability + +Capabilities provide a foundation for evolving provider behavior while +maintaining compatibility with existing Crossplane installations. \ No newline at end of file diff --git a/content/master/whats-new/_index.md b/content/master/whats-new/_index.md index 149e92da..33a7a39c 100644 --- a/content/master/whats-new/_index.md +++ b/content/master/whats-new/_index.md @@ -6,12 +6,13 @@ description: Learn what's new in the Crossplane v2 preview **Crossplane v2 makes Crossplane more useful, more intuitive, and less opinionated.** -Crossplane v2 makes four major changes: +Crossplane v2 makes five major changes: * **Composite resources are now namespaced** -* **Managed resources are now namespaced** +* **Managed resources are now namespaced** * **Composition supports any Kubernetes resource** * **Operations enable operational workflows** +* **Managed Resource Definitions provide selective resource activation** **Crossplane v2 is better suited to building control planes for applications, not just infrastructure.** It removes the need for awkward abstractions like @@ -172,6 +173,61 @@ deprecate and remove cluster scoped MRs at a future date. Read more about Crossplane v2's [backward compatibility](#backward-compatibility). {{}} +## Managed Resource Definitions + +Crossplane v2 introduces Managed Resource Definitions (MRDs) that provide +selective resource activation and improved resource discovery. + +**MRDs solve performance and usability challenges with large providers.** +Installing a provider like AWS traditionally creates hundreds of CRDs, even if +you only need a few resources. MRDs let you activate only the resources you +actually use. + +```mermaid +flowchart LR + provider(Provider Package) + mrd1(S3 Bucket MRD) + mrd2(EC2 Instance MRD) + mrd3(RDS DB MRD) + crd1(S3 Bucket CRD) + crd2(EC2 Instance CRD) + policy(Activation Policy) + + provider --> mrd1 + provider --> mrd2 + provider --> mrd3 + + policy -.->|activates| mrd1 + policy -.->|activates| mrd2 + mrd3 -.->|inactive| + + mrd1 --> crd1 + mrd2 --> crd2 + + style mrd1 fill:#c8e6c9 + style mrd2 fill:#c8e6c9 + style mrd3 fill:#ffcdd2 + style crd1 fill:#e8f5e8 + style crd2 fill:#e8f5e8 +``` + +### Key MRD benefits + +**Performance optimization** - Only create CRDs for resources you need, reducing +cluster overhead and improving provider installation speed. + +**Connection details discovery** - MRDs document what connection details each +managed resource provides, making it easier to understand resource capabilities. + +**Policy-based activation** - Use ManagedResourceActivationPolicy (MRAP) to +activate resources with flexible pattern matching. + +**SafeStart providers** - Providers can opt into SafeStart capability, starting +with all MRDs inactive for better performance. + +Learn more about [Managed Resource Definitions]({{}}) +and [get started with MRDs]({{}}). + ## Compose any resource Crossplane v2 isn't opinionated about using composition together with managed diff --git a/utils/vale/styles/Crossplane/crossplane-words.txt b/utils/vale/styles/Crossplane/crossplane-words.txt index 50a59d28..dd8712f4 100644 --- a/utils/vale/styles/Crossplane/crossplane-words.txt +++ b/utils/vale/styles/Crossplane/crossplane-words.txt @@ -61,7 +61,15 @@ initProvider KCL LateInitialize managementPolicies +ManagedResourceActivationPolicy +ManagedResourceDefinition +ManagedResourceDefinitions +MRAP +MRAPs MR +MRD +MRD's +MRDs MRs Operation-specific PatchSet @@ -71,6 +79,8 @@ ProviderConfigs ProviderRevision RunFunctionRequest RunFunctionResponse +SafeStart +SafeStart-capable Sigstore SSL StoreConfig diff --git a/utils/vale/styles/Crossplane/spelling-exceptions.txt b/utils/vale/styles/Crossplane/spelling-exceptions.txt index a86c0320..59e79cb5 100644 --- a/utils/vale/styles/Crossplane/spelling-exceptions.txt +++ b/utils/vale/styles/Crossplane/spelling-exceptions.txt @@ -84,3 +84,24 @@ v2 validators version-specific webhook-based +well-documented +user-friendly +provider-nop +provider-specific +pattern-based +fine-grained +environment-specific +real-world +trial-and-error +CRD-only +flag-like +Team-based +Service-based +Provider-wide +Environment-based +Policy-based +Crossplane-specific +non-SafeStart +GitOps +Makefile +backporting