Skip to main content
โšก Calmops

Crossplane: Kubernetes-based Control Plane for Cloud Resources

Introduction

Crossplane transforms Kubernetes into a universal control plane for cloud resources. Instead of managing infrastructure through scattered CLIs and dashboards, you can define, compose, and provision cloud services using familiar Kubernetes patterns.

This guide covers Crossplane’s architecture, practical implementation, and how to build internal platforms with it.


Understanding Crossplane

Crossplane extends Kubernetes with:

  • Custom Resource Definitions (CRDs): Cloud resources as Kubernetes objects
  • Composites: Compose multiple resources into higher-level abstractions
  • Providers: Cloud provider-specific controllers
  • Self-Service: Enable teams to provision resources without tickets

Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      Crossplane                          โ”‚
โ”‚                                                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚              Kubernetes Cluster                   โ”‚   โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚   โ”‚
โ”‚  โ”‚  โ”‚  Composite  โ”‚  โ”‚   XRDs      โ”‚  โ”‚ Claims   โ”‚โ”‚   โ”‚
โ”‚  โ”‚  โ”‚ Definitions โ”‚  โ”‚             โ”‚  โ”‚          โ”‚โ”‚   โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜โ”‚   โ”‚
โ”‚  โ”‚         โ”‚                 โ”‚                โ”‚      โ”‚   โ”‚
โ”‚  โ”‚         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚   โ”‚
โ”‚  โ”‚                           โ–ผ                        โ”‚   โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚   โ”‚
โ”‚  โ”‚  โ”‚           Composition Engine                 โ”‚ โ”‚   โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                           โ”‚                                โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚                   Providers                          โ”‚   โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”          โ”‚   โ”‚
โ”‚  โ”‚  โ”‚   AWS    โ”‚  โ”‚   Azure  โ”‚  โ”‚   GCP    โ”‚          โ”‚   โ”‚
โ”‚  โ”‚  โ”‚ Provider  โ”‚  โ”‚ Provider  โ”‚  โ”‚ Provider  โ”‚          โ”‚   โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜          โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Installation

Basic Installation

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

# Install Crossplane
helm install crossplane crossplane-stable/crossplane \
  --namespace crossplane-system \
  --create-namespace

# Install CLI
brew install crossplane/tap/crossplane

# Verify installation
crossplane version

Provider Installation

# Install AWS Provider
crossplane pkg install provider crossplane/provider-aws:v0.47.0

# Install Azure Provider
crossplane pkg install provider crossplane/provider-azure:v0.16.0

# Install GCP Provider
crossplane pkg install provider crossplane/provider-gcp:v0.23.0

# View installed providers
crossplane pkg get providers

Core Concepts

Providers

# provider-aws.yaml
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws
spec:
  package: crossplane/provider-aws:v0.47.0
  controllerConfigRef:
    name: aws-provider-config
---
apiVersion: v1
kind: Secret
metadata:
  name: aws-creds
  namespace: crossplane-system
type: Opaque
data:
  credentials: <base64-encoded-aws-creds>
---
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: aws-provider-config
spec:
  credentials:
    source: Secret
    secretRef:
      name: aws-creds
      namespace: crossplane-system
      key: credentials

Composite Resource Definitions (XRD)

# xrd-database.yaml
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: databases.example.com
spec:
  group: example.com
  names:
    kind: Database
    plural: databases
  versions:
    - name: v1alpha1
      served: true
      referenceable: true
  validation:
    openAPIV3Schema:
      type: object
      properties:
        spec:
          type: object
          properties:
            size:
              type: string
              enum: [small, medium, large]
            engine:
              type: string
              enum: [mysql, postgres]
          required:
            - size
            - engine

Composition

# composition-database.yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: database.example.com
  labels:
    provider: aws
spec:
  compositeTypeRef:
    apiVersion: example.com/v1alpha1
    kind: Database
  resources:
    # RDS Instance
    - name: rds
      base:
        apiVersion: rds.aws.crossplane.io/v1alpha1
        kind: DBInstance
        spec:
          forProvider:
            dbInstanceClass: db.t3.small
            engine: postgres
            masterUsername: admin
            allocatedStorage: 20
          providerConfigRef:
            name: aws-provider-config
      patches:
        - fromFieldPath: metadata.name
          toFieldPath: metadata.name
        - fromFieldPath: spec.size
          toFieldPath: spec.forProvider.dbInstanceClass
          transforms:
            - type: map
              map:
                small: db.t3.small
                medium: db.t3.medium
                large: db.t3.large
        - fromFieldPath: spec.engine
          toFieldPath: spec.forProvider.engine
        - fromFieldPath: metadata.uid
          toFieldPath: spec.writeConnectionSecretToRef.name

    # Security Group
    - name: security-group
      base:
        apiVersion: ec2.aws.crossplane.io/v1alpha1
        kind: SecurityGroup
        spec:
          forProvider:
            groupDescription: "Database security group"
            vpcId: vpc-12345
          providerConfigRef:
            name: aws-provider-config
      patches:
        - fromFieldPath: metadata.name
          toFieldPath: metadata.name
          toFieldPath: spec.forProvider.groupName

