Deploying Amazon Elastic Kubernetes Service with Terraform and automating the pipeline through GitHub Actions combines declarative infrastructure with continuous delivery. The terraform-aws-eks module is a comprehensive Terraform module for provisioning and managing Amazon Elastic Kubernetes Service (EKS) clusters and their associated infrastructure. The module abstracts the complexity of EKS cluster creation by managing the EKS control plane, compute resources (node groups), IAM roles, security groups, network configuration, encryption, and cluster add-ons through a single, declarative configuration.
AWS Elastic Kubernetes Service (EKS) is a managed service that lets you deploy, manage, and scale containerized applications on Kubernetes. In this tutorial context, you will deploy an EKS cluster using Terraform. Then, you will configure kubectl using Terraform output and verify that your cluster is ready to use. While you could use the built-in AWS provisioning processes (UI, CLI, CloudFormation) for EKS clusters, Terraform provides you with several benefits:
Unified Workflow - If you already use Terraform to deploy AWS infrastructure, you can use the same workflow to deploy both EKS clusters and applications into those clusters.
Full Lifecycle Management - Terraform creates, updates, and deletes tracked resources without requiring you to inspect an API to identify those resources.
Graph of Relationships - Terraform determines and observes dependencies between resources. For example, if an AWS Kubernetes cluster needs a specific VPC and subnet configurations, Terraform will not attempt to create the cluster if it fails to provision the VPC and subnet first.
The tutorial assumes some basic familiarity with Kubernetes and kubectl but does not assume any pre-existing deployment. You can complete this tutorial using the same workflow with either Terraform Community Edition or HCP Terraform. HCP Terraform is a platform that you can use to manage and execute your Terraform projects.
Module Architecture and Core Files
This page covers the module's architecture, component relationships, and high-level configuration patterns. For specific topics, see the dedicated documentation.
The module is organized into a root module and several specialized sub-modules that handle specific aspects of EKS infrastructure:
Key Files:
main.tf
Creates awsekscluster resource, IAM roles, security groups, OIDC provider, and add-ons
variables.tf
Defines all module input variables including cluster configuration, node group definitions, and IAM settings
outputs.tf
Exposes cluster attributes, endpoints, security group IDs, and IAM role ARNs
node_groups.tf
Orchestrates the creation of compute resources by invoking sub-modules
The root module provisions the following primary resources:
| Resource Type | Terraform Resource | Purpose |
|---|---|---|
| EKS Cluster | awsekscluster.this | Kubernetes control plane |
| CloudWatch Log Group | awscloudwatchlog_group.this | Control plane logs |
| IAM Role (Cluster) | awsiamrole.this | Control plane permissions |
| IAM Role (Auto Mode) | awsiamrole.eks_auto | EKS Auto Mode node permissions |
| OIDC Provider | awsiamopenidconnectprovider.oidc_provider | IRSA (IAM Roles for Service Accounts) |
| Security Groups | awssecuritygroup.cluster |
This structure makes the module suitable for both greenfield deployments and incremental adoption in existing accounts.
State Management and Remote Backend
Production Terraform workflows require remote state with locking and encryption. Store Terraform state in S3 with DynamoDB locking.
hcl
terraform {
backend "s3" {
bucket = "terraform-state-bucket"
key = "eks/terraform.tfstate"
region = "us-west-2"
dynamodb_table = "terraform-state-lock"
encrypt = true
use_lockfile = true
}
}
The backend configuration uses bucket terraform-state-bucket, key eks/terraform.tfstate, region us-west-2, dynamodbtable terraform-state-lock, encrypt true, uselockfile true. The dynamodb_table ensures concurrent runs cannot corrupt state and encryption protects secrets stored in state.
Modular Organization for Maintainability
Breaking the configuration into modules improves maintainability and enables reuse across environments.
```hcl
module "vpc" {
source = "./modules/vpc"
# VPC configuration parameters
}
module "eks" {
source = "./modules/eks"
# EKS configuration parameters
vpcid = module.vpc.vpcid
subnetids = module.vpc.privatesubnet_ids
}
```
The VPC module outputs network identifiers that feed directly into the EKS module inputs. This explicit dependency graph prevents the cluster creation from attempting to start before the network exists.
EKS Blueprints Add-Ons and ArgoCD Deployment
The terraform-aws-eks module manages core control plane resources. For add-ons, the AWS EKS Blueprints framework provides composable modules.
Deploy ArgoCD using the EKS Blueprints framework:
hcl
module "kubernetes_addons" {
source = "github.com/aws-ia/terraform-aws-eks-blueprints//modules/kubernetes-addons"
eks_cluster_id = module.eks_blueprints.eks_cluster_id
enable_argocd = true
enable_metrics_server = true
enable_cluster_autoscaler = true
enable_aws_load_balancer_controller = true
argocd_helm_config = {
values = [templatefile("${path.module}/values.yaml", {})]
}
}
The configuration enables ArgoCD, metrics server, cluster autoscaler, and AWS Load Balancer Controller as Helm-managed add-ons. The eks_cluster_id ties the add-on lifecycle to the cluster.
Automatic Scaling Based on Resource Utilization
Node groups can be scaled automatically using Target Tracking policies.
hcl
resource "aws_autoscaling_policy" "cluster_autoscaling" {
name = "eks-cluster-autoscaling"
policy_type = "TargetTrackingScaling"
target_tracking_configuration {
target_value = 75.0
predefined_metric_specification {
predefined_metric_type = "ASGAverageCPUUtilization"
}
}
autoscaling_group_name = aws_eks_node_group.main.resources[0].autoscaling_groups[0].name
}
The policy targets 75.0 percent average CPU utilization across the Auto Scaling group backing the node group. The module exposes the autoscaling group name through computed references.
GitHub Actions CI/CD for Terraform EKS
Automating EKS with GitHub Actions is a reliable way to manage your new cluster. The workflow separates plan on pull requests from apply on main.
Create a workflow file in .github/workflows to define the deployment process:
yaml
name: Terraform AWS Workflow
on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
jobs:
terraform:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v3
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions
aws-region: us-west-2
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
- name: Terraform Plan
if: github.event_name == 'pull_request'
run: terraform plan -no-color
- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: terraform apply -auto-approve
The workflow runs on ubuntu-latest with id-token write and contents read permissions. AWS credentials are assumed via role-to-assume arn:aws:iam::123456789012:role/github-actions in aws-region us-west-2. Terraform is set up with hashicorp/setup-terraform@v3. Init always runs. Plan runs only on pullrequest. Apply runs only when github.ref == 'refs/heads/main' && github.eventname == 'push'.
This pattern provides peer review via plan output and automated promotion to production.
Integration Patterns and Workflow Considerations
When using the terraform-aws-eks module with GitHub Actions, several operational patterns emerge.
State isolation per environment is achieved by using distinct backend key paths, e.g., eks/dev/terraform.tfstate and eks/prod/terraform.tfstate while sharing the same bucket and lock table.
Variable management can be handled via GitHub Actions secrets for AWS credentials and Terraform Cloud variables for module inputs. The module's variables.tf defines all module input variables including cluster configuration, node group definitions, and IAM settings, making it straightforward to map secrets to inputs.
Add-on upgrades are decoupled from control plane changes. The kubernetes_addons module allows independent enable/disable flags for ArgoCD, metrics server, cluster autoscaler, and AWS load balancer controller without touching node group definitions.
Scaling policies reference computed autoscaling group names from awseksnodegroup.main.resources[0].autoscalinggroups[0].name, which requires a dependency on the node group creation. Terraform's graph of relationships ensures correct ordering.
Operational Best Practices
The module abstracts complexity but does not replace architectural decisions. Network configuration should place the control plane in private subnets with public endpoint access disabled for hardening. Encryption settings should be enforced for secrets and logs. IAM roles should follow least privilege and be versioned alongside code.
For CI/CD, the workflow shown uses actions/checkout@v3 and aws-actions/configure-aws-credentials@v2. Using OpenID Connect for role assumption avoids long-lived credentials. Terraform init with -backend-config can be used to avoid hardcoding backend details in code.
The combination of Terraform AWS EKS modules and GitHub Actions provides a repeatable, auditable path from pull request to production Kubernetes cluster.
Conclusion
The terraform-aws-eks module delivers a complete, declarative model for EKS clusters including control plane, IAM, security groups, OIDC provider, and CloudWatch logging. Pairing it with modular VPC definitions, S3/DynamoDB state, EKS Blueprints add-ons for ArgoCD and autoscaling, and a GitHub Actions workflow that plans on pull_request and applies on push to main creates a production-grade delivery pipeline for Kubernetes on AWS. The architecture supports full lifecycle management, dependency graph enforcement, and unified workflow for infrastructure and platform teams. This approach scales from single cluster experiments to multi-account, multi-environment platforms while maintaining auditability and repeatability.