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