Amazon EKS — Fargate Profiles

4 minute read

EKS on Fargate lets you run Kubernetes pods without managing any EC2 instances. AWS provisions, scales, and patches the underlying compute for each pod. You define which pods should run on Fargate using Fargate profiles.


How Fargate Works with EKS

┌─────── Your Responsibility ───────┐    ┌─────── AWS Responsibility ────────┐
│                                    │    │                                    │
│  Pod definitions (YAML)            │    │  Compute provisioning              │
│  Fargate profile selectors         │    │  OS patching                       │
│  Resource requests (CPU/memory)    │    │  Scaling (per-pod)                 │
│  Application code                  │    │  Isolation (each pod = own VM)     │
│                                    │    │  ENI per pod                       │
└────────────────────────────────────┘    └────────────────────────────────────┘

Each Fargate pod runs in its own isolated micro-VM (using Firecracker). Pods don’t share compute with other pods — full tenant isolation.


Fargate Profile Selectors

A Fargate profile tells EKS: “Run pods matching these selectors on Fargate instead of EC2.”

Creating a Fargate Profile

aws eks create-fargate-profile \
  --cluster-name my-cluster \
  --fargate-profile-name dev-profile \
  --pod-execution-role-arn arn:aws:iam::123456789:role/eks-fargate-role \
  --subnets subnet-private-a subnet-private-b \
  --selectors '[
    {"namespace": "dev"},
    {"namespace": "batch", "labels": {"compute": "fargate"}}
  ]'

Using eksctl

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: my-cluster
  region: us-east-1

fargateProfiles:
  - name: dev-profile
    selectors:
      - namespace: dev
      - namespace: batch
        labels:
          compute: fargate

Selector Matching Rules

Selector Matches
namespace: dev All pods in the dev namespace
namespace: batch, labels: {compute: fargate} Pods in batch namespace WITH the label compute=fargate
namespace: kube-system System pods (CoreDNS) on Fargate

Rules:

  • Namespace is required in every selector
  • Labels are optional (further filter within the namespace)
  • Multiple selectors are OR’d — a pod matching any selector runs on Fargate
  • If a pod matches both a Fargate profile and an EC2 node group, Fargate takes priority

Fargate Pod Execution Role

Fargate pods need an IAM role for pulling images and sending logs:

# Trust policy
cat > fargate-trust.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "eks-fargate-pods.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "ArnLike": {
          "aws:SourceArn": "arn:aws:eks:us-east-1:123456789:fargateprofile/my-cluster/*"
        }
      }
    }
  ]
}
EOF

aws iam create-role \
  --role-name eks-fargate-role \
  --assume-role-policy-document file://fargate-trust.json

aws iam attach-role-policy --role-name eks-fargate-role \
  --policy-arn arn:aws:iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy

Fargate Pod Sizing

Fargate pods are sized based on your resource requests. AWS rounds up to the nearest supported configuration:

vCPU Memory Options
0.25 vCPU 0.5 GB, 1 GB, 2 GB
0.5 vCPU 1 GB, 2 GB, 3 GB, 4 GB
1 vCPU 2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB
2 vCPU 4 GB to 16 GB (1 GB increments)
4 vCPU 8 GB to 30 GB (1 GB increments)
8 vCPU 16 GB to 60 GB (4 GB increments)
16 vCPU 32 GB to 120 GB (8 GB increments)

If your pod requests 0.3 vCPU and 1 GB memory, Fargate provisions 0.5 vCPU / 1 GB and charges for that.

Tip: Set accurate resource requests. Over-requesting wastes money. Under-requesting still gets rounded up, but OOMKills become more likely.


Fargate Limitations

Limitation Details
DaemonSets Not supported — Fargate has no “nodes” for DaemonSets to target
Privileged containers Not supported — pods run in isolated micro-VMs
GPUs Not supported — no GPU instance types on Fargate
HostNetwork / HostPort Not supported
EBS volumes Not supported (use EFS instead for persistent storage)
StatefulSets Partially — you can use them but without EBS. Use EFS for storage
Startup time 30-60 seconds (cold start for new pods)
Max pods per cluster No hard limit, but Fargate has regional capacity limits
Subnets Only private subnets (Fargate pods can’t get public IPs)
Node affinity/selector Pods auto-get the eks.amazonaws.com/compute-type: fargate label

CoreDNS on Fargate

If your cluster runs only on Fargate (no EC2 nodes), you need a Fargate profile for CoreDNS:

aws eks create-fargate-profile \
  --cluster-name my-cluster \
  --fargate-profile-name coredns-profile \
  --pod-execution-role-arn arn:aws:iam::123456789:role/eks-fargate-role \
  --subnets subnet-private-a subnet-private-b \
  --selectors '[{"namespace": "kube-system", "labels": {"k8s-app": "kube-dns"}}]'

Then patch CoreDNS to remove the eks.amazonaws.com/compute-type: ec2 annotation:

kubectl patch deployment coredns -n kube-system \
  --type json \
  -p='[{"op": "remove", "path": "/spec/template/metadata/annotations/eks.amazonaws.com~1compute-type"}]'

Logging on Fargate

Fargate has a built-in Fluent Bit sidecar. Configure it with a ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-logging
  namespace: aws-observability
data:
  output.conf: |
    [OUTPUT]
        Name              cloudwatch_logs
        Match             *
        region            us-east-1
        log_group_name    /eks/fargate/my-cluster
        log_stream_prefix fargate-
        auto_create_group true

Create the namespace first:

kubectl create namespace aws-observability
kubectl apply -f logging-configmap.yaml

Fargate vs Managed Node Groups

Feature Fargate Managed Node Groups
Management Fully serverless AWS manages AMI/updates
Pricing Per-pod (vCPU + GB/hr) EC2 instance pricing
Startup time 30-60s cold start Instant (nodes always running)
DaemonSets Not supported Supported
GPU Not supported Supported
EBS Not supported Supported
Isolation Pod-level (micro-VM) Shared node
Best for Burst, batch, dev, regulated workloads Steady-state production

Cost Comparison (Example)

Pod requesting 0.5 vCPU, 1 GB memory, running 24/7:

Compute Monthly Cost (approx.)
Fargate (0.5 vCPU, 1 GB) ~$18/month
t3.medium (2 vCPU, 4 GB) shared ~$30/month but runs 4-8 pods

Fargate gets expensive at scale. For steady-state workloads, EC2 nodes with bin-packing are cheaper.


Best Practices

  1. Use Fargate for dev/test namespaces — no idle EC2 costs
  2. Use Fargate for batch Jobs — spin up, process, shut down
  3. Set accurate resource requests — Fargate charges by the nearest tier
  4. Use EFS (not EBS) for persistent storage on Fargate
  5. Don’t put everything on Fargate — steady-state production workloads are cheaper on EC2
  6. Plan for cold start latency — 30-60 seconds; not ideal for latency-sensitive real-time workloads
  7. Monitor costs closely — Fargate pricing can add up quickly with many small pods

Updated: