Crossplane Kubernetes Infrastructure Management
Manage cloud infrastructure as Kubernetes resources with Crossplane. Provision AWS, GCP, and Azure resources using custom resource
π‘ Quick Answer: Crossplane extends Kubernetes with CRDs for cloud resources (RDS, S3, VPCs, etc.). Install Crossplane + a Provider (AWS/GCP/Azure), define Compositions for your infrastructure patterns, then teams claim resources with simple CRs β just like requesting a PVC. GitOps-friendly:
kubectl get managedshows all cloud resources.
The Problem
- Infrastructure provisioning is disconnected from application deployment
- Terraform state management is complex in team environments
- Developers need cloud resources but shouldnβt have direct cloud console access
- Multi-cloud requires different tools (Terraform, Pulumi, CloudFormation)
- No single control plane for both infrastructure and applications
The Solution
Install Crossplane
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane crossplane-stable/crossplane \
--namespace crossplane-system \
--create-namespace \
--wait
# Verify
kubectl get pods -n crossplane-system
kubectl get crds | grep crossplaneInstall AWS Provider
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws
spec:
package: xpkg.upbound.io/upbound/provider-family-aws:v1.7.0
---
# Provider credentials
apiVersion: v1
kind: Secret
metadata:
name: aws-credentials
namespace: crossplane-system
type: Opaque
stringData:
credentials: |
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
---
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-credentials
key: credentialsProvision Cloud Resources
# Create an S3 bucket
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
name: my-app-data
spec:
forProvider:
region: us-east-1
tags:
Environment: production
ManagedBy: crossplane
providerConfigRef:
name: default
---
# Create an RDS instance
apiVersion: rds.aws.upbound.io/v1beta2
kind: Instance
metadata:
name: my-app-database
spec:
forProvider:
region: us-east-1
instanceClass: db.t3.medium
engine: postgres
engineVersion: "15"
allocatedStorage: 50
dbName: myapp
masterUsername: admin
masterPasswordSecretRef:
name: db-master-password
namespace: crossplane-system
key: password
skipFinalSnapshot: true
publiclyAccessible: false
vpcSecurityGroupIdRefs:
- name: db-security-group
providerConfigRef:
name: default
writeConnectionSecretToRef:
name: db-connection
namespace: my-appDefine Compositions (Platform API)
# Composition: reusable infrastructure template
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xdatabases.platform.example.com
spec:
group: platform.example.com
names:
kind: XDatabase
plural: xdatabases
claimNames:
kind: Database
plural: databases
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
size:
type: string
enum: ["small", "medium", "large"]
engine:
type: string
enum: ["postgres", "mysql"]
required: ["size", "engine"]
---
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: database-aws
labels:
provider: aws
spec:
compositeTypeRef:
apiVersion: platform.example.com/v1alpha1
kind: XDatabase
resources:
- name: rds-instance
base:
apiVersion: rds.aws.upbound.io/v1beta2
kind: Instance
spec:
forProvider:
region: us-east-1
skipFinalSnapshot: true
publiclyAccessible: false
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.engine
toFieldPath: spec.forProvider.engine
- type: FromCompositeFieldPath
fromFieldPath: spec.size
toFieldPath: spec.forProvider.instanceClass
transforms:
- type: map
map:
small: db.t3.micro
medium: db.t3.medium
large: db.r6g.xlargeTeam Claims (Simple Interface)
# Developers request a database β no cloud knowledge needed
apiVersion: platform.example.com/v1alpha1
kind: Database
metadata:
name: user-service-db
namespace: user-service
spec:
size: medium
engine: postgresCheck Status
# View all managed cloud resources
kubectl get managed
# NAME READY SYNCED AGE
# bucket.s3.aws/my-app-data True True 5m
# instance.rds.aws/my-app-database True True 10m
# View claims
kubectl get databases -A
# NAMESPACE NAME READY CONNECTION-SECRET AGE
# user-service user-service-db True db-connection 3m
# Debug resource
kubectl describe instance.rds.aws my-app-databaseCommon Issues
Resource stuck in βCreatingβ / not syncing
- Cause: Provider credentials incorrect or insufficient IAM permissions
- Fix: Check provider pod logs:
kubectl logs -n crossplane-system -l pkg.crossplane.io/revision
βcannot compose resources: referenced field not foundβ
- Cause: Patch path doesnβt match actual resource spec
- Fix: Verify field paths against provider CRD schema; use
kubectl explain
Composition not selected for claim
- Cause: No matching Composition for the CompositeResourceDefinition
- Fix: Ensure Compositionβs
compositeTypeRefmatches XRD; check label selectors
Best Practices
- Use Compositions β abstract cloud details; expose simple claims to teams
- GitOps with ArgoCD β manage Crossplane resources in Git like any other K8s resource
- IRSA/Workload Identity β avoid static credentials; use cloud-native identity
- Separate provider configs β different credentials for dev/staging/prod
- Write connection secrets β auto-inject credentials into application namespaces
- Monitor with
kubectl get managedβ single view of all cloud resources
Key Takeaways
- Crossplane makes cloud resources into Kubernetes CRDs β managed via
kubectl - Compositions create platform APIs β teams claim resources without cloud expertise
- Providers support AWS, GCP, Azure, and 100+ services
- GitOps-native: store infrastructure as YAML in Git, deploy via ArgoCD
- Connection secrets automatically provide credentials to applications
kubectl get managedshows all cloud resources across all providers

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
