RAPID INCIDENT TRIAGE & ACTION PLAN•Performance
01. Error Signature
EKS Fargate ENI IP Exhaustion Monitor
02. Root Cause Vector

EKS Fargate pod sandbox creation fails when subnet CIDR exhaustion prevents ENI allocation, killing new pod scheduling entirely.

03. Rapid Prescription

Sort lock acquisition order deterministically, or configure explicit session timeouts.

Zero-Trust Client IDE/ Performance

EKS Fargate ENI IP Exhaustion Monitor

EKS Fargate pod sandbox creation fails when subnet CIDR exhaustion prevents ENI allocation, killing new pod scheduling entirely.

SYSTEM STATUS
CREDITS: 0 / 3
source.yaml(77L)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
apiVersion: v1
kind: ConfigMap
metadata:
  name: legacy-pci-fargate-config
  namespace: pci-secure-zone
  annotations:
    # TODO: Migrate to GitOps, but compliance says keep this for audit trail
    devops-bot/last-updated: "2022-11-30"
data:
  # OLD: maxPods: "10"  # Commented out during the 2023 scaling initiative
  maxPods: "110"  # Increased for Black Friday, never scaled back
  # VULNERABILITY: This annotation forces ENI attachment per pod, ignoring subnet size, leading to IP exhaustion under load.
  eks.amazonaws.com/fargate-profile: legacy-app-profile
  # Secret injected as env var placeholder (DO NOT COMMIT)
  DATABASE_URI: "postgresql://prod-db-user:AKIATESTDUMMYEXAMPLEKEY123456@prod-cluster.cluster-abcdefghijklm.us-east-1.rds.amazonaws.com:5432/legacy_pci_db"
  STRIPE_API_KEY: "sk_live_TESTDUMMYEXAMPLEKEY1234567890abcdef"
  # RSA key for internal service auth (rotated quarterly)
  INTERNAL_SSH_KEY: |
    -----BEGIN RSA PRIVATE KEY-----
    MIIEpAIBAAKCAQEAxXp9Kf7jklweoiuwerlkjsdf9834kjlksdfj98sdfkjwe9r8
    sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834k
    jlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkf
    jlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj
    98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjf
    lksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfk
    jwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf
    9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8
    sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kj
    lksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfj
    lksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj
    98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjf
    lksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfk
    jwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf
    9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8
    sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kj
    lksdfj98sdfkjwe9r8sldkfjlksdjflksjdf9834kjlksdfj98sdfkjwe9r8sldkfj
    -----END RSA PRIVATE KEY-----
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: legacy-checkout-service
  namespace: pci-secure-zone
  labels:
    app: legacy-checkout
    tier: backend
spec:
  replicas: 100  # Auto-scaled from HPA, but baseline kept high for "performance"
  selector:
    matchLabels:
      app: legacy-checkout
  template:
    metadata:
      labels:
        app: legacy-checkout
      annotations:
        # This forces each pod onto a dedicated ENI for "security isolation" per PCI
        security.internal/eni-per-pod: "true"
    spec:
      containers:
      - name: app
        image: my-registry.internal/legacy-api:v3.7.1-stable
        env:
        - name: AWS_ACCESS_KEY_ID
          value: "AKIATESTDUMMYEXAMPLEKEY123456"
        - name: AWS_SECRET_ACCESS_KEY
          value: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
      nodeSelector:
        eks.amazonaws.com/compute-type: fargate
AI Audit Console
> Waiting for pre-flight audit...
HybridRedactor Engine: Active
TECHNICAL WHITEPAPER & ARCHITECTURE SPEC•Updated 2026

Fixing EKS Fargate 'Pod Sandbox Creation Failed' Due to ENI IP Exhaustion

Threat/Impact Level: HIGH | Downtime Risk: HIGH | Time to Fix: 15–45 mins depending on subnet re-IP strategy

TL;DR

  • What broke: Fargate can't allocate an ENI for the pod sandbox because every available IP in the configured subnet(s) is consumed. New pods are dead on arrival — FailedCreatePodSandBox in events, nothing scheduled.
  • How to fix it: Add secondary CIDR blocks to your VPC, provision new larger subnets, update your Fargate profile to include them, and optionally enable prefix delegation on the VPC CNI.
  • Shortcut: Use our Client-Side Sandbox above to auto-refactor your Fargate profile and Terraform VPC config — it detects exhausted CIDRs and outputs corrected subnet allocations without sending your ARNs anywhere.

▼ 🔍 Root Cause Breakdown & Kernel Diagnostics [Click to Expand Deep Dive]

The Incident (What Does the Error Mean?)

You'll see this in kubectl describe pod <pod-name>:

