# 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 ```hcl 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 ```hcl # 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](https://github.com/cloudposse/terraform-null-label) - Resource naming ## Pod Selection Fargate profiles use selectors to determine which pods run on Fargate: ### Namespace-Only Selection ```hcl kubernetes_namespace = "my-namespace" kubernetes_labels = {} ``` All pods in `my-namespace` will run on Fargate. ### Namespace + Label Selection ```hcl 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: ```yaml 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 ```yaml 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 1. **Private Subnets Only**: Fargate profiles require private subnets with NAT gateway or VPC endpoints 2. **Subnet Tagging**: Subnets must have the tag `kubernetes.io/cluster/ = "shared"` or `owned` 3. **Resource Limits**: Fargate requires explicit CPU and memory resource specifications 4. **Networking**: Pods get their own ENI and private IP address 5. **Profile Limits**: Each Fargate profile supports one namespace and up to 5 label selectors 6. **CoreDNS**: For CoreDNS to run on Fargate, you need a specific Fargate profile for kube-system namespace 7. **Storage**: Only supports ephemeral storage and Amazon EFS (not EBS) 8. **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 1. **Use Private Subnets**: Always use private subnets for Fargate profiles 2. **Specify Resources**: Always define CPU and memory requests/limits for Fargate pods 3. **Multiple Profiles**: Create separate profiles for different workload types 4. **Label Strategy**: Use consistent labeling for easy workload routing 5. **Cost Optimization**: Use Fargate for variable workloads; consider EC2 for stable, predictable loads 6. **Monitoring**: Use CloudWatch Container Insights for Fargate monitoring 7. **Logging**: Configure Fargate logging to CloudWatch or Fluent Bit 8. **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: ```hcl 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 ```bash 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.