This article will compare Terraform and Kubernetes, two of the most dominant tools in the cloud infrastructure space. Although they share some similarities, they are built to serve different purposes.
Terraform is a tool for provisioning and managing infrastructure as code, such as servers, databases, and networking across multiple cloud providers. Kubernetes is a container orchestration platform that manages the deployment, scaling, and operation of containerized applications.
Terraform builds the infrastructure where Kubernetes might run. Kubernetes then manages application workloads on that infrastructure. They often work together but solve different layers of the stack.
We will briefly take a look at each one of them and discuss their similarities and differences.
To learn more about these two foundational cloud infrastructure technologies, check the multiple tutorials on Spacelift’s blog around Kubernetes and Terraform.
How we compared these platforms
We aim to make our recommendations practical and vendor-neutral. We based this comparison on each vendor’s public documentation and pricing pages, hands-on experience using both tools, and the dimensions that matter most in practice.
What is Terraform?
Terraform is a tool that allows us to safely and predictably manage infrastructure at scale using cloud-agnostic and infrastructure as code principles. It is developed by HashiCorp and enables infrastructure provisioning both in the cloud and on-premises.
Terraform is written in the declarative configuration language HashiCorp Configuration Language (HCL) and facilitates the automation of infrastructure management across any environment. It allows IT professionals to collaborate and perform changes safely on cloud environments and scale them on demand according to the business needs.
Modules provide excellent reusability and code-sharing opportunities to boost the collaboration and productivity of teams operating on the cloud. Providers are plugins that offer integration and interaction with different APIs and are one of the main ways to extend Terraform’s functionality.
Terraform maintains an internal state of the managed infrastructure, including resources, configurations, metadata, and their relationships. The state is actively maintained by Terraform and used to create plans, track changes, and modify infrastructure environments. The state should be stored remotely to allow teamwork and collaboration as a best practice.
The core Terraform workflow consists of three concrete stages. First, we generate the infrastructure as code configuration files representing our environment’s desired state. Next, we check the output of the generated plan based on our manifests. After carefully reviewing the changes, we apply the plan to provision infrastructure resources.

Note: Terraform releases up to and including 1.5.x remain open source under the Mozilla Public License 2.0 (MPL 2.0). In August 2023, HashiCorp moved later releases to the Business Source License (BSL, also written BUSL), and IBM completed its acquisition of HashiCorp in February 2025.
OpenTofu is the open-source fork created in response. It started from the last MPL-licensed Terraform release, shipped its first stable version (1.6.0) in January 2024 with backward compatibility to Terraform 1.5.x, and is now an MPL 2.0 project under the Linux Foundation and the CNCF. Since the fork it has added features the open Terraform binary does not include, such as native state encryption and ephemeral values.
What is Kubernetes?
Kubernetes (K8s) is an open-source system for container orchestration, automating deployments, and managing containerized apps. Its orchestration model lets applications scale and achieve high availability. It was originally designed by Google, drawing on its experience running critical workloads in production, and is now maintained by the Cloud Native Computing Foundation (CNCF).
Kubernetes strives to be cloud agnostic at its core, providing great flexibility in running workloads across cloud and on-premises environments. Additionally, it is designed with extensibility in mind, allowing you to easily add features and custom tooling to clusters.
One of its main benefits is its self-healing capabilities. Containers that fail are automatically restarted and rescheduled, nodes can be configured to be automatically replaced, and traffic is served only by healthy components based on health checks.
Rollouts are handled progressively, and Kubernetes provides smart mechanisms to monitor application health during deployments. Rolling back problematic changes happens automatically if the application health doesn’t report a healthy status after a new deployment. Keeping the application running while rolling out new software versions has been a hot topic in the Kubernetes ecosystem over the past years, with many possible deployment strategies.
Kubernetes handles service discovery and load-balances traffic between similar pods natively without the need for complex external solutions. It has extendable built-in mechanisms to manage configuration and secrets for your applications. Scaling your applications has never been easier since it provides autoscaling options, scaling through commands, or via a UI.
Kubernetes provides a cluster of nodes, a group of worker machines that run containerized applications. Each node hosts pods that hold application workload containers. The brain of the whole system is the control plane. Each cluster consists of several components that manage the worker nodes and pods and guarantee operational continuity:
- The API server is the component that exposes the Kubernetes API and serves as the front-end of the control plane, handling all communication between the other parts.
- The etcd component is used to store all cluster data and state.
- The scheduler manages how pods are assigned to nodes and takes all the workload scheduling decisions.
- The controller manager components run different controller processes to ensure that the cluster’s desired state matches its current state.
- The cloud controller manager integrates Kubernetes clusters with external cloud providers, embeds their logic, and links the Kubernetes API with the Cloud Provider’s API.
- On each node, the kubelet is the agent responsible for running containers in pods, and kube-proxy is the component that adds the necessary networking capabilities for communication between pods and nodes.

