DEV Community

Cover image for Terraform v15.0 with AWS (EKS deployment)
cosckoya
cosckoya

Posted on

Terraform v15.0 with AWS (EKS deployment)

Terraform v15 was released on April 14th.

On this post I will use the following resources:

· Provision an EKS Cluster (AWS)
· Terraform v15.0
· Terraform Registry
· Pre-Commit
· Terraform Pre-commit
· Terraform-docs
· Tflint
· Tfsec

This is based on the Hashicorp Learning Tutorial "Provision an EKS Cluster (AWS)". I took that tutorial as a base project for this post, then I had tweaked it a little bit. I had set up some variables, modified some module and providers versions and changed some of the "list" and "map" functions. Also, I added some pre-commit hooks based on tflint, tfsec and terraform-docs. Let's start!

Before starting, I always make some resource inventory/manifest, more like a shopping cart, that helps me on what should I deploy for each cloud project. So here is the "inventory":

1 x Amazon VPC 6 x Amazon Subnet (3 x Public + 3 x Private) 3 x Amazon EC2 1 x Amazon EKS 1 x Kubernetes AWS-Auth policy 
Enter fullscreen mode Exit fullscreen mode

First thing to do, is to init a git repository. Mine is this one. Then we must create some folder and files there:

CMD> mkdir terraform CMD> touch terraform/{main,outputs,variables,versions}.tf terraform/README.md 
Enter fullscreen mode Exit fullscreen mode

To enable pre-commit, we need to create a .pre-commit-config.yaml file that will contain relative config and install pre-commit in the project:

CMD> echo 'repos: - repo: git://github.com/antonbabenko/pre-commit-terraform rev: master hooks: - id: terraform_fmt - id: terraform_validate - id: terraform_docs - id: terraform_docs_without_aggregate_type_defaults - id: terraform_tflint args: - 'args=--enable-rule=terraform_documented_variables' - id: terraform_tfsec - repo: https://github.com/pre-commit/pre-commit-hooks rev: master hooks: - id: check-merge-conflict - id: end-of-file-fixer' > .pre-commit-config.yaml CMD> pre-commit install pre-commit installed at .git/hooks/pre-commit 
Enter fullscreen mode Exit fullscreen mode

Project folder hierarchy should look like this:

CMD> tree . ├── README.md └── terraform ├── main.tf ├── outputs.tf ├── README.md ├── variables.tf └── versions.tf 
Enter fullscreen mode Exit fullscreen mode

Let's start setting up "versions.tf" file. This file contains our relative provider versions, it's better to close this versions to avoid some misconfigurations in the future updates:

# Providers version # Ref. https://www.terraform.io/docs/configuration/providers.html terraform { required_version = "~>0.15" required_providers { # Base Providers random = { source = "hashicorp/random" version = "3.1.0" } null = { source = "hashicorp/null" version = "3.1.0" } local = { source = "hashicorp/local" version = "2.1.0" } template = { source = "hashicorp/template" version = "2.2.0" } # AWS Provider aws = { source = "hashicorp/aws" version = "3.37.0" } # Kubernetes Provider kubernetes = { source = "hashicorp/kubernetes" version = "2.1.0" } } } 
Enter fullscreen mode Exit fullscreen mode

Then I manage to set some project variables in the "variables.tf". This will help me to make some different workspaces, environments or command line variable override:

# Common variable "project" { default = "cosckoya" description = "Project name" } variable "environment" { default = "laboratory" description = "Environment name" } # Amazon variable "region" { default = "us-east-1" description = "AWS region" } variable "vpc_cidr" { type = string default = "10.0.0.0/16" description = "AWS VPC CIDR" } variable "public_subnets_cidr" { type = list(any) default = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] description = "AWS Public Subnets" } variable "private_subnets_cidr" { type = list(any) default = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"] description = "AWS Private Subnets" } 
Enter fullscreen mode Exit fullscreen mode

This is my custom "main.tf" file. Here I changed the "locals" to set some tags as a "tomap(..)" function, update d the modules to the last version and also updated the Kubernetes version to 1.19. Just to test and have fun.

[...] locals { cluster_name = "${var.project}-${var.environment}-eks" tags = tomap({"Environment" = var.environment, "project" = var.project}) } [...] ## Amazon Networking module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "2.78.0" name = "${var.project}-${var.environment}-vpc" cidr = var.vpc_cidr azs = data.aws_availability_zones.available.names private_subnets = var.public_subnets_cidr public_subnets = var.private_subnets_cidr enable_nat_gateway = true single_nat_gateway = true enable_dns_hostnames = true tags = { "kubernetes.io/cluster/${local.cluster_name}" = "shared" } public_subnet_tags = { "kubernetes.io/cluster/${local.cluster_name}" = "shared" "kubernetes.io/role/elb" = "1" } private_subnet_tags = { "kubernetes.io/cluster/${local.cluster_name}" = "shared" "kubernetes.io/role/internal-elb" = "1" } } [...] 
Enter fullscreen mode Exit fullscreen mode

I didn't touch any of the "outputs.tf".

Check these git repositories for more information:
· Learn Terraform - Provision an EKS Cluster
· Cosckoya's AWS Terraform Laboratory

Time to have fun now. Let's play with this:

· Initialize the project

CMD> terraform init 
Enter fullscreen mode Exit fullscreen mode

In here we should test the pre-commit rules that we had set up, take note of every Tfsec error about the security compliance. Try to resolve each or comment them with this docs

Add these lines to the "terraform" README.md:

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> <!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --> 
Enter fullscreen mode Exit fullscreen mode

Running Pre-Commit, our config will create a basic document with a lot of interesting information about our Terraform project

CMD> pre-commit run -a Terraform fmt............................................................Passed Terraform validate.......................................................Passed Terraform docs...........................................................Passed Terraform docs (without aggregate type defaults).........................Passed Terraform validate with tflint...........................................Passed Check for merge conflicts................................................Passed Fix End of Files.........................................................Passed 
Enter fullscreen mode Exit fullscreen mode

And check that README.md file:

CMD> cat terraform/README.md [...] ## Requirements [...] ## Providers [...] ## Modules [...] ## Resources [...] ## Inputs [...] ## Outputs 
Enter fullscreen mode Exit fullscreen mode

Mine is available here

Now it's time to have fun!
· Plan the project

CMD> terraform plan 
Enter fullscreen mode Exit fullscreen mode

· Deploy the project

CMD> terraform apply 
Enter fullscreen mode Exit fullscreen mode

· Connect to the cluster and enjoy!

CMD> aws eks --region $(terraform output -raw region) update-kubeconfig --name $(terraform output -raw cluster_name) 
Enter fullscreen mode Exit fullscreen mode

Running some basic commands we can see that the cluster is up and running:

CMD> kubectl cluster-info Kubernetes control plane is running at https://<SOME-BIG-HASH>.us-east-1.eks.amazonaws.com CoreDNS is running at https://<SOME-BIG-HASH>.us-east-1.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy CMD> kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-2-138.ec2.internal Ready <none> 26m v1.19.6-eks-d1db3c ip-10-0-2-88.ec2.internal Ready <none> 26m v1.19.6-eks-d1db3c ip-10-0-3-68.ec2.internal Ready <none> 26m v1.19.6-eks-d1db3c 
Enter fullscreen mode Exit fullscreen mode

Enjoy!

Ps. As you could see this is so similar to the AWS Terraform Learn page. Little tweaks to test some changes between versions.

I'm a very big fan of @antonbabenko work. I recommend everyone to follow him.

Top comments (0)