DEV Community

Cover image for Automate your Infrastructure on AWS using Terraform Controller and FluxCD
Amit Chaturvedi
Amit Chaturvedi

Posted on

Automate your Infrastructure on AWS using Terraform Controller and FluxCD

Introduction

In the age of cloud-native operations, infrastructure automation is no longer optional—it's essential. While tools like Terraform have long been the standard for Infrastructure as Code (IaC), integrating them into a GitOps workflow brings unprecedented control, traceability, and scalability. In this blog, we'll explore how to automate your AWS infrastructure using Terraform Controller (from the Crossplane ecosystem) and FluxCD, leveraging Git as the single source of truth.

Why Terraform Controller + FluxCD?

  • Terraform Controller: A Kubernetes controller that allows you to manage Terraform executions through Custom Resource Definitions (CRDs).
  • FluxCD: A GitOps toolkit that automates Kubernetes deployments by syncing Git repositories with clusters.
  • GitOps Benefits: Version control, audit trails, CI/CD integration, and reduced configuration drift.

Prerequisites
Before you begin, ensure you have the following:

  • A Kubernetes cluster (EKS,AKS,GKS,On-Prem or local like KinD)
  • AWS credentials with necessary IAM permissions
  • kubectl, flux, and terraform controller installed
  • A Git repository for storing Terraform manifests

Step-by-Step Guide

Install Kind Cluster

#cat config.yaml kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane - role: worker - role: worker 
Enter fullscreen mode Exit fullscreen mode
#kind create cluster --config=config.yaml 
Enter fullscreen mode Exit fullscreen mode

Image description

Install flux cli

#brew install fluxcd/tap/flux 
Enter fullscreen mode Exit fullscreen mode

Image description

BootStrap fluxcd to install flux-system with gitrepo infra-demo
Image description

#flux bootstrap gitlab --token-auth --owner=infra-demo2 --repository=flux-system --branch=main --path=clusters/dev 
Enter fullscreen mode Exit fullscreen mode

Image description

A namespace name flux-system will be created with required components

#kubectl get ns #kubectl get all -n flux-system 
Enter fullscreen mode Exit fullscreen mode

Image description

Lets Install Terraform Controller

#helm repo add tofu-controller https://flux-iac.github.io/tofu-controller #helm upgrade -i tofu-controller tofu-controller/tf-controller \ --namespace flux-system 
Enter fullscreen mode Exit fullscreen mode

Image description

Lets Verify Controller in flux-system

#kubectl get pods -n flux-system | grep tf 
Enter fullscreen mode Exit fullscreen mode

Image description

Create infrastructure project inside infra-demo repo and map Source list and Kustamization to infra-demo repository to managed by Flux-cd

Image description

#cat infra-demo.yaml apiVersion: source.toolkit.fluxcd.io/v1beta1 kind: GitRepository metadata: name: vpc-creation namespace: flux-system spec: interval: 30s url: https://gitlab.com/infra-demo2/infrastructure.git ref: branch: main secretRef: name: flux-system --- apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 kind: Kustomization metadata: name: vpc-creation namespace: flux-system spec: prune: true interval: 2m path: ./ sourceRef: kind: GitRepository name: vpc-creation timeout: 3m healthChecks: - apiVersion: infra.contrib.fluxcd.io/v1alpha1 kind: Terraform name: vpc-creation namespace: flux-system 
Enter fullscreen mode Exit fullscreen mode

Lets Create terraform Code in Infrastructure Project to deploy VPC in AWS Account

#cat main.tf resource "aws_vpc" "main" { cidr_block = var.vpc_cidr enable_dns_support = true enable_dns_hostnames = true tags = { Name = "${var.project}-vpc" } } resource "aws_subnet" "public" { count = length(var.public_subnets) vpc_id = aws_vpc.main.id cidr_block = var.public_subnets[count.index] availability_zone = element(var.availability_zones, count.index) map_public_ip_on_launch = true tags = { Name = "${var.project}-public-subnet-${count.index + 1}" } } resource "aws_internet_gateway" "igw" { vpc_id = aws_vpc.main.id tags = { Name = "${var.project}-igw" } } resource "aws_route_table" "public" { vpc_id = aws_vpc.main.id tags = { Name = "${var.project}-public-rt" } } resource "aws_route" "internet_access" { route_table_id = aws_route_table.public.id destination_cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.igw.id } resource "aws_route_table_association" "public_assoc" { count = length(var.public_subnets) subnet_id = aws_subnet.public[count.index].id route_table_id = aws_route_table.public.id } 
Enter fullscreen mode Exit fullscreen mode
#cat outputs.tf output "vpc_id" { value = aws_vpc.main.id } output "public_subnet_ids" { value = aws_subnet.public[*].id } 
Enter fullscreen mode Exit fullscreen mode
#cat variables.tf variable "aws_region" { default = "us-east-1" } variable "project" { default = "demo" } variable "vpc_cidr" { default = "10.0.0.0/16" } variable "public_subnets" { default = ["10.0.1.0/24", "10.0.2.0/24"] } variable "availability_zones" { default = ["us-east-1a", "us-east-1b"] } 
Enter fullscreen mode Exit fullscreen mode

Note: Not Recommended

#cat provider.tf provider "aws" { region = var.aws_region access_key = "XXXXXXXXXX" secret_key = "YYYYYYYYYYYYYY" } 
Enter fullscreen mode Exit fullscreen mode

Now Create Terraform Controller to Deploy Terraform Code

#cat terraform.yaml apiVersion: infra.contrib.fluxcd.io/v1alpha1 kind: Terraform metadata: name: vpc-creation namespace: flux-system spec: interval: 1m approvePlan: auto path: ./ sourceRef: kind: GitRepository name: vpc-creation namespace: flux-system 
Enter fullscreen mode Exit fullscreen mode

Now the Repo will look Like
Image description

Now Lets Deploy infrademo.yaml to Map Repo to get managed by flux-system

#flux get sources all | grep vpc-creation #flux get kustomization | grep vpc-creation # kubectl apply -f infrademo.yaml #flux get sources all | grep vpc-creation #flux get sources all | grep vpc-creation 
Enter fullscreen mode Exit fullscreen mode

Image description

Once we Deploy it Terraform Controller is going to Create a runner with name of vpc-creation-tf-runner which is going to deploy the resources in AWS

Image description

Lets verify the log of the runner

kubectl logs vpc-creation-tf-runner -n flus-system -f 
Enter fullscreen mode Exit fullscreen mode

Image description

Congratulations: We have deployed our resource successfully

Lets Verify from the AWS Portal

Image description

Image description

Top comments (0)