Check out this article to learn more about the Key Kubernetes Cluster Components.
Differences between Terraform and Kubernetes
These two modern technologies have many similarities but also fundamental differences.
Terraform is an infrastructure provisioning tool, while Kubernetes is a container orchestration platform. They are often used together, with Terraform setting up infrastructure and Kubernetes managing application-level operations.
Understanding their distinction is key in DevOps workflows that require both infrastructure provisioning and application orchestration.
Let’s look into them in more detail.
| Terraform | Kubernetes | |
| Category | Infrastructure as code (IaC) provisioning | Container orchestration |
| What it manages | Cloud and on-premises resources: servers, networks, databases, and clusters | Containerized application workloads |
| Configuration language | HCL | YAML or JSON manifests |
| State model | Explicit state file that reconciles desired and actual infrastructure | Continuous reconciliation by controllers, with cluster state stored in etcd |
| Drift handling | Native plan and apply surfaces drift before changes are applied | Continuously reconciles to desired state, with no built-in pre-change plan or diff |
| Place in the stack | Builds the platform, including the Kubernetes cluster itself | Runs and scales applications on the platform |
| Licensing | BSL for current releases; 1.5.x and earlier are MPL 2.0, and OpenTofu is the MPL 2.0 fork | Open source under Apache 2.0, CNCF-governed |
| Typical users | Platform, DevOps, and cloud engineers | Platform, DevOps, and site reliability engineers |
1) Area of focus
First and foremost, Terraform and Kubernetes serve different purposes and solve different problems. Terraform focuses on provisioning infrastructure components and targets the Infrastructure as Code space. Kubernetes aims to enable us to run container workloads and targets the container orchestration space.
2) Configuration language and CLI
Manifests in Terraform are written in HCL language, while in Kubernetes in YAML or JSON. Each tool has its own command line utility and tool-specific internals to understand before being productive.
3) Tool workflow
The Terraform workflow is generally considered easy to understand and provides a welcoming experience for new users. On the other hand, to be effective in running applications in Kubernetes, one has to understand a lot of cluster internal components and mechanics, and usually, it takes more time for users to get up to speed with Kubernetes.
4) Configuration drift and planning phase
Terraform provides a native way to detect and notify you of configuration drift and unwanted changes by leveraging the planning phase of its typical workflow. In contrast, Kubernetes doesn’t support this functionality out of the box.
5) State management
Both tools track state, but they treat it differently. Terraform keeps an explicit state file that it compares against your configuration on every plan, so you review proposed changes before anything happens.
Kubernetes stores cluster state in etcd and runs a continuous reconciliation loop, with controllers working to match the running state to the desired state without a separate review step. One model asks you to approve changes up front, the other applies them and keeps correcting.
6) Lifecycle scope
Terraform is strongest at day-one provisioning and controlled day-two changes: create a resource, change it, destroy it. Kubernetes is built for continuous day-two operations. It keeps applications running, scales them under load, replaces failed nodes, and rolls out new versions while the service stays up.
Kubernetes vs Terraform: Similarities
1) Both live in the DevOps toolchain
Both tools operate in the DevOps space and are typically set up and configured by the same type of IT practitioners: Site Reliability, DevOps, and Cloud engineers.
2) Cloud agnostic
Both tools take a similar approach to staying as cloud, platform, and API agnostic as possible, so they can run workloads across different environments, and both have mature, actively maintained integrations with the most common cloud providers.
Their licensing now differs, though. Kubernetes is open source under the Apache 2.0 license and governed by the CNCF. Terraform’s current releases are under the Business Source License (BSL); only version 1.5.x and earlier remain open source, with OpenTofu carrying that open-source lineage forward under the MPL 2.0.
3) Declarative configuration
Although they use different languages, Terraform and Kubernetes take a similar conceptual approach to define the configuration. The manifests in both tools are written in a declarative style.
4) State and reconciliation
The notion of the state exists in both tools, although it is implemented differently. Terraform and Kubernetes apply some logic to reconcile the desired state configured in declarative configuration files with the running state.
5) Extensible by design
Both tools are highly extensible through external plugins, API integrations, or custom resources, as needed.
6) Built for scale
Terraform and Kubernetes are battle-tested technologies that can support huge scale since they are designed and architected with scaling considerations for modern cloud-native environments.
7) Fit for CI/CD pipelines
Since both Terraform and Kubernetes offer highly automatable workflows, they can be integrated and combined with CI/CD pipelines to automate their lifecycle.
Kubernetes and Terraform synergies
By decomposing all the information we discussed, we realize that Kubernetes and Terraform complement each other, as they operate at different levels and can be used in parallel.
A typical model adopted by cloud practitioners is to use Terraform to provision infrastructure resources (e.g., Kubernetes clusters) and Kubernetes to manage containerized apps running on those clusters.
Terraform’s approach simplifies and standardizes the complex task of provisioning Kubernetes clusters. Terraform, in this case, enables a unified flow for provisioning Kubernetes clusters across providers with a declarative approach that is preferred over command line utilities. This approach works great, but users must use separate flows to manage infrastructure and application resources.
Another approach is to use Terraform to manage Kubernetes-specific application components as well. This model has the advantage of adding the Terraform workflow to Kubernetes components. This way, IT operators can detect configuration drift on Kubernetes and manage infrastructure and application resources with the same workflow and configuration language.
This approach has a significant disadvantage since Terraform requires a well-defined schema for each managed resource. Thus each Kubernetes resource needs to be translated into a Terraform schema to be available. This dependency makes maintaining Kubernetes resources through Terraform cumbersome at times.
Do you need both Terraform and Kubernetes?
Usually, yes. The two tools cover different layers, so they complement each other more often than they compete. A common pattern is to provision the cluster and its supporting cloud resources with Terraform, then deploy and scale your containerized applications on that cluster with Kubernetes.
You can run Kubernetes without Terraform, and you can use Terraform without ever touching Kubernetes, but teams running containerized workloads in the cloud tend to reach for both.
Kubernetes Cloud Operators
Kubernetes Cloud Operators manage, configure, and integrate cloud-specific resources with a Kubernetes cluster. Cloud providers usually develop these operators to facilitate integrations with their respective services.
They facilitate the following use cases:
- Service provisioning: You can automatically provision services required by your microservices. For example, if your application requires a database, you can use a k8s operator to provide the service for you.
- Secrets integrations: When you are working with k8s, you will most likely have many configmaps and secrets defined. Sometimes, sharing these secrets on some of your infrastructure resources can be tricky. By using operators, this becomes easier as you can seamlessly integrate your k8s resources with your secrets management tool.
- GitOps workflows: Using operators in the cloud context, can facilitate your GitOps workflow, as you will declare both your infrastructure and the applications in the same way
There are a couple of advantages of using Kubernetes Cloud Operator, but there are many downsides to using them too. The downsides are:
- Limited service coverage – Terraform providers are always close to supporting absolutely anything that a cloud provider supports due to the extensive work of the community. When it comes to k8s cloud operators, they don’t have such a big community backing them up, and sometimes, for specific services, only some basic operations are available, requiring fallback to other services/methods.
- Troubleshooting complexity – Using k8s cloud operators increases the troubleshooting complexity. This happens because you will not only need to troubleshoot your code and the resource you are provisioning but the operator itself too, which will be harder to do.
- Learning curve – Terraform is more popular among DevOps engineers than k8s cloud operators are. Managing infrastructure resources via k8s will steepen the learning curve.
- Vendor lock-in – By managing your infrastructure with a k8s cloud operator, will tie your infrastructure to a cloud provider and migrating will be harder to do than by using Terraform.
- Maturity – Some k8s cloud operators are newer and might not be as stable as tools such as Terraform, Pulumi, or CloudFormation.
Some popular Cloud Operators provided by major cloud providers are:
Building an AWS infrastructure by using Terraform and AWS Controllers for Kubernetes (ACK)
AWS ACK configuration
AWS ACK can be deployed on any k8s cluster, and for this example, I will be using an EKS cluster.
The recommended way to install an ACK Service Controller is by using Helm.
I already have the EKS cluster deployed, so the next step would be to deploy the S3 ACK service controller.
This is done by logging into the ecr public registry, getting the correct helm chart for your service, and running helm install, similar to the commands below:
export SERVICE=s3
export RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/${SERVICE}-controller/releases/latest | jq -r '.tag_name | ltrimstr("v")')
export ACK_SYSTEM_NAMESPACE=ack-system
export AWS_REGION=us-west-2
aws ecr-public get-login-password --region us-east-1 | helm registry login --username AWS --password-stdin public.ecr.aws
helm install --create-namespace -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller \
oci://public.ecr.aws/aws-controllers-k8s/$SERVICE-chart --version=$RELEASE_VERSION --set=aws.region=$AWS_REGIONYou can check the status of the controller by running:
kubectl --namespace ack-system get pods -l "app.kubernetes.io/instance=ack-s3-controller"
NAME READY STATUS RESTARTS AGE
ack-s3-controller-s3-chart-646b5bd457-vbvxb 1/1 Running 0 11sNow, ACK is deployed, but we still need to configure it before we are able to use it.
The next step refers to configuring IAM Roles for Service Accounts (IRSA).
First, ensure you have eksctl installed on your machine. Check out this guide to see how to install it.
Create an OpenID Connect (OIDC) identity provider for your EKS cluster:
export EKS_CLUSTER_NAME=<eks cluster name>
export AWS_REGION=<aws region id>
eksctl utils associate-iam-oidc-provider --cluster $EKS_CLUSTER_NAME --region $AWS_REGION --approveNext, create a bash script based on this and run it. This will create an IAM role for your ACK service controller. You will also need to attach an IAM policy to that role. For that, you can create another bash script based on this and run it. The policy can be changed to satisfy your needs.
Associate the IAM role you’ve created with the ACK service account like so:
IRSA_ROLE_ARN=eks.amazonaws.com/role-arn=$ACK_CONTROLLER_IAM_ROLE_ARN kubectl annotate serviceaccount -n $ACK_K8S_NAMESPACE $ACK_K8S_SERVICE_ACCOUNT_NAME $IRSA_ROLE_ARNTo ensure that everything will work properly, You will also need to create a cluster role and cluster role binding for the leases.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ack-s3-controller-leader-election
rules:
- apiGroups:
- "coordination.k8s.io"
resources:
- "leases"
verbs:
- "get"
- "list"
- "watch"
- "create"
- "update"
- "delete"apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ack-s3-controller-leader-election-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ack-s3-controller-leader-election
subjects:
- kind: ServiceAccount
name: ack-s3-controller
namespace: ack-systemApply the above configurations to ensure the role and rolebinding are created successfully.
Now, restart your deployment to take all changes into consideration:
kubectl get deployments -n $ACK_K8S_NAMESPACE
kubectl -n $ACK_K8S_NAMESPACE rollout restart deployment <ACK deployment name>AWS ACK S3 bucket creation
To generate an S3 bucket, you will just need to define a configuration for it similar to:
apiVersion: s3.services.k8s.aws/v1alpha1
kind: Bucket
metadata:
name: k8s-bucket-demo
spec:
name: k8s-bucket-demoSave it to a file and run:
kubectl apply -f s3_bucket.yamlYou can head over to your AWS account and see the S3 bucket created.
If you are facing any issues and you don’t see your bucket created in AWS, even though you ran kubectl apply successfully, you will need to check the controller logs to understand what has happened.
Terraform S3 bucket creation
The process of installing and using Terraform is pretty straightforward. Simply go here and download the correct Terraform version for your operating system.
The following code will generate an S3 bucket with the name terraform-test-bucket.
provider "aws" {
region = "eu-west-1"
}
resource "aws_s3_bucket" "this" {
bucket = "terraform-test-bucket"
}You will simply need to run the following commands, and you are good to go:
terraform init
terraform apply -auto-approveAfter you run the apply, your resource will be created if you are not receiving any errors.
As mentioned above, with k8s operators, even though you are getting a successful result after running kubectl apply, you can still have surprises in your environment. The controller is the source of truth, so that’s the place you will need to look for logs and understand what has happened.
With Terraform, this is not the case, as if your apply succeeds, your resources will be provisioned successfully, and if you are having any issues, you will see them directly after your apply fails.
As you can see, Kubernetes operators achieve the same thing as Terraform does, but they are hard to deploy, hard to maintain, and you have to do troubleshooting in multiple places. For Terraform, the process is easy, and you won’t get false positives as you can get by using operators.
Kubernetes and Terraform with Spacelift
Running Terraform and Kubernetes usually means running two separate workflows, with separate tooling, access controls, and places to look when something drifts. Spacelift manages both in one place. It supports Terraform and Kubernetes and lets you create stacks for each, so you can build CI/CD pipelines that combine them, let your teams collaborate, and apply security controls across both.
A common pattern is to deploy Kubernetes clusters with Terraform stacks, then deploy your containerized applications to those clusters on separate Kubernetes stacks. With this setup, you get drift detection on your Kubernetes stacks and manage every stack from one place.
You can go further with custom policies that harden the security and reliability of your deployments. Spacelift gives you several policy types to fit different use cases: add plan policies to warn about or block security and compliance violations, or approval policies to require sign-off before a deployment runs. The result is one workflow for Terraform and Kubernetes, with the same policies, approvals, and drift detection applied to both.
Take a look at the documentation to get started with Spacelift.

Spacelift was also the most cost-effective and flexible option, supporting multiple frameworks including OpenTofu and Pulumi — not just Terraform. This flexibility mitigated the risk of vendor lock-in and sprawl as Orbica’s tech stack expanded.
Key points
We delved into two of the most used modern DevOps tools, Kubernetes and Terraform. We discovered what makes each of them appealing and what functionalities they provide to IT operators and developers.

We discussed their similarities, differences, and synergies and explored ways to combine them with Spacelift.
Solve your infrastructure challenges
Spacelift lets you automate, audit, secure, and continuously deliver your infrastructure. It solves common state management problems and adds the controls infrastructure teams need: policy as code, drift detection, and approvals.
Frequently asked questions
Can Terraform replace Kubernetes?
No. Terraform provisions infrastructure, and Kubernetes orchestrates containers. Terraform can create a Kubernetes cluster, but it does not schedule, scale, or heal the applications running inside it.
Can Kubernetes replace Terraform?
Not for general infrastructure. Kubernetes Cloud Operators can provision some cloud resources from inside a cluster, but coverage is narrower than Terraform’s provider ecosystem, and you take on extra troubleshooting and potential vendor lock-in.
Can Terraform deploy applications to Kubernetes?
Yes. Terraform has Kubernetes and Helm providers that can apply manifests and install charts. It works, but every Kubernetes resource needs a matching Terraform schema, which makes managing application objects this way more cumbersome than using native manifests.
