Infrastructure Provisioning with Crossplane
Providers & Managed Resources
4 min read
Providers are the heart of Crossplane, connecting to cloud APIs and managing infrastructure resources. Understanding how to configure providers and work with managed resources is essential for building your platform.
Provider Types
Crossplane supports providers for major cloud platforms and services:
# Available Provider Categories
providers:
cloud_platforms:
- name: provider-aws
resources: "EC2, RDS, S3, VPC, EKS, Lambda, etc."
package: xpkg.upbound.io/upbound/provider-family-aws
- name: provider-gcp
resources: "Compute, CloudSQL, GCS, VPC, GKE, etc."
package: xpkg.upbound.io/upbound/provider-family-gcp
- name: provider-azure
resources: "VMs, SQL, Storage, VNet, AKS, etc."
package: xpkg.upbound.io/upbound/provider-family-azure
kubernetes:
- name: provider-kubernetes
resources: "Deployments, Services, ConfigMaps, etc."
use_case: "Deploy apps alongside infrastructure"
- name: provider-helm
resources: "Helm releases"
use_case: "Deploy Helm charts as part of compositions"
other:
- name: provider-terraform
use_case: "Use Terraform modules in Crossplane"
- name: provider-sql
use_case: "Manage databases, users, grants"
Installing Multiple Providers
For a real platform, you'll need multiple providers:
# providers.yaml - Install AWS family providers
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-ec2
spec:
package: xpkg.upbound.io/upbound/provider-aws-ec2:v1.1.0
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-rds
spec:
package: xpkg.upbound.io/upbound/provider-aws-rds:v1.1.0
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-s3
spec:
package: xpkg.upbound.io/upbound/provider-aws-s3:v1.1.0
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-iam
spec:
package: xpkg.upbound.io/upbound/provider-aws-iam:v1.1.0
# Apply all providers
kubectl apply -f providers.yaml
# Wait for providers to be healthy
kubectl wait provider --all --for=condition=Healthy --timeout=300s
# List installed providers
kubectl get providers
# NAME INSTALLED HEALTHY PACKAGE AGE
# provider-aws-ec2 True True xpkg.upbound.io/upbound/provider-aws-ec2:v1.1.0 2m
# provider-aws-rds True True xpkg.upbound.io/upbound/provider-aws-rds:v1.1.0 2m
# provider-aws-s3 True True xpkg.upbound.io/upbound/provider-aws-s3:v1.1.0 2m
# provider-aws-iam True True xpkg.upbound.io/upbound/provider-aws-iam:v1.1.0 2m
Provider Configuration Options
Configure credentials securely:
# Option 1: Secret-based credentials (development)
---
apiVersion: v1
kind: Secret
metadata:
name: aws-creds
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-creds
key: credentials
---
# Option 2: IRSA (production - AWS)
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: IRSA
---
# Option 3: Workload Identity (production - GCP)
apiVersion: gcp.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
projectID: my-gcp-project
credentials:
source: InjectedIdentity
---
# Option 4: Multiple configurations (multi-account)
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: production
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-creds-prod
key: credentials
---
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: development
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-creds-dev
key: credentials
Managed Resource Examples
RDS Database
# rds-instance.yaml
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
metadata:
name: production-postgres
spec:
forProvider:
region: us-east-1
allocatedStorage: 20
autoMinorVersionUpgrade: true
backupRetentionPeriod: 7
backupWindow: "03:00-04:00"
dbInstanceClass: db.t3.micro
dbName: appdb
engine: postgres
engineVersion: "15.4"
instanceIdentifier: production-postgres
maintenanceWindow: "Mon:04:00-Mon:05:00"
multiAz: false
passwordSecretRef:
key: password
name: db-password
namespace: default
publiclyAccessible: false
skipFinalSnapshot: true
storageEncrypted: true
storageType: gp3
username: dbadmin
vpcSecurityGroupIdRefs:
- name: db-security-group
dbSubnetGroupNameRef:
name: db-subnet-group
providerConfigRef:
name: default
writeConnectionSecretToRef:
name: postgres-connection
namespace: default
VPC with Subnets
# vpc.yaml
apiVersion: ec2.aws.upbound.io/v1beta1
kind: VPC
metadata:
name: platform-vpc
spec:
forProvider:
region: us-east-1
cidrBlock: 10.0.0.0/16
enableDnsHostnames: true
enableDnsSupport: true
tags:
Name: platform-vpc
Environment: production
providerConfigRef:
name: default
---
# subnet.yaml
apiVersion: ec2.aws.upbound.io/v1beta1
kind: Subnet
metadata:
name: platform-subnet-a
spec:
forProvider:
region: us-east-1
availabilityZone: us-east-1a
cidrBlock: 10.0.1.0/24
vpcIdRef:
name: platform-vpc
mapPublicIpOnLaunch: false
tags:
Name: platform-subnet-a
providerConfigRef:
name: default
S3 Bucket with Encryption
# s3-bucket-secure.yaml
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
name: app-data-bucket
spec:
forProvider:
region: us-east-1
tags:
Environment: production
providerConfigRef:
name: default
---
apiVersion: s3.aws.upbound.io/v1beta1
kind: BucketServerSideEncryptionConfiguration
metadata:
name: app-data-bucket-encryption
spec:
forProvider:
region: us-east-1
bucketRef:
name: app-data-bucket
rule:
- applyServerSideEncryptionByDefault:
- sseAlgorithm: AES256
---
apiVersion: s3.aws.upbound.io/v1beta1
kind: BucketVersioning
metadata:
name: app-data-bucket-versioning
spec:
forProvider:
region: us-east-1
bucketRef:
name: app-data-bucket
versioningConfiguration:
- status: Enabled
---
apiVersion: s3.aws.upbound.io/v1beta1
kind: BucketPublicAccessBlock
metadata:
name: app-data-bucket-public-access
spec:
forProvider:
region: us-east-1
bucketRef:
name: app-data-bucket
blockPublicAcls: true
blockPublicPolicy: true
ignorePublicAcls: true
restrictPublicBuckets: true
Connection Secrets
Crossplane can write connection details to Kubernetes Secrets:
# Resource with connection secret
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
metadata:
name: my-database
spec:
forProvider:
# ... configuration
writeConnectionSecretToRef:
name: db-connection-secret
namespace: default
---
# The resulting secret contains:
# apiVersion: v1
# kind: Secret
# metadata:
# name: db-connection-secret
# data:
# endpoint: <base64-encoded-endpoint>
# port: <base64-encoded-port>
# username: <base64-encoded-username>
# password: <base64-encoded-password>
# View connection details
kubectl get secret db-connection-secret -o yaml
# Use in your application
kubectl get secret db-connection-secret -o jsonpath='{.data.endpoint}' | base64 -d
Resource References
Link resources together using references:
# Reference patterns
references:
# By name (in same namespace)
vpcIdRef:
name: my-vpc
# By selector (match labels)
vpcIdSelector:
matchLabels:
environment: production
team: platform
# By external name (existing resource)
vpcId: vpc-0123456789abcdef0
# Secret reference (for sensitive values)
passwordSecretRef:
key: password
name: db-credentials
namespace: crossplane-system
# Example: Security group referencing VPC
apiVersion: ec2.aws.upbound.io/v1beta1
kind: SecurityGroup
metadata:
name: db-security-group
spec:
forProvider:
region: us-east-1
description: "Database security group"
vpcIdRef:
name: platform-vpc # References the VPC by name
ingress:
- fromPort: 5432
toPort: 5432
protocol: tcp
cidrBlocks:
- 10.0.0.0/16
tags:
Name: db-security-group
Observing Resources
Monitor your managed resources:
# List all managed resources
kubectl get managed
# Check specific resource type
kubectl get instance.rds.aws.upbound.io
# Watch resource status
kubectl get bucket -w
# Get detailed status
kubectl describe instance.rds.aws.upbound.io my-database
# Check events
kubectl get events --field-selector involvedObject.name=my-database
# View Crossplane logs for debugging
kubectl logs -n crossplane-system -l pkg.crossplane.io/provider=provider-aws-rds
In the next lesson, we'll build on these fundamentals to create Compositions and XRDs—the key to self-service infrastructure. :::