Warning  FailedCreatePodSandBox  kubelet  Failed to create pod sandbox:
  rpc error: code = Unknown desc = failed to set up sandbox container
  "abc123" network for pod "my-service-7d9f8b-xkqzp":
  networkPlugin cni failed to set up pod
  "my-service-7d9f8b-xkqzp_production" network:
  add cmd: failed to assign an IP address to container

And in CloudWatch /aws/eks/<cluster>/cluster or VPC Flow Logs you'll see ENI attachment failures with InsufficientFreeAddressesInSubnet.

Immediate consequence: Every new Fargate pod targeting the exhausted subnet fails to start. Deployments hang at 0/1 Running. HPA scale-out events silently fail. If this is your only AZ subnet in a Fargate profile, your entire workload loses the ability to self-heal or scale.


▼ 🔍 Detailed Impact & Blast Radius Analysis [Click to Expand Deep Dive]

The Attack Vector / Blast Radius

Fargate is not EC2. There is no node-level IP sharing. Each Fargate pod consumes at minimum 1 ENI and 1 primary IP from your subnet. A /24 gives you 251 usable IPs minus AWS-reserved addresses (5 per subnet). At scale:

  • 200-pod namespace + ALB + NAT + other ENIs = subnet full, zero warning
  • No pre-exhaustion alerting exists by default. AWS does not emit a CloudWatch metric for "subnet IP utilization" out of the box until you build it yourself
  • Cascading failure: A rolling deployment tries to bring up new pods before terminating old ones (maxSurge). Both old and new pods compete for IPs. The deployment deadlocks. Old pods won't terminate because Kubernetes waits for new ones to be Ready. New ones can't start. You're stuck.
  • Multi-AZ configs where only one AZ subnet is exhausted produce intermittent failures that are hell to diagnose — some pods start, some don't, depending on which AZ the scheduler targets

How to Fix It

Basic Fix — Add a New Subnet and Update the Fargate Profile

The fastest path out of a live outage: provision a new subnet in the same AZ with a larger CIDR, then add it to your Fargate profile.

# terraform/vpc.tf

- resource "aws_subnet" "fargate_primary" {
-   vpc_id            = aws_vpc.main.id
-   cidr_block        = "10.0.1.0/24"   # 251 IPs — exhausted
-   availability_zone = "us-east-1a"
- }

+ resource "aws_subnet" "fargate_primary" {
+   vpc_id            = aws_vpc.main.id
+   cidr_block        = "10.0.1.0/24"
+   availability_zone = "us-east-1a"
+ }
+
+ resource "aws_subnet" "fargate_overflow" {
+   vpc_id            = aws_vpc.main.id
+   cidr_block        = "10.0.16.0/20"  # 4091 IPs — room to grow
+   availability_zone = "us-east-1a"
+   tags = {
+     Name = "fargate-overflow-1a"
+   }
+ }
# terraform/fargate_profile.tf

 resource "aws_eks_fargate_profile" "default" {
   cluster_name           = aws_eks_cluster.main.name
   fargate_profile_name   = "default"
   pod_execution_role_arn = aws_iam_role.fargate_pod_execution.arn

   subnet_ids = [
-    aws_subnet.fargate_primary.id
+    aws_subnet.fargate_primary.id,
+    aws_subnet.fargate_overflow.id
   ]

   selector {
     namespace = "production"
   }
 }

⚠️ Fargate profile updates that change subnet_ids require profile recreation in some Terraform provider versions. Plan for a brief scheduling gap or use blue/green profile swap.


Enterprise Best Practice — Secondary CIDR + VPC CNI Prefix Delegation

If your VPC CIDR space is itself exhausted (common in large orgs with RFC 1918 carve-outs), attach a secondary CIDR from the 100.64.0.0/10 CG-NAT range (AWS supports this) and build Fargate subnets there.

# terraform/vpc.tf

 resource "aws_vpc" "main" {
   cidr_block = "10.0.0.0/16"
 }

+ resource "aws_vpc_ipv4_cidr_block_association" "cgnat_secondary" {
+   vpc_id     = aws_vpc.main.id
+   cidr_block = "100.64.0.0/16"  # CG-NAT range, AWS-supported secondary
+ }
+
+ resource "aws_subnet" "fargate_cgnat_1a" {
+   vpc_id            = aws_vpc.main.id
+   cidr_block        = "100.64.0.0/18"  # 16,379 IPs
+   availability_zone = "us-east-1a"
+   depends_on        = [aws_vpc_ipv4_cidr_block_association.cgnat_secondary]
+ }
+
+ resource "aws_subnet" "fargate_cgnat_1b" {
+   vpc_id            = aws_vpc.main.id
+   cidr_block        = "100.64.64.0/18"
+   availability_zone = "us-east-1b"
+   depends_on        = [aws_vpc_ipv4_cidr_block_association.cgnat_secondary]
+ }

Also add a CloudWatch alarm on available IPs so you never get blindsided again:

