Creating an Amazon EKS (Elastic Kubernetes Service) cluster using Terraform involves a series of carefully orchestrated steps. Each step can be encapsulated within its own Terraform module for better modularity and reusability. Here’s a breakdown of how to structure your Terraform project to deploy an EKS cluster on AWS.
1. VPC Module
- Create a Virtual Private Cloud (VPC): This is where your EKS cluster will reside.
- Set Up Subnets: Establish both public and private subnets within the VPC to segregate your resources effectively.
2. EKS Module
- Deploy the EKS Cluster: Link the components created in the VPC module to your EKS cluster.
- Define Security Rules: Set up security groups and rules for both the EKS master nodes and worker nodes.
- Configure IAM Roles: Create IAM roles and policies needed for the EKS master and worker nodes.
Project Directory Structure
Let’s begin by creating a root project directory named terraform-eks-project
. Below is the suggested directory structure for the entire Terraform project:
terraform-eks-project/
│
├── modules/ # Root directory for all modules
│ ├── vpc/ # VPC module: VPC, Subnets (public & private)
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ │
│ └── eks/ # EKS module: cluster, worker nodes, IAM roles, security groups
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ └── worker_userdata.tpl
│
├── backend.tf # Backend configuration (e.g., S3 for remote state)
├── main.tf # Main file to call and stitch modules together
├── variables.tf # Input variables for the main configuration
├── outputs.tf # Output values from the main configuration
├── provider.tf # Provider block for the main configuration
├── terraform.tfvars # Variable definitions file
└── README.md # Documentation and instructions
Root Configuration Files Overview
backend.tf
: Specifies how Terraform state is managed and where it’s stored (e.g., in an S3 bucket).main.tf
: The central configuration file that integrates the various modules and manages the AWS resources.variables.tf
: Declares the variables used throughout the project.outputs.tf
: Manages the outputs from the Terraform scripts, such as IDs and ARNs.terraform.tfvars
: Contains user-defined values for the variables.README.md
: Provides documentation and usage instructions for the project.
Backend Configuration (backend.tf)
The backend.tf
file is responsible for defining how Terraform state is loaded and how operations are executed. For instance, using an S3 bucket as the backend allows for secure and durable state storage.
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket" # Replace with your S3 bucket name
key = "path/to/my/key" # Path to the state file within the bucket
region = "us-west-1" # AWS region of your S3 bucket
encrypt = true # Enable server-side encryption of the state file
# Optional: DynamoDB for state locking and consistency
dynamodb_table = "my-terraform-lock-table" # Replace with your DynamoDB table name
# Optional: If S3 bucket and DynamoDB table are in different AWS accounts or need specific credentials
# profile = "myprofile" # AWS CLI profile name
}
}
Main Configuration (main.tf)
The main.tf
file includes module declarations for the VPC and EKS components.
VPC Module
The VPC module creates the foundational network infrastructure components.
module "vpc" {
source = "./modules/vpc" # Location of the VPC module
env = terraform.workspace # Current workspace (e.g., dev, prod)
app = var.app # Application name or type
vpc_cidr = lookup(var.vpc_cidr_env, terraform.workspace) # CIDR block specific to workspace
public_subnet_number = 2 # Number of public subnets
private_subnet_number = 2 # Number of private subnets
db_subnet_number = 2 # Number of database subnets
region = var.aws_region # AWS region
# NAT Gateways settings
vpc_enable_nat_gateway = var.vpc_enable_nat_gateway # Enable/disable NAT Gateway
enable_dns_hostnames = true # Enable DNS hostnames in the VPC
enable_dns_support = true # Enable DNS resolution in the VPC
}
EKS Module
The EKS module sets up a managed Kubernetes cluster on AWS.
module "eks" {
source = "./modules/eks"
env = terraform.workspace
app = var.app
vpc_id = module.vpc.vpc_id
cluster_name = var.cluster_name
cluster_service_ipv4_cidr = lookup(var.cluster_service_ipv4_cidr, terraform.workspace)
public_subnets = module.vpc.public_subnet_ids
cluster_version = var.cluster_version
cluster_endpoint_private_access = var.cluster_endpoint_private_access
cluster_endpoint_public_access = var.cluster_endpoint_public_access
cluster_endpoint_public_access_cidrs = var.cluster_endpoint_public_access_cidrs
sg_name = var.sg_external_eks_name
}
Outputs Configuration (outputs.tf)
The outputs.tf
file defines the values that Terraform will output after applying the configuration. These outputs can be used for further automation or simply for inspection.
output "vpc_id" {
value = module.vpc.vpc_id
}
output "cluster_id" {
value = module.eks.cluster_id
}
output "cluster_arn" {
value = module.eks.cluster_arn
}
output "cluster_certificate_authority_data" {
value = module.eks.cluster_certificate_authority_data
}
output "cluster_endpoint" {
value = module.eks.cluster_endpoint
}
output "cluster_version" {
value = module.eks.cluster_version
}
Variable Definitions (terraform.tfvars)
The terraform.tfvars
file is where you define the values for variables that Terraform will use.
aws_region = "us-east-1"
# VPC Core
vpc_cidr_env = {
"dev" = "10.101.0.0/16"
#"test" = "10.102.0.0/16"
#"prod" = "10.103.0.0/16"
}
cluster_service_ipv4_cidr = {
"dev" = "10.150.0.0/16"
#"test" = "10.201.0.0/16"
#"prod" = "10.1.0.0/16"
}
enable_dns_hostnames = true
enable_dns_support = true
vpc_enable_nat_gateway = false
# EKS Configuration
cluster_name = "test_cluster"
cluster_version = "1.27"
cluster_endpoint_private_access = true
cluster_endpoint_public_access = true
cluster_endpoint_public_access_cidrs = ["0.0.0.0/0"]
sg_external_eks_name = "external_kubernetes_sg"
Variable Declarations (variables.tf)
The variables.tf
file is where you declare all the variables used in your Terraform configuration. This allows for flexible and reusable configurations.
variable "aws_region" {
description = "Region in which AWS Resources to be created"
type = string
default = "us-east-1"
}
variable "zone" {
description = "The zone where VPC is"
type = list(string)
default = ["us-east-1a", "us-east-1b"]
}
variable "azs" {
type = list(string)
description = "List of availability zones suffixes."
default = ["a", "b", "c"]
}
variable "app" {
description = "The APP name"
default = "ekstestproject"
}
variable "env" {
description = "The Environment variable"
type = string
default = "dev"
}
variable "vpc_cidr_env" {}
variable "cluster_service_ipv4_cidr" {}
variable "enable_dns_hostnames" {}
variable "enable_dns_support" {}
# VPC Enable NAT Gateway (True or False)
variable "vpc_enable_nat_gateway" {
description = "Enable NAT Gateways for Private Subnets Outbound Communication"
type = bool
default = true
}
# VPC Single NAT Gateway (True or False)
variable "vpc_single_nat_gateway" {
description = "Enable only single NAT Gateway in one Availability Zone to save costs during our demos"
type = bool
default = true
}
# EKS Variables
variable "cluster_name" {
description = "The EKS cluster name"
default = "k8s"
}
variable "cluster_version" {
description = "The Kubernetes minor version to use for the
EKS cluster (for example 1.26)"
type = string
default = null
}
variable "cluster_endpoint_private_access" {
description = "Indicates whether the Amazon EKS private API server endpoint is enabled."
type = bool
default = false
}
variable "cluster_endpoint_public_access" {
description = "Indicates whether the Amazon EKS public API server endpoint is enabled."
type = bool
default = true
}
variable "cluster_endpoint_public_access_cidrs" {
description = "List of CIDR blocks which can access the Amazon EKS public API server endpoint."
type = list(string)
default = ["0.0.0.0/0"]
}
variable "sg_external_eks_name" {
description = "The SG name."
}
Conclusion
This guide outlines the key components of setting up an Amazon EKS cluster using Terraform. By organizing your Terraform code into reusable modules, you can efficiently manage and scale your infrastructure across different environments. The modular approach not only simplifies management but also promotes consistency and reusability in your Terraform configurations.