Practical Examples

Platform Team Setup

# Claim - User request
apiVersion: example.com/v1alpha1
kind: Database
metadata:
  name: my-production-db
  namespace: default
spec:
  size: large
  engine: postgres
  version: "14"
  storage: 100Gi

Composite with Multiple Resources

# Composition for Platform Team
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: platform-databases.example.com
spec:
  compositeTypeRef:
    apiVersion: example.com/v1alpha1
    kind: Database
  resources:
    # RDS Instance
    - name: database
      base:
        apiVersion: rds.aws.crossplane.io/v1beta1
        kind: DBInstance
        spec:
          forProvider:
            dbInstanceClass: db.t3.small
            engine: postgres
          providerConfigRef:
            name: aws-provider-config
      patches:
        - fromFieldPath: metadata.name
          toFieldPath: metadata.name
        - fromFieldPath: spec.size
          toFieldPath: spec.forProvider.dbInstanceClass

    # Subnet Group
    - name: subnet-group
      base:
        apiVersion: rds.aws.crossplane.io/v1alpha1
        kind: DBSubnetGroup
        spec:
          forProvider:
            description: "Subnet group for database"
            subnetIds: []
          providerConfigRef:
            name: aws-provider-config

    # Security Group
    - name: security-group
      base:
        apiVersion: ec2.aws.crossplane.io/v1alpha1
        kind: SecurityGroup
        spec:
          forProvider:
            groupDescription: "Database access"
            vpcId: vpc-0abc123
          providerConfigRef:
            name: aws-provider-config

GitOps Integration

# Install Crossplane with ArgoCD
argocd app create crossplane \
  --repo https://charts.crossplane.io/stable \
  --helm-chart crossplane \
  --helm-set "provider.packages={crossplane/provider-aws}"

# Apply XRDs and Compositions via Git
argocd app create platform-resources \
  --repo https://github.com/myorg/platform-config \
  --path ./crossplane \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace crossplane-system

Advanced Patterns

Environment-Specific Compositions

# Composition for Production
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: databases.production.example.com
  labels:
    environment: production
spec:
  compositeTypeRef:
    apiVersion: example.com/v1alpha1
    kind: Database
  environment:
    policy: SelectOne
    rules:
      - match:
          kind: Composition
        variables:
          - name: vpc-id
            value: vpc-prod-12345
          - name: enable-backups
            value: true
  resources:
    - name: database
      base:
        apiVersion: rds.aws.crossplane.io/v1beta1
        kind: DBInstance
      patches:
        - fromEnvironmentVariable:
            name: vpc-id
          toFieldPath: spec.forProvider.vpcId

Self-Service Portal

# Platform API exposed via Kubernetes
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: platforms.example.com
spec:
  group: example.com
  names:
    kind: Platform
    plural: platforms
  versions:
    - name: v1alpha1
      served: true
      referenceable: true
---
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: platforms.example.com
spec:
  compositeTypeRef:
    apiVersion: example.com/v1alpha1
    kind: Platform
  resources:
    - name: vpc
      base:
        apiVersion: ec2.aws.crossplane.io/v1alpha1
        kind: VPC
    - name: cluster
      base:
        apiVersion: eks.aws.crossplane.io/v1alpha1
        kind: Cluster
    - name: rds
      base:
        apiVersion: rds.aws.crossplane.io/v1beta1
        kind: DBCluster

Implementation Checklist

Setup Phase

  • Install Crossplane
  • Configure providers
  • Set up credentials

Platform Team

  • Define XRDs
  • Create Compositions
  • Test resource provisioning

User Experience

  • Create claims
  • Set up RBAC
  • Document usage

Summary

Crossplane transforms Kubernetes into a unified control plane:

  1. Kubernetes-native: Use familiar YAML patterns for cloud resources
  2. Composable: Build higher-level abstractions for teams
  3. Multi-cloud: Single tool for AWS, Azure, GCP
  4. GitOps-ready: Manage infrastructure through Git

Start with simple resources, then build composable abstractions as your platform matures.


External Resources

Comments