Terraform AWS EKS Fargate Profile Module
Overview
This Terraform module provisions an AWS EKS Fargate Profile, enabling serverless compute for Kubernetes workloads. Fargate profiles allow you to run pods without managing EC2 instances, with automatic scaling and built-in security.
Features
- EKS Fargate Profile provisioning
- Namespace and label-based pod selection
- IAM role and policy management for Fargate pods
- Automatic pod execution without EC2 instances
- CloudPosse naming conventions
- Conditional module enablement
- Integration with existing EKS clusters
Resources Created
Fargate
- AWS EKS Fargate Profile
- Fargate Pod Execution IAM Role
IAM
- IAM Role for Fargate pod execution
- IAM Policy Attachment: AmazonEKSFargatePodExecutionRolePolicy
Usage
Basic Example
module "eks_fargate_profile" {
source = "git@github.com:webuildyourcloud/terraform-aws-eks_fargate_profile.git?ref=tags/0.0.2"
# Naming
namespace = "myorg"
stage = "prod"
name = "app"
# Cluster Configuration
cluster_name = "my-eks-cluster"
subnet_ids = ["subnet-12345678", "subnet-87654321"]
# Fargate Selection
kubernetes_namespace = "fargate-workloads"
kubernetes_labels = {
fargate = "true"
}
# Tags
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
Multiple Fargate Profiles
# Fargate profile for development namespace
module "fargate_dev" {
source = "git@github.com:webuildyourcloud/terraform-aws-eks_fargate_profile.git?ref=tags/0.0.2"
namespace = "myorg"
stage = "prod"
name = "dev"
cluster_name = module.eks_cluster.cluster_id
subnet_ids = module.vpc.private_subnet_ids
kubernetes_namespace = "development"
kubernetes_labels = {}
tags = {
Environment = "development"
}
}
# Fargate profile for specific workload with labels
module "fargate_batch" {
source = "git@github.com:webuildyourcloud/terraform-aws-eks_fargate_profile.git?ref=tags/0.0.2"
namespace = "myorg"
stage = "prod"
name = "batch"
cluster_name = module.eks_cluster.cluster_id
subnet_ids = module.vpc.private_subnet_ids
kubernetes_namespace = "batch-processing"
kubernetes_labels = {
workload = "batch"
compute = "fargate"
}
tags = {
WorkloadType = "batch"
}
}
Variables
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| namespace | Namespace (e.g., 'eg' or 'cp') | string |
"" |
no |
| stage | Stage (e.g., 'prod', 'staging', 'dev') | string |
"" |
no |
| name | Solution name (e.g., 'app' or 'cluster') | string |
n/a | yes |
| delimiter | Delimiter between namespace, stage, name and attributes | string |
"-" |
no |
| attributes | Additional attributes | list(string) |
[] |
no |
| tags | Additional tags | map(string) |
{} |
no |
| enabled | Enable/disable module resources | bool |
true |
no |
| cluster_name | Name of the EKS cluster | string |
n/a | yes |
| subnet_ids | List of private subnet IDs to associate with Fargate Profile | list(string) |
n/a | yes |
| kubernetes_namespace | Kubernetes namespace for pod selection | string |
n/a | yes |
| kubernetes_labels | Key-value mapping of Kubernetes labels for pod selection | map(string) |
{} |
no |
Outputs
| Name | Description |
|---|---|
| eks_fargate_profile_role_arn | ARN of the EKS Fargate Profile IAM role |
| eks_fargate_profile_role_name | Name of the EKS Fargate Profile IAM role |
| eks_fargate_profile_id | EKS Cluster name and Fargate Profile name separated by colon |
| eks_fargate_profile_arn | Amazon Resource Name (ARN) of the EKS Fargate Profile |
| eks_fargate_profile_status | Status of the EKS Fargate Profile |
Requirements
| Name | Version |
|---|---|
| terraform | >= 0.13 |
| aws | Latest |
Dependencies
- cloudposse/terraform-null-label - Resource naming
Pod Selection
Fargate profiles use selectors to determine which pods run on Fargate:
Namespace-Only Selection
kubernetes_namespace = "my-namespace"
kubernetes_labels = {}
All pods in my-namespace will run on Fargate.
Namespace + Label Selection
kubernetes_namespace = "my-namespace"
kubernetes_labels = {
compute = "fargate"
tier = "backend"
}
Only pods in my-namespace with matching labels will run on Fargate.
Kubernetes Integration
Deploy Pod to Fargate
Create a pod that matches the Fargate profile selector:
apiVersion: v1
kind: Pod
metadata:
name: my-fargate-pod
namespace: fargate-workloads
labels:
fargate: "true"
spec:
containers:
- name: nginx
image: nginx:latest
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
Deploy Deployment to Fargate
apiVersion: apps/v1
kind: Deployment
metadata:
name: fargate-app
namespace: fargate-workloads
spec:
replicas: 3
selector:
matchLabels:
app: my-app
fargate: "true"
template:
metadata:
labels:
app: my-app
fargate: "true"
spec:
containers:
- name: app
image: my-app:v1.0
resources:
requests:
cpu: 500m
memory: 1Gi
Important Notes
- Private Subnets Only: Fargate profiles require private subnets with NAT gateway or VPC endpoints
- Subnet Tagging: Subnets must have the tag
kubernetes.io/cluster/<cluster_name> = "shared"orowned - Resource Limits: Fargate requires explicit CPU and memory resource specifications
- Networking: Pods get their own ENI and private IP address
- Profile Limits: Each Fargate profile supports one namespace and up to 5 label selectors
- CoreDNS: For CoreDNS to run on Fargate, you need a specific Fargate profile for kube-system namespace
- Storage: Only supports ephemeral storage and Amazon EFS (not EBS)
- Creation Time: Fargate profile creation takes 3-5 minutes
Fargate Resource Specifications
CPU and Memory Combinations
Fargate supports specific CPU and memory combinations:
| vCPU | Memory Options |
|---|---|
| 0.25 | 0.5 GB, 1 GB, 2 GB |
| 0.5 | 1 GB, 2 GB, 3 GB, 4 GB |
| 1 | 2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB |
| 2 | Between 4 GB and 16 GB in 1 GB increments |
| 4 | Between 8 GB and 30 GB in 1 GB increments |
Best Practices
- Use Private Subnets: Always use private subnets for Fargate profiles
- Specify Resources: Always define CPU and memory requests/limits for Fargate pods
- Multiple Profiles: Create separate profiles for different workload types
- Label Strategy: Use consistent labeling for easy workload routing
- Cost Optimization: Use Fargate for variable workloads; consider EC2 for stable, predictable loads
- Monitoring: Use CloudWatch Container Insights for Fargate monitoring
- Logging: Configure Fargate logging to CloudWatch or Fluent Bit
- Security: Leverage pod-level IAM roles via IRSA
Cost Considerations
Fargate pricing is based on:
- vCPU resources (per hour)
- Memory resources (per GB per hour)
- Minimum charge duration: 1 minute
Cost comparison:
- Use Fargate: Variable workloads, batch jobs, development/testing
- Use EC2 Node Groups: Stable baseline workloads, cost-sensitive production workloads
CoreDNS on Fargate
To run CoreDNS on Fargate, create a specific profile:
module "fargate_coredns" {
source = "git@github.com:webuildyourcloud/terraform-aws-eks_fargate_profile.git"
name = "coredns"
cluster_name = module.eks_cluster.cluster_id
subnet_ids = module.vpc.private_subnet_ids
kubernetes_namespace = "kube-system"
kubernetes_labels = {
"k8s-app" = "kube-dns"
}
}
Then remove the eks.amazonaws.com/compute-type : ec2 annotation from CoreDNS pods.
Troubleshooting
Pods stuck in Pending state
- Verify subnet IDs are correct and private
- Check subnet tags include cluster name
- Ensure NAT gateway or VPC endpoints are configured
- Verify resource requests match Fargate configurations
Fargate profile creation fails
- Verify cluster name is correct
- Check IAM permissions for creating Fargate profiles
- Ensure subnets are in the same VPC as the cluster
Pods not matching Fargate profile
- Verify namespace matches
kubernetes_namespace - Check pod labels match
kubernetes_labels - Ensure no conflicting node selectors or taints
Monitoring and Logging
Enable Container Insights
aws eks update-cluster-config \
--name my-cluster \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'
Configure Fluent Bit for Fargate
Deploy AWS Fluent Bit DaemonSet for centralized logging from Fargate pods.
License
This module is provided as-is for use within your organization.