
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Crossplane: Kubernetes-Native Infrastructure extends your cluster’s control plane to manage external cloud resources like RDS instances, VPCs, and S3 buckets using standard kubectl commands. Instead of maintaining separate Terraform state files or clicking through cloud consoles, you define infrastructure as Kubernetes Custom Resources that reconcile continuously against provider APIs. This approach unifies application and infrastructure lifecycle management under a single GitOps workflow, eliminating configuration drift between your deployment manifests and actual cloud state.
What is Crossplane: Kubernetes-Native Infrastructure and how does it work?
At its core, Crossplane transforms Kubernetes from a container orchestrator into a universal control plane for all your infrastructure. When you adopt self-service infrastructure with Crossplane, you stop treating cloud provisioning as a separate CI/CD stage and start treating it as just another Kubernetes workload. The architecture relies on three distinct layers that separate concerns between platform engineers, developers, and cloud vendors.
The bottom layer consists of Managed Resources (MRs), which are high-fidelity representations of cloud provider primitives. A RDSInstance or S3Bucket CRD maps almost one-to-one with the underlying AWS API schema. Above this sits the Composite Resource Definition (XRD) layer, where platform teams create abstracted interfaces like XPostgreSQLDatabase that hide vendor lock-in and enforce organizational policies. Finally, Claims provide namespace-scoped access for application teams, allowing developers to request infrastructure without cluster-admin privileges or knowledge of underlying cloud topology.
How do you install and configure Crossplane providers on Kubernetes?
Getting started requires installing the Crossplane Helm chart and at least one provider. In production environments running on Amazon EKS, I recommend pinning specific versions rather than relying on latest tags to ensure reproducible deployments during disaster recovery scenarios.
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane crossplane-stable/crossplane \
--namespace crossplane-system \
--create-namespace \
--set args='--enable-environment-configs' \
--version 1.19.0 Once the core control plane is running, install providers as separate CRDs. Each provider runs as a pod within the cluster and handles authentication plus API translation for a specific vendor.
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-rds
spec:
package: xpkg.upbound.io/upbound/provider-aws-rds:v1.2.1
---
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: aws-default
spec:
credentials:
source: IRSA
region: ap-south-1 A common mistake in Nepal-based deployments or regions with intermittent connectivity is forgetting to configure provider-level timeouts and retry policies. Cloud APIs can throttle aggressively; without proper backoff configuration, your reconciliation loops may trigger rate limits that cascade across unrelated resources. Always set spec.controllerConfig with appropriate resource limits and environment variables for SDK tuning when operating outside major cloud regions.
Verifying provider health
After installation, confirm providers are healthy before attempting resource creation:
- Run
kubectl get providersand verify STATUS showsHealthy - Check provider pods in
crossplane-systemnamespace for restart counts - Validate IAM permissions using the provider's dry-run mode if available
- Review controller logs for authentication errors before proceeding
How do you create composite resources and compositions in Crossplane?
The real power of Crossplane: Kubernetes-Native Infrastructure emerges when you build abstractions over raw provider resources. Compositions let you bundle multiple managed resources into cohesive units that reflect your organization's actual service catalog rather than cloud vendor taxonomy.
Define an XRD first to establish the contract your development teams will consume:
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.com
spec:
group: database.example.com
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
storageGB:
type: integer
tier:
type: string
enum: [standard, performance]
required: [storageGB, tier] Then create a Composition that implements this interface using AWS primitives. Notice how patch sets transform abstract parameters into concrete provider configurations — this is where policy enforcement happens implicitly through structure rather than external validation webhooks.
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: aws-postgresql-standard
spec:
compositeTypeRef:
apiVersion: database.example.com/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: rds-instance
base:
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
engine: postgres
engineVersion: "16.2"
instanceClass: db.t3.medium
allocatedStorage: 20
skipFinalSnapshotBeforeDeletion: false
patches:
- fromFieldPath: spec.storageGB
toFieldPath: spec.forProvider.allocatedStorage
- fromFieldPath: metadata.annotations[crossplane.io/external-name]
toFieldPath: metadata.annotations[crossplane.io/external-name] For teams already practicing GitOps with ArgoCD, these YAML definitions live alongside application manifests in the same repository. ArgoCD syncs both app deployments and infrastructure claims in a single reconciliation cycle, guaranteeing that database provisioning completes before dependent services attempt connection.
Crossplane vs Terraform: Which should you choose for infrastructure automation?
This question dominates every platform engineering discussion in 2026. Both tools solve infrastructure-as-code problems but with fundamentally different operational models. Understanding these trade-offs prevents costly rework later.
| Criteria | Crossplane | Terraform |
|---|---|---|
| Control Model | Continuous reconciliation loop | Plan/apply imperative execution |
| State Storage | Kubernetes etcd + status fields | Remote backend (S3, Consul, etc.) |
| Drift Detection | Automatic, real-time correction | Manual plan required |
| RBAC Integration | Native Kubernetes RBAC | Separate IAM/policy system |
| Multi-tenancy | Namespace isolation built-in | Workspace/state file separation |
| Learning Curve | High (K8s API + CRDs + Compositions) | Moderate (HCL + modules) |
| Ecosystem Maturity | Growing rapidly, gaps exist | Mature, extensive module registry |
| Best For | Platform teams, GitOps-native orgs | Traditional IaC, multi-cloud scripts |
In practice, I recommend Crossplane when your team already operates Kubernetes competently and wants to unify application plus infrastructure lifecycles. Choose Terraform when managing heterogeneous environments where Kubernetes isn't the central abstraction, or when your team lacks deep K8s expertise. Many organizations successfully run both: Terraform for foundational networking and identity, Crossplane for developer-facing services atop that foundation.
Migration considerations
If migrating existing Terraform state to Crossplane, use the official import mechanisms rather than recreating resources. Crossplane supports adopting externally-created resources by annotating managed resources with their cloud provider IDs. This allows gradual migration without downtime or data loss, critical for production systems serving Nepali fintech or e-commerce platforms where maintenance windows are constrained.
How do you secure Crossplane deployments for compliance and audits?
Running infrastructure controllers inside your application cluster creates unique security challenges. Every provider pod has permissions to create, modify, and delete cloud resources — compromise means full cloud account takeover. Apply defense-in-depth principles consistently.
Never store long-lived cloud credentials as Kubernetes secrets. Use IRSA (AWS), Workload Identity (GCP), or Managed Identity (Azure) to bind provider service accounts to ephemeral, scoped credentials. Configure Kubernetes RBAC so developers can only create Claims in their own namespaces, never directly manipulate Managed Resources or ProviderConfigs. Implement OPA or Kyverno policies to reject compositions that violate security baselines — for example, blocking RDS instances without encryption or public accessibility.
For SOC 2 or ISO 27001 audits, Crossplane's declarative nature actually simplifies evidence collection. Your Git repository becomes the authoritative record of intended infrastructure state, while Kubernetes audit logs capture every mutation. Automate evidence extraction by querying resource statuses and reconciliation events, feeding them directly into compliance dashboards rather than manual screenshot collections.
Implementing Crossplane: Kubernetes-Native Infrastructure in Production
Adopting Crossplane: Kubernetes-Native Infrastructure pays dividends when your platform team commits to building genuine abstractions rather than exposing raw cloud APIs to developers. Start small: pick one high-friction resource type like databases or message queues, build a solid Composition with proper security guardrails, and prove the workflow with a single product team before expanding. Monitor reconciliation latency and provider health using Prometheus metrics exported by Crossplane controllers — silent failures in infrastructure reconciliation cause far worse outages than application bugs. If you're evaluating whether this approach fits your organization's maturity level and compliance requirements, reach out to discuss your specific infrastructure challenges.