+ resource "aws_cloudwatch_metric_alarm" "subnet_ip_exhaustion" {
+   alarm_name          = "fargate-subnet-ip-low-${each.key}"
+   comparison_operator = "LessThanThreshold"
+   evaluation_periods  = 2
+   metric_name         = "AvailableIPAddresses"
+   namespace           = "AWS/EC2"
+   period              = 300
+   statistic           = "Minimum"
+   threshold           = 50   # Alert at 50 IPs remaining
+   dimensions = {
+     SubnetId = each.value
+   }
+   alarm_actions = [aws_sns_topic.ops_alerts.arn]
+ }

💡 Tired of pasting proprietary infrastructure configs into public LLMs? Generic AI interfaces log your company's ARNs, connection strings, and private keys. StackEngine enforces client-side zero-trust boundaries—the sandbox above executes 100% locally in your browser. Drop your broken manifest above to redact secrets locally and synthesize deterministic patch drafts with your own API key.

(For CI/CD pipeline automation, install via npm i -g stackengine).


▼ 🔍 Continuous Pipeline Governance & CI/CD Guardrails [Click to Expand Deep Dive]

Prevention in CI/CD

1. Checkov — block small Fargate subnets at plan time:

# checkov custom check: enforce minimum /20 for Fargate subnets
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
import ipaddress

class FargateSubnetSizeCheck(BaseResourceCheck):
    ID = "CKV_CUSTOM_FARGATE_SUBNET_SIZE"
    NAME = "Fargate subnets must be /20 or larger"
    SUPPORTED_RESOURCES = ["aws_subnet"]
    BLOCK_TYPE = "resource"

    def scan_resource_conf(self, conf):
        cidr = conf.get("cidr_block", [""])[0]
        try:
            network = ipaddress.IPv4Network(cidr, strict=False)
            return network.prefixlen <= 20  # /20 or larger = PASS
        except ValueError:
            return False

2. OPA/Conftest — gate Fargate profile PRs:

# policy/fargate_subnet.rego
package fargate

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_eks_fargate_profile"
  count(resource.change.after.subnet_ids) < 2
  msg := sprintf(
    "Fargate profile '%v' must reference subnets in at least 2 AZs to prevent single-AZ IP exhaustion.",
    [resource.name]
  )
}

3. GitHub Actions gate — run before terraform apply:

- name: Conftest Fargate Policy Check
  run: |
    terraform show -json plan.tfplan > plan.json
    conftest test plan.json --policy policy/fargate_subnet.rego

4. Ongoing: Set up a Lambda on a cron (or use AWS Config rule vpc-sg-open-only-to-authorized-ports as a template pattern) to publish AvailableIPAddresses per subnet to a custom CloudWatch namespace. Feed it into your runbook alerting. Treat subnet IP utilization above 70% as a P2 ticket, not a P0 fire.

Official Grounding & Normative Specifications

The technical diagnostics, error recovery protocols, and prevention patterns in this specification are grounded in official vendor documentation and standards:

Diagnostic & Architectural FAQ

Q1.Why does each EKS Fargate pod consume a full ENI IP instead of sharing like EC2 nodes?
Fargate's isolation model gives each pod its own dedicated microVM with its own network namespace. There is no node-level ENI sharing or VPC CNI IPAMD pooling. Every pod requires one primary IP from your subnet at launch time, which is why IP exhaustion hits Fargate deployments faster than equivalent EC2-based node groups. This is the fundamental architectural flaw you're fighting—a silent, predictable killer of production availability.
Q2.Can I fix this without downtime by just expanding the existing subnet CIDR?
No. AWS does not allow you to resize an existing subnet's CIDR block after creation—this is a hard platform constraint. Your options are: (1) add a new larger subnet in the same AZ and update the Fargate profile to include it, (2) attach a secondary VPC CIDR and create new subnets from it, or (3) delete and recreate the subnet if it's empty, which is only viable in non-production environments. Each manual step is a high-risk, error-prone operation that can introduce security gaps and cause cascading failures. Drop the broken manifest into the StackEngine Local Sandbox above to automatically compile a zero-trust fix with validated blast radius containment.
Q3.How do I get alerted before subnet IPs are fully exhausted on Fargate?
Create a CloudWatch Metric Alarm on the 'AvailableIPAddresses' metric under the 'AWS/EC2' namespace, scoped to each Fargate subnet ID. Set a threshold alarm at 50–100 IPs remaining with a minimum evaluation period of 2x5 minutes. Wire it to SNS. AWS does not alert on this by default—you must instrument it explicitly. Terraform resource 'aws_cloudwatch_metric_alarm' is the standard path. Doing this manually across large mono-repos or at scale is a compliance and consistency nightmare. Deploy the StackEngine CI/CD Automator (Team Edition) for on-prem, automated pull request generation with Maker-Checker review and enterprise-grade policy enforcement.