Self-Service Infrastructure with Crossplane

Khimananda Oli 8 min read Virtualization
Self-Service Infrastructure with Crossplane

By Khimananda Oli | Last reviewed: August 2026

Platform engineering teams face a persistent bottleneck: developers need cloud resources fast, but granting direct console access creates security risks and configuration drift. Self-service infrastructure with Crossplane solves this by exposing managed cloud services as native Kubernetes APIs, allowing application teams to provision databases, caches, and storage through standard kubectl commands or GitOps workflows. This approach shifts infrastructure from a ticket-based gatekeeper model to a scalable, policy-enforced product that aligns with how modern engineering teams actually work.

What is self-service infrastructure with Crossplane and why use it?

Crossplane extends Kubernetes to manage external infrastructure by treating cloud provider APIs as reconciled resources. Unlike traditional Infrastructure as Code tools that run imperatively during deployment, Crossplane operates on a continuous control loop. If someone manually changes an RDS instance parameter in the AWS console, Crossplane detects the drift and reverts it to match the declared state. For teams already running GitOps with ArgoCD for declarative Kubernetes deployments, this means infrastructure lifecycle management uses the exact same workflow as application deployments.

Developerkubectl / GitOpsClaim (XRC)Kubernetes APICrossplane CoreXRD + CompositionProvider ControllersDrift DetectionAWS ProviderRDS / S3 / IAMAzure ProviderAKS / Blob / SQL
Self-service infrastructure with Crossplane architecture: developers interact only with the Kubernetes API, while Crossplane reconciles claims against cloud providers

The critical distinction is the abstraction layer. Platform engineers define Composite Resource Definitions (XRDs) that expose only the parameters developers should touch—database size, engine version, backup retention—while hiding VPC IDs, subnet selection, and IAM role wiring. This prevents the "too many knobs" problem that plagues direct Terraform module usage. When combined with AWS IAM best practices for least-privilege access, you get a system where developers can self-serve without ever holding long-lived cloud credentials.

How do you configure Composite Resource Definitions for safe developer abstractions?

XRDs are the contract between platform teams and application developers. A well-designed XRD exposes intent, not implementation. In practice, I start by identifying the 3–5 parameters that actually vary per environment, then hardcode everything else in the Composition. Here's a production-grade PostgreSQL claim definition:

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xpostgresqlinstances.db.example.com
spec:
  group: db.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
                  minimum: 20
                  maximum: 500
                  description: "Allocated storage in gigabytes"
                engineVersion:
                  type: string
                  enum: ["14", "15", "16"]
                  default: "16"
                tier:
                  type: string
                  enum: ["dev", "staging", "production"]
                  description: "Environment tier determines HA and backup config"
              required:
                - storageGB
                - tier

Notice the constraints: storage has min/max bounds, engine versions are enumerated, and the tier field drives implicit configuration. Developers never see subnet IDs or security group rules. The corresponding Composition maps these fields to actual AWS RDS resources while injecting platform-managed defaults like encryption keys, monitoring agents, and tagging standards. Always validate XRDs in a staging cluster before promoting; a malformed schema can block all claims in that API group.

Testing XRDs locally before cluster deployment

Use crossplane beta render to dry-run compositions without a live cluster. This catches composition logic errors and missing patches early:

crossplane beta render xr.yaml composition.yaml functions/ \
  --output yaml > rendered-output.yaml

This command outputs the fully-rendered managed resources that would be created. Review them for correct tagging, proper secret references, and expected parameter mapping. Integrate this step into your CI pipeline alongside CI/CD best practices for small teams to prevent broken abstractions from reaching production.

How does Crossplane compare to Terraform for internal developer platforms?

Teams evaluating self-service infrastructure with Crossplane inevitably ask whether to replace existing Terraform workflows. The answer depends on your operational model, not technical superiority. Both tools solve infrastructure provisioning, but they optimize for different personas and feedback loops.

CriteriaCrossplaneTerraform
Control PlaneKubernetes API (continuous reconciliation)CLI / CI job (plan/apply cycles)
Drift RemediationAutomatic, continuousManual or scheduled plan detection
Developer Interfacekubectl, Helm, ArgoCD, KustomizeHCL modules, Atlantis, Spacelift
State ManagementKubernetes etcd + provider statusRemote backend (S3, Consul, TF Cloud)
Abstraction ModelXRD + Composition (API-first)Modules + Variables (config-first)
Multi-Provider OrchestrationNative single control planeWorkspace/module composition
Learning Curve for DevsLow if K8s-nativeModerate (new DSL + workflow)

In my experience, Crossplane wins when your team already lives in Kubernetes and wants infrastructure to behave like a platform API. Terraform remains superior for complex multi-cloud networking, legacy brownfield migrations, or teams without dedicated platform engineers. Many organizations successfully run both: Terraform for foundational networking and cluster bootstrapping, Crossplane for application-layer self-service above that foundation.

Terraform WorkflowWrite HCLPlanApplyEpisodic • Human-triggered • Drift until next applyCrossplane WorkflowSubmit ClaimReconcileObserveContinuous • Auto-drift correction • Always convergingWhen to Choose WhichTerraform: Foundation, networking, brownfield, no K8s expertiseCrossplane: App-layer self-service, K8s-native teams, GitOps alignment
Terraform operates in episodic plan-apply cycles while Crossplane continuously reconciles desired state, making it better suited for self-service infrastructure with ongoing drift protection

How do you secure self-service infrastructure with Crossplane in production?

Security in self-service infrastructure with Crossplane hinges on three layers: RBAC scoping, provider credential isolation, and policy enforcement. Never give developers direct access to managed resource kinds like RDSInstance. Instead, grant permissions only to your custom XRD claim types. This ensures all provisioning flows through your validated Composition logic.

  1. Namespace-scoped RBAC: Bind developer roles to specific namespaces. Use Kubernetes ServiceAccounts tied to CI pipelines rather than shared kubeconfig files. Each team gets its own namespace with claims restricted to their XRD types.
  2. Provider Config isolation: Create separate ProviderConfigs per environment or team boundary. Store credentials in external secret stores (AWS Secrets Manager, HashiCorp Vault) referenced via the External Secret Store plugin. Never embed credentials in ProviderConfig manifests.
  3. Policy-as-code validation: Deploy Kyverno or OPA Gatekeeper to enforce tagging standards, region restrictions, and cost guardrails at admission time. Reject claims that exceed budget thresholds or violate compliance requirements before they reach the controller.
  4. Audit trail automation: Enable Crossplane's built-in event logging and forward to your observability stack. Every reconcile action, status change, and error generates structured events. For SOC 2 environments, map these events to control evidence automatically.

A common mistake is over-permissioning the Crossplane provider service account. Follow the principle of least privilege: if your Composition only creates RDS instances and S3 buckets, the provider IAM role should have zero EC2 or Lambda permissions. Test permission boundaries by attempting forbidden operations in staging first.

How do you integrate Crossplane with existing GitOps and monitoring stacks?

Crossplane's Kubernetes-native design makes GitOps integration straightforward. Store XRDs, Compositions, and ProviderConfigs in your infrastructure repo alongside application manifests. ArgoCD or Flux manages the platform layer; developers submit claims through PRs to their application repos. This separation keeps platform evolution controlled while enabling developer autonomy within defined boundaries.

For observability, deploy the prometheus-operator service monitor for Crossplane metrics. Key alerts include high reconcile error rates, long sync durations, and provider authentication failures. Pair this with monitoring with Prometheus and Grafana dashboards that track claim fulfillment SLAs and resource utilization trends. When building infrastructure as code foundations, ensure your monitoring covers both the provisioning layer and the resulting managed resources.

Infra RepoXRDs, CompositionsProviderConfigsApp RepoClaims (XRCs)App ManifestsArgoCD / FluxSync PlatformSync ClaimsCrossplaneReconcile LoopStatus UpdatesPrometheusMetrics + AlertsFeedback Loop
GitOps integration for self-service infrastructure with Crossplane: ArgoCD syncs platform and app repos separately, while Prometheus provides continuous feedback on reconciliation health

Handling secrets and connection strings securely

Crossplane writes connection details to Kubernetes Secrets by default. For production, configure the External Secret Store plugin to write directly to AWS Secrets Manager or Vault instead. This prevents sensitive credentials from appearing in etcd backups or kubectl get secret output. Reference these external secrets in your application pods using CSI drivers or secret injection operators. Always rotate provider credentials independently of claim lifecycles.

Implementing Self-Service Infrastructure with Crossplane Successfully

Start small: pick one resource type (typically PostgreSQL or Redis) and one team as early adopters. Build the XRD, Composition, and RBAC bindings together with that team's input. Measure time-to-provision before and after; real adoption requires demonstrable velocity gains. Scale gradually, adding resource types based on actual demand signals rather than speculative completeness.

If your organization needs help designing compliant, developer-friendly platform abstractions or auditing existing Crossplane deployments for security gaps, reach out to discuss your infrastructure platform strategy. Getting the abstraction boundaries right early prevents costly rework and developer trust erosion later.

Frequently Asked Questions

It enables developers to provision cloud resources via Kubernetes manifests without direct console access, using Crossplane as a control plane to abstract provider APIs into reusable platform abstractions.

Crossplane runs continuously in-cluster as a controller, enabling GitOps-native reconciliation and real-time drift detection, unlike Terraform’s CLI-driven, state-file-dependent apply cycles that require external automation for self-service workflows.

Crossplane v1.18 is the current stable release supporting production-grade self-service infrastructure with improved composition functions, provider config caching, and enhanced RBAC integration for multi-tenant platforms.

Yes, through internal developer portals like Backstage or custom CLIs that generate Kubernetes manifests, allowing teams unfamiliar with YAML to request infrastructure via forms while Crossplane handles provisioning behind the scenes.

Enforce namespace-scoped RBAC, use ProviderConfig per team with least-privilege cloud IAM roles, and validate compositions with OPA/Gatekeeper policies to prevent unauthorized resource creation or configuration drift.

Overly granular compositions that expose raw provider fields, missing resource quotas, inadequate error messaging in composite resources, and neglecting to test upgrade paths for providers and Crossplane itself during platform updates.

Typically two to four weeks for a minimal viable platform including provider installation, base compositions, RBAC scaffolding, and CI integration, depending on team familiarity with Kubernetes controllers and cloud API modeling.

Indirectly, by enforcing standardized resource sizes, auto-tagging for chargeback, and preventing shadow IT through governed provisioning, though savings depend on policy enforcement maturity and developer adoption of approved templates.

Inspect CompositeResource and managed resource status conditions via kubectl, check crossplane-controller logs for reconciliation errors, and validate provider credentials and API quotas using cloud CLI tools against the failing resource spec.

Yes, using the import annotation on managed resources to adopt pre-existing infrastructure into Crossplane’s control loop, enabling gradual migration of legacy assets into self-service compositions without recreation or downtime.

Track reconciliation latency, provider API error rates, composite resource readiness, and controller memory usage via Prometheus exporters bundled with Crossplane v1.18 to detect bottlenecks before they impact developer experience.

Use external secret stores like Vault or AWS Secrets Manager via the External Secret Store feature, avoiding Kubernetes Secrets for sensitive provider credentials and injecting runtime secrets into composed resources securely.

Only if already running Kubernetes; otherwise, the operational overhead outweighs benefits. Small teams should consider simpler PaaS options first and adopt Crossplane when multi-cloud governance or platform scaling justifies complexity.

Package compositions as OCI images using crossplane xpkg build, tag with semantic versions, and distribute via private registries to enable safe rollbacks and audit trails across environment promotions.

Basic Kubernetes manifest literacy, understanding of composite vs managed resources, and familiarity with your platform’s specific XRD schemas; deep Crossplane internals are unnecessary when abstractions are well-designed and documented.