Introducing Terraform-Operator: The Basics
Terraform-Operator is a Kubernetes CRD and Controller to configure, run, and manage your Terraform resources right from your cluster. Simply configure a Kubernetes manifest, apply, and watch Terraform-Operator run the Terraform. Once it's complete, it saves the Terraform output into a Kubernetes ConfigMap which can be consumed directly by your Pods. This makes it ideal to deploy along with Services which use cloud resources.
Deploy the Operator
- 
								
Option #1 The easiest method to install the Terraform-Operator is via helm
$ helm repo add isaaguilar https://isaaguilar.github.io/helm-charts
$ helm install terraform-operator isaaguilar/terraform-operator --namespace tf-system --create-namespace
 - 
								
Option #2 Install it via
kubectlby first installing the CRD followed by the Controller.
$ git clone https://github.com/isaaguilar/terraform-operator
$ kubectl apply -f terraform-operator/deploy/crds/tf.isaaguilar.com_terraforms_crd.yaml
$ kubectl apply -f terraform-operator/deploy --namespace tf-system
 
Once the operator is installed, Terraform resources are ready to be deployed. However one critical component is missing; somewhere to store our Terraform State. The Terraform-Operator can be configured to store state to any Terraform backend. This is configured per resource. For now let's use the default; HashiCorp's Consul running in your cluster. Install it using the following command:
									
										$ git clone --single-branch --branch v0.19.0 https://github.com/hashicorp/consul-helm.git
										$ helm upgrade --install hashicorp ./consul-helm \
--namespace tf-system \
--set server.replicas=1 \
--set server.bootstrapExpect=1
									
Running Terraform
Now let's pick a simple example. Let's deploy a S3 bucket in AWS; we're going to need some AWS credentials. The Terraform-Operator can mount credentials from a Kubernetes Secret so let's create that:
									
										$ kubectl create secret generic aws-session-credentials \
 --from-literal=AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
 --from-literal=AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
									
Nice! The secret name aws-session-credentials is ready to be used in the configuration. Create the S3 bucket configuration as :
									
# terraform-my-bucket.yaml
---
apiVersion: tf.isaaguilar.com/v1alpha1
kind: Terraform
metadata:
  name: my-bucket
spec:
  terraformVersion: 0.12.29
  terraformModule:
    address: https://github.com/cloudposse/terraform-aws-s3-bucket.git
  applyOnCreate: true
  applyOnUpdate: true
  applyOnDelete: true
  ignoreDelete: false  # Make sure to clean up example and delete when kubectl delete is run
  credentials:
  - secretNameRef:
      name: aws-session-credentials
  env:
  - name: AWS_REGION
    value: us-west-2
  - name: TF_VAR_name
    value: terraform-operator-s3-bucket-example
									
Ready to deploy.
									
										$ kubectl apply -f terraform-my-bucket.yaml
terraform.tf.isaaguilar.com/my-bucket created
									
After a small while you'll see your pod
									
										$ kubectl get pods
NAME                      READY   STATUS      RESTARTS   AGE
my-bucket-nlv85           1/1     Running     1          39s
										
Run kubectl logs -f my-bucket-nlv85 to see the Terraform run logs. Once the pod completes, a ConfigMap with the Terraform output content is saved. Let's check out what we've got:
									
										$ kubectl get configmap my-bucket-output -oyaml
										
apiVersion: v1
data:
  access_key_id: ""
  bucket_arn: arn:aws:s3:::terraform-operator-s3-bucket-example
  bucket_domain_name: terraform-operator-s3-bucket-example.s3.amazonaws.com
  bucket_id: terraform-operator-s3-bucket-example
  bucket_region: us-west-2
  bucket_regional_domain_name: terraform-operator-s3-bucket-example.s3.us-west-2.amazonaws.com
  enabled: "true"
  secret_access_key: ""
  user_arn: ""
  user_enabled: "false"
  user_name: ""
  user_unique_id: ""
kind: ConfigMap
metadata:
  creationTimestamp: "2020-10-22T04:45:48Z"
  name: my-bucket-output
  namespace: default
  resourceVersion: "416381"
  selfLink: /api/v1/namespaces/default/configmaps/my-bucket-output
  uid: 74a2e9d0-1421-11eb-bbe8-025000000001
										
Congratulations! The S3 bucket is ready to be used. I'll outline what went on in the Terraform-Operator to get to this point in another post. For now, let's explore more to see what we've got.
Terraform State with Consul
When using Terraform-Operator's default Terraform State backend, Consul, state is organized in the Key/Value data store as . You can use  to view the Consul Ui.
									
										$ kubectl port-forward -n tf-system svc/hashicorp-consul-ui 8000:80
Forwarding from 127.0.0.1:8000 -> 8500
Forwarding from [::1]:8000 -> 8500
										
See the Ui by going to localhost:8000 in a browser

Or  query Consul's  endpoint using curl.
									
										$ curl "http://127.0.0.1:8000
Cleanup Terraform
To clean up the environment, run  on the Terraform resource. This will trigger a new pod, this time running  in the Terraform run.
									
										$ kubectl delete terraform my-bucket
terraform.tf.isaaguilar.com "my-bucket" deleted
										
Summary
							Terraform-Operator provides an organized structure to define your infrastructure-as-code with a first-class Kubernetes experience. It's easy to get setup and running in just a few minutes. Cleanup is a breeze. To learn more check out the official docs at https://github.com/isaaguilar/terraform-operator/tree/master/docs.
							
						
I would love to hear your feedback and expand on the project!
Send bugs, questions, feature requests for the Terraform-Operator to isaaguilar/terraform-operator by posting a new issue!