Keeping the terraform state in a Kubernetes Secret

terraform state Kubernetes Secret

2 min read | by Jordi Prats

Storing the terraform state into a S3 bucket with dynamoDB for locking has become the de facto standard for being able to share the state across an organization. Nevertheless, there are interesting alternatives: We can use a Kubernetes Secret

By using a Kubernetes Secret we no longer need dynamoDB since it uses a Lease for handling locking.

We can configure the backend as follows:

terraform {  backend "kubernetes" {  config_path = "~/.kube/config"  secret_suffix = "tfstate"  namespace = "default"  } } provider "kubernetes" { config_path = "~/.kube/config" config_context = "minikube" } resource "kubernetes_namespace" "demo_ns" { metadata { name = "testing-k8s-tfstate" } } 

There are many other options to be able to configure the backend to select the appropriate Kubernetes cluster

We can run this code using the usual workflow:

$ terraform init $ terraform plan $ terraform apply 

Checking the secret that it has created we will see that it is a regular

$ kubectl get secret -n default NAME TYPE DATA AGE default-token-t6662 kubernetes.io/service-account-token 3 6m55s tfstate-default-tfstate Opaque 1 63s $ kubectl describe secret tfstate-default-tfstate Name: tfstate-default-tfstate Namespace: default Labels: app.kubernetes.io/managed-by=terraform  tfstate=true  tfstateSecretSuffix=tfstate  tfstateWorkspace=default Annotations: encoding: gzip Type: Opaque Data ==== tfstate: 511 bytes 

It is stored as a compressed json, so we can read it's data using the following command:

$ kubectl get secret tfstate-default-tfstate -o jsonpath="{.data.tfstate}" | base64 -d | gzip -d - {  "version": 4,  "terraform_version": "1.1.3", (...) 

As you might already noticed, the workspace name is part of the secret's name, so if we rerun the code using a new namespace (deleting the namespace to make it work):

$ kubectl delete ns testing-k8s-tfstate $ terraform workspace new demo $ terraform apply -auto-approve 

We'll find a new Secret for each of the workspaces we are using:

$ kubectl get secret -n default NAME TYPE DATA AGE default-token-t6662 kubernetes.io/service-account-token 3 9m29s tfstate-default-tfstate Opaque 1 3m37s tfstate-demo-tfstate Opaque 1 89s 

Posted on 19/04/2022