Arnab Saha - Engineering Leader
Posts

Reusing Existing Terraform State while migrating to Crossplane 2023

May 27, 2023

3 min read

crossplaneterraformiacawsmigration

As part of evaluating Crossplane for IaC, one important use-case that I was evaluating was the overall flow of migrating resources managed by Terraform to Crossplane.

The idea was to run through the flow discussed in Crossplane's blog discussing the same use-case as I was interested in.

While it answered most of my questions, I was looking at understanding how to re-use the terraform state as part of the migration exercise.

Pre-requisites

Migration Flow

1. Clone the repo

It's a modified version of upbound's version .

2. Apply Terraform resources

Ensure you have Terraform & AWS CLI configured on your terminal and then apply the following, which provisions a VPC & Subnet:

terraform init
terraform plan -out tf.out
terraform apply "tf.out"

3. Verify the resources

We can see the VPC and Subnet created by Terraform on the AWS console.

4. Upload terraform state to S3

We can now upload the local terraform state file in a S3 bucket. In this example we push it in the bucket "xplanetfstate". This along with the region and the AWS credentials can be configured in the ProviderConfig, which will be used by Crossplane Compositions and Claims in the next sections:

apiVersion: tf.upbound.io/v1beta1
kind: ProviderConfig
metadata:
  name: aws-us-east-1
spec:
  configuration: |
    terraform {
      backend "s3" {
        bucket     = "xplanetfstate"
        key        = "terraform.tfstate"
        region     = "us-east-1"
        access_key = "KEY"
        secret_key = "SECRET"
      }
    }
    provider "aws" {
      shared_credentials_file = "aws-creds.ini"
      region = "us-east-1"
    }
  credentials:
    - filename: aws-creds.ini
      secretRef:
        key: creds
        name: aws-creds
        namespace: crossplane-system
      source: Secret

5. Use Terraform Provider by Crossplane

We can achieve the same result using the Terraform workspace but letting it be provisioned via Terraform Provider by Crossplane.

6. Apply via composition

Let's see an example of using a composition to apply the same Terraform module but now via Terraform Provider by Crossplane:

kubectl apply -f crossplane/composition-tf-only/composition.yaml
kubectl apply -f crossplane/composition-tf-only/subnet-tf.yaml

This will provision the same VPC & Subnet but via a workspace object that internally uses Terraform itself.

7. Iterative migration with existing state

We can now take an iterative journey and re-use our existing terraform state that we originally uploaded to S3:

kubectl apply -f crossplane/composition-tf-and-native/composition.yaml
kubectl apply -f crossplane/composition-tf-and-native/subnet-mixed.yaml

In this case the same VPC provisioned originally by Terraform is continued to be used by Crossplane and is managed by Terraform Provider. And the subnet itself is now natively managed by AWS Provider.

8. Fully native

We can eventually move to an entirely native way of managing the resources.

Conclusion

With Terraform Provider and re-using existing Terraform states we are able to assess a migration journey to native Crossplane. And of course with that, all the benefits that Crossplane brings on the table.

Looking forward to evaluating the journey on an actual production workflow!