Back to Technology

Crossplane Track Part 1: Providers & Managed Resources

June 6, 2026 Wasil Zafar 38 min read

Install Crossplane, configure cloud Providers, and create Managed Resources to provision real cloud infrastructure from Kubernetes.

Table of Contents

  1. Crossplane Concepts
  2. Install Crossplane
  3. Configure a Provider
  4. Managed Resources
  5. Resource Status & Readiness
  6. Exercises
  7. Key Takeaways & Next Steps

Crossplane Concepts

Crossplane transforms your Kubernetes cluster into a universal control plane for infrastructure. Instead of using vendor-specific tools (Terraform CLI, AWS Console, gcloud), you declare infrastructure as Kubernetes custom resources and let Crossplane reconcile them into real cloud resources.

Key Insight: Crossplane extends the Kubernetes API with CRDs for every cloud resource (S3 buckets, RDS instances, VPCs). You manage infrastructure with the same kubectl workflows, RBAC, and GitOps pipelines you already use for applications.
  • Providers — Extend the Kubernetes API with CRDs for a specific cloud (AWS, GCP, Azure). Each Provider installs hundreds of new resource types
  • Managed Resources — Individual cloud resources represented as Kubernetes objects (e.g., an S3 Bucket, a CloudSQL Instance)
  • ProviderConfig — Credentials and configuration for authenticating to the cloud provider
  • Compositions — Templates that combine multiple Managed Resources into reusable blueprints (covered in Part 2)

Install Crossplane

Crossplane installs into its own namespace and runs as a set of controllers that watch for infrastructure CRDs:

# Add the Crossplane Helm repository
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update

# Install Crossplane into the crossplane-system namespace
helm install crossplane crossplane-stable/crossplane \
  --namespace crossplane-system \
  --create-namespace \
  --set args='{"--enable-usages"}'

# Verify the installation
kubectl get pods -n crossplane-system
# Expected: crossplane and crossplane-rbac-manager pods Running

# Check Crossplane version
kubectl get deployment crossplane -n crossplane-system \
  -o jsonpath='{.spec.template.spec.containers[0].image}'

Configure a Provider

Providers are Crossplane packages that install cloud-specific CRDs and controllers. After installing a Provider, you configure it with credentials via a ProviderConfig:

# Install the AWS Provider
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-s3
spec:
  package: xpkg.upbound.io/upbound/provider-aws-s3:v1.7.0
  runtimeConfigRef:
    name: default
# Apply the Provider
kubectl apply -f provider-aws-s3.yaml

# Wait for the Provider to become healthy
kubectl get providers.pkg.crossplane.io
# NAME              INSTALLED   HEALTHY   PACKAGE                                          AGE
# provider-aws-s3   True        True      xpkg.upbound.io/upbound/provider-aws-s3:v1.7.0  60s

# Create a credentials Secret for AWS
kubectl create secret generic aws-credentials \
  -n crossplane-system \
  --from-file=credentials=./aws-credentials.txt
# Configure the Provider with credentials
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
  name: default
spec:
  credentials:
    source: Secret
    secretRef:
      namespace: crossplane-system
      name: aws-credentials
      key: credentials

Managed Resources

With the Provider installed and configured, you can create Managed Resources — Kubernetes objects that map 1:1 to cloud resources. Crossplane continuously reconciles desired state with actual cloud state.

# Create an S3 Bucket as a Managed Resource
apiVersion: s3.aws.upbound.io/v1beta2
kind: Bucket
metadata:
  name: my-crossplane-bucket
spec:
  forProvider:
    region: us-east-1
    tags:
      Environment: production
      ManagedBy: crossplane
  providerConfigRef:
    name: default
# Apply and observe the resource
kubectl apply -f bucket.yaml

# Check the status
kubectl get bucket my-crossplane-bucket
# NAME                   READY   SYNCED   EXTERNAL-NAME          AGE
# my-crossplane-bucket   True    True     my-crossplane-bucket   2m

# Describe for detailed conditions
kubectl describe bucket my-crossplane-bucket

# Delete the cloud resource by deleting the K8s object
kubectl delete bucket my-crossplane-bucket

Resource Status & Readiness

Every Managed Resource reports its state through standard Kubernetes conditions. The two critical conditions are Synced (Crossplane successfully communicated with the cloud API) and Ready (the cloud resource is available for use).

Status Flow: After kubectl apply, a resource transitions: Synced=False → Synced=True, Ready=False → Ready=True. If provisioning fails, Synced shows the error. The external-name annotation stores the cloud-side identifier (ARN, resource ID).
# Watch resource conditions in real-time
kubectl get bucket -w

# Query specific conditions
kubectl get bucket my-crossplane-bucket -o jsonpath='{.status.conditions}'

# Check the external-name (cloud resource identifier)
kubectl get bucket my-crossplane-bucket \
  -o jsonpath='{.metadata.annotations.crossplane\.io/external-name}'

# List all managed resources across all types
kubectl get managed

Exercises

Exercise 1: Install Crossplane on a Kind cluster. Install provider-aws-s3 and configure it with AWS credentials (use localstack for a free local AWS simulation). Create an S3 Bucket Managed Resource and verify it reaches Ready=True and Synced=True status.
Exercise 2: Install a second Provider (e.g., provider-aws-rds). Create an RDS Instance Managed Resource with spec.forProvider specifying engine, instanceClass, and masterUsername. Observe the provisioning lifecycle and check the external-name annotation once ready.
Exercise 3: Test Crossplane's drift detection by manually modifying the S3 bucket tags in the AWS console (or localstack). Wait for the next reconciliation loop (~1 minute) and verify that Crossplane corrects the drift back to the declared state. Use kubectl describe to observe the reconciliation event.

Key Takeaways & Next Steps

  • Crossplane turns Kubernetes into a control plane for cloud infrastructure
  • Providers install CRDs for specific cloud services; ProviderConfig supplies credentials
  • Managed Resources are 1:1 mappings to cloud resources with continuous reconciliation
  • Synced and Ready conditions report provisioning status; external-name stores the cloud ID
  • Drift detection automatically corrects manual changes to match declared state

Next in the Series

In Part 2: Compositions & XRDs, we'll define reusable infrastructure blueprints using Compositions and expose simplified platform APIs via CompositeResourceDefinitions.