max Pods is higher than the node's ENIs can give IPs for
Skipping ENI allocation as the max ENI limit is already reached
What you see
$ kubectl get pods -n shop -o wide --field-selector spec.nodeName=ip-10-0-1-23.ec2.internal
NAME READY STATUS NODE
web-7d9f8c6b5-2bq7d 1/1 Running ip-10-0-1-23.ec2.internal
...
web-7d9f8c6b5-x2k4q 0/1 ContainerCreating ip-10-0-1-23.ec2.internal# /var/log/aws-routed-eni/ipamd.log on the node
{"level":"debug","caller":"ipamd/ipamd.go:1031","msg":"Skipping ENI allocation as the max ENI limit is already reached"}
{"level":"error","caller":"datastore/data_store.go:858","msg":"DataStore has no available IP/Prefix addresses"}The scheduler only checks the node's max Pods. If that's set higher than the instance's network interfaces can hold IPs for, Pods keep landing on a node that has no IP left to give them. An m5.large has 3 ENIs with 10 IPs each; one per ENI is the ENI's own, so 27 Pods can get an IP, and its default max Pods is 29 (27 plus 2 host-network Pods, aws-node and kube-proxy).
Confirm
# The kubelet's max Pods, and the instance type
kubectl get node ip-10-0-1-23.ec2.internal -o jsonpath='{.status.allocatable.pods} {.metadata.labels.node\.kubernetes\.io/instance-type}{"\n"}'
# ENIs per instance, and IPv4 addresses per ENI
aws ec2 describe-instance-types --instance-types m5.large \
--query 'InstanceTypes[].NetworkInfo.[MaximumNetworkInterfaces,Ipv4AddressesPerInterface]' --output text
# Pods on the node that need a VPC IP (host-network Pods use the node's IP)
kubectl get pods -A --field-selector spec.nodeName=ip-10-0-1-23.ec2.internal,status.phase=Running -o custom-columns=NAME:.metadata.name,HOSTNET:.spec.hostNetwork --no-headers | grep -vc trueHere it's the instance's limit, not the subnet: the subnet still has free IPs, and the ipamd log has no EC2 error, just the ENI limit. Max Pods gets set too high by a custom --max-pods or maxPods in node user data, spec.kubelet.maxPods in a Karpenter EC2NodeClass, or by turning prefix delegation off (or custom networking on) without replacing the nodes.
Fix
- Make max Pods match the IPs: work it out with the EKS
max-pods-calculator.shscript (it takes the instance type, the VPC CNI version, and flags for prefix delegation and custom networking), and set that on new nodes. Managed node groups that use the EKS AMI without a custom AMI in the launch template set it for you. In Karpenter, removemaxPods: with the AL2, AL2023 and Bottlerocket AMI families Karpenter then calculates it from the ENI limits. - Or give the node more IPs: turn on prefix delegation (
ENABLE_PREFIX_DELEGATION=true, Nitro instances only). Each ENI slot then holds a /28 prefix of 16 addresses, so a higher max Pods is real. Only new nodes get the new max Pods; replace the old ones. - Custom networking: the primary ENI no longer hosts Pods, so an
m5.largegives (3 − 1) × (10 − 1) + 2 = 20 Pods, not 29. Lower max Pods to match (with Karpenter, set itsreservedENIssetting to1), or pair it with prefix delegation.
Prevent
- Never set max Pods by hand without the calculator, and change it in the same rollout as any VPC CNI mode change.
- Choose instance types for Pod count as well as CPU and memory; small instances run out of IPs first.