Crossplane vs Terraform: Which Infrastructure as Code Tool is Best?
Infrastructure as code (IaC) tools have become essential for managing cloud and Kubernetes infrastructure. Two popular options are Crossplane and Terraform. But which one is best for your needs? Here we’ll compare the pros and cons of each.
Crossplane is an open source Kubernetes add-on that enables declarative management of infrastructure resources using Kubernetes custom resources. It builds on the Kubernetes control plane to unify infrastructure provisioning, management, and application deployments.
Terraform is a popular open source IaC tool from HashiCorp for defining, provisioning, and managing infrastructure safely and efficiently. It uses a declarative syntax to define resource dependencies so infrastructure can be easily provisioned and changed.
- Native Kubernetes integration — Crossplane is designed natively for Kubernetes while Terraform can be used independently or with its Kubernetes provider.
- Declarative syntax — Both use a declarative syntax but Crossplane’s is Kubernetes-native YAML while Terraform uses its own HCL syntax.
- Provisioning — Crossplane provisions resources via Kubernetes controllers while Terraform typically provisions directly via API/SDK.
- State — Terraform explicitly manages state while Crossplane relies on the declarative model and Kubernetes to handle it.
- Ecosystem — Terraform has a more mature provider ecosystem while Crossplane coverage is still expanding.
- Tight Kubernetes integration
- Leverages Kubernetes for scale and portability
- Unified control plane for infrastructure & apps
- Can extend with custom controllers/providers
- Very mature and proven tool
- Huge ecosystem of providers
- Battle-tested provisioning capabilities
- Customizable and extendable
Crossplane uses a Kubernetes-native architecture. It extends the Kubernetes control plane using Custom Resource Definitions (CRDs) and controllers. The Crossplane control plane monitors declarative infrastructure configs and reconciles desired state in the cloud.
The Crossplane architecture has four different components:
- Providers: Providers are the external entities that offer different resources such as storage, compute, DNS, networking, and so on. Some major cloud providers include AWS, Azure, and GCP. These providers are not part of the cluster, but Crossplane connects them with Kubernetes clusters to use their resources.
- Managed resources: Providers offer various resources that applications can use. When a resource is created and monitored through Crossplane, it’s considered a managed resource. Crossplane introduces this real-world infrastructure into the control plane to make it available as an extension to the Kubernetes API. A unique managed resource is created using the provider’s CRD. For instance, Crossplane builds a bucket managed resource inside the Kubernetes cluster connected to an Amazon S3 storage bucket using the AWS provider’s bucket CRD.
- Composite resources: A set of provisioned managed resources creates a composite resource. A unique abstraction or API is created by composing various resources, configurations, and policies together. This API is then made available to developers for self-service access to infrastructure. As composite resources are cluster-scoped, they are usually available to all cluster namespaces.
- Claims: Claims are the means through which a user interacts with Crossplane. When the user requires infrastructure for their application, they create a claim, and Crossplane works to provision that infrastructure for them.
Unlike Terraform, which has a Kubernetes provider to provision Kubernetes resources and is not inherently Kubernetes-centric, the main purpose of Crossplane is to extend the Kubernetes declarative API and control plane. This allows you to treat the external infrastructure and services as Kubernetes resources, enabling infrastructure as code practices and a Kubernetes-native experience. Crossplane empowers developers with self-service infrastructure provisioning, automation, and efficiency while leveraging Kubernetes’ ecosystem and tooling.
Terraform uses a direct model, communicating with providers and provisioning resources via API calls. The Terraform client parses and plans configs, executes changes via providers, and manages state.
There are three high-level components in Terraform’s architecture:
- Terraform Core: Written in the Go programming language, Terraform Core is a statically compiled binary. The Terraform CLI, which is the primary interface for Terraform users, is a compiled binary generated by Terraform Core. The Core is responsible for parsing the configuration files (containing infrastructure configuration), execution planning, resource provisioning, and resource state management.
- Providers: Terraform uses plugins called Terraform providers to interact with cloud providers, SaaS providers, and other APIs. The Terraform providers contain all the necessary logic to connect to specific services offered by different cloud providers. Before you can use them, you need to declare the providers you need in your Terraform configuration so that Terraform can install them. You can find all widely used Terraform providers, such as AWS, Azure, and Google Cloud, in the Terraform Registry.
- A state file: Terraform requires a state file to map physical resources to your configuration, enabling it to control and manage the infrastructure efficiently. This file, typically named
*.tfstate, stores metadata, resource details, current state, and dependencies. Keeping this file secure is crucial due to its sensitive information regarding the managed infrastructure.
Terraform enables infrastructure as code to manage the entire lifecycle of the infrastructure used in a particular project. IaC makes it much easier to provision and manage the infrastructure with the help of declarative language, making it more consistent, repeatable, and reliable. Using a configuration file, Terraform also allows different developers to work on the same file, making collaboration easier.
Crossplane configurations use Kubernetes YAML files to define resources like compute classes, bucket claims, etc. This aligns with Kubernetes workflow conventions.
Terraform uses HashiCorp Configuration Language (HCL) for a custom declarative syntax in
.tf files. This provides wide flexibility but requires learning a new config language.
Crossplane configurations can integrate nicely with Kubernetes CD pipelines using kubectl or Kubernetes APIs. No additional integration is needed.
Terraform can integrate with CI/CD using the
terraform CLI but requires configuring remote state storage and wrapping
terraform commands in scripts. Additional tools like Atlantis help streamline integration.
Crossplane leverages Kubernetes controllers to provision resources. Config changes trigger corresponding reconciliations. Errors surface as Kubernetes events.
Terraform directly provisions resources via API calls. Users execute
terraform apply to build/update infrastructure. Failed provisions surface as
Crossplane can be extended using Kubernetes operator SDKs or custom resource definers. This allows new managed resources.
Terraform can be customized via provider plugins. New providers expand integrations while provider wrappers modify existing behavior.
Templating & Reuse
Crossplane composes resources using Kubernetes native templating like helm charts or kustomize.
Terraform enables reuse through modules. Modules can be parameterized and published for team sharing.
Which is Better?
For Kubernetes-centric workflows, Crossplane is likely the better choice. It leans heavily into Kubernetes abstractions and may offer a more natural developer experience in container environments.
For general IaC or multi-platform portability, Terraform still has the edge. Its maturity, provider ecosystem and wide user base make it versatile for many infrastructure use cases.
In reality, the two can complement each other in modern infrastructure stacks. For example, Terraform can handle general infrastructure while Crossplane focuses on Kubernetes-native concerns.
Overall there’s no universally better option. Evaluate each tool’s strengths and benefits for your particular use case to choose the best IaC solution.