EKS Networking: VPC CNI and Load Balancing
Use the Amazon VPC CNI plugin so pods get native VPC IP addresses, and expose services with the AWS Load Balancer Controller.
EKS Networking: VPC CNI and Load Balancing is a free AWS Solutions Architect lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the AWS Solutions Architect learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Kubernetes Networking Basics
Kubernetes requires every pod to have a unique, routable IP address and for pods to communicate with each other without NAT. The Container Network Interface (CNI) plugin is responsible for assigning IPs and configuring network routes on worker nodes. Different Kubernetes platforms use different CNI implementations; AWS uses the Amazon VPC CNI plugin to integrate Kubernetes networking directly with the VPC layer.
Amazon VPC CNI Plugin
The Amazon VPC CNI plugin assigns each pod an IP address directly from your VPC's subnet CIDR range. This means pods are first-class VPC citizens — they can be accessed by other VPC resources, on-premises systems via VPN/Direct Connect, and security groups without any overlay network translation. Each EC2 worker node maintains a pool of secondary private IPs (one per ENI slot) that are assigned to pods as they schedule.
# Check the VPC CNI version installed in your cluster
kubectl describe daemonset aws-node -n kube-system | grep Image
# View the secondary IPs assigned to a node
aws ec2 describe-network-interfaces \
--filters 'Name=attachment.instance-id,Values=i-0abcdef1234567890' \
--query 'NetworkInterfaces[].PrivateIpAddresses[].PrivateIpAddress'ENI and IP Address Warm Pool
The VPC CNI plugin maintains a warm pool of pre-allocated IP addresses on each node to allow fast pod scheduling. When a node starts, the CNI attaches multiple ENIs and assigns secondary IPs up to the WARM_IP_TARGET or MINIMUM_IP_TARGET environment variables. The maximum number of pods a node can run is therefore limited by the instance's ENI count multiplied by the IPs per ENI, which varies by instance type.
# Check maximum pods supported by an instance type
aws ec2 describe-instance-types \
--instance-types m5.large \
--query 'InstanceTypes[].NetworkInfo.{MaxENIs:MaximumNetworkInterfaces,IPv4sPerENI:Ipv4AddressesPerInterface}'
# Max pods formula: (MaxENIs x (IPv4sPerENI - 1)) + 2
# m5.large: 3 ENIs x (10-1) + 2 = 29 podsSecurity Groups for Pods
By default, all pods on a node share the node's security group. With the Security Groups for Pods feature, you can assign individual security groups to specific pods using the SecurityGroupPolicy custom resource. This allows fine-grained network access control — for example, only a database pod can receive traffic on port 5432 from the API pod's security group. This feature requires the VPC CNI version 1.7.7 or later and a trunk ENI on the node.
# Define a SecurityGroupPolicy (custom resource)
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: db-pod-sg-policy
namespace: production
spec:
podSelector:
matchLabels:
role: database
securityGroups:
groupIds:
- sg-0db1234567890abcdKubernetes Service Types on EKS
Kubernetes Services expose a set of pods under a stable DNS name and IP. On EKS, the three relevant service types are: ClusterIP (internal cluster communication only), NodePort (opens a port on every node — rarely used on EKS), and LoadBalancer (provisions an AWS load balancer automatically). The LoadBalancer type is how most internet-facing EKS services are exposed.
# Expose a deployment with a LoadBalancer service
kubectl expose deployment my-api \
--type=LoadBalancer \
--name=my-api-svc \
--port=80 \
--target-port=8080
# Check the assigned AWS load balancer hostname
kubectl get svc my-api-svc -o wideAWS Load Balancer Controller
The AWS Load Balancer Controller is an open-source Kubernetes controller that manages ALB and NLB resources on behalf of EKS clusters. When you create a Kubernetes Ingress object, the controller provisions an Application Load Balancer. When you create a Service of type LoadBalancer with the correct annotations, it provisions a Network Load Balancer. The controller replaces the older in-tree Kubernetes load balancer provider.
# Install AWS Load Balancer Controller with Helm
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=my-cluster \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller \
--set region=us-east-1 \
--set vpcId=vpc-0abc1234def567890Kubernetes Ingress with ALB
An Kubernetes Ingress object defines HTTP/HTTPS routing rules — path-based and host-based — into your cluster. The AWS Load Balancer Controller reads Ingress objects annotated with kubernetes.io/ingress.class: alb and creates a corresponding Application Load Balancer with listener rules that match. This eliminates the need to manually create ALBs and target groups for each application service.
# Ingress YAML that creates an ALB
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
namespace: production
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
rules:
- http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 80NLB for TCP/UDP Workloads
When your workload requires TCP or UDP (not HTTP) — such as a game server, gRPC service, or database proxy — use the NLB instead of ALB. Annotate the Kubernetes Service with service.beta.kubernetes.io/aws-load-balancer-type: 'external' and service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: 'ip'. The controller provisions an NLB with pod IPs as direct targets, bypassing node-level port forwarding for lower latency.
# Service YAML that creates an NLB with IP targets
apiVersion: v1
kind: Service
metadata:
name: grpc-svc
namespace: production
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: 'external'
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: 'ip'
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
spec:
type: LoadBalancer
selector:
app: grpc-server
ports:
- port: 50051
targetPort: 50051
protocol: TCPDNS Resolution Within the Cluster
EKS runs CoreDNS as the cluster DNS provider. Every service gets a DNS name in the format service-name.namespace.svc.cluster.local, which resolves to the service's ClusterIP. Pods are also discoverable via DNS. CoreDNS is deployed as a Deployment (not a DaemonSet), and its replicas should be scaled based on cluster size. EKS manages CoreDNS as an add-on, allowing automated version upgrades.
# Verify DNS resolution from within a pod
kubectl run dns-test --image=busybox --rm -it --restart=Never -- \
nslookup kubernetes.default.svc.cluster.local
# Expected output: Name: kubernetes.default.svc.cluster.local
# Address: 10.100.0.1 (ClusterIP of the kubernetes service)Network Policies in EKS
Kubernetes NetworkPolicy objects define allow rules for pod-to-pod and pod-to-external traffic. By default, all pods in a cluster can communicate freely. To enforce zero-trust networking you can install the Amazon VPC CNI network policy controller (available since VPC CNI v1.14). Network policies are evaluated at the Linux kernel level using eBPF, providing high-performance enforcement without an overlay network.
# NetworkPolicy: allow traffic to api pods only from frontend pods
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-allow-frontend
namespace: production
spec:
podSelector:
matchLabels:
role: api
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 8080VPC CNI Troubleshooting Tips
Common EKS networking issues include IP address exhaustion (fix by enabling prefix delegation or adding larger subnets), pods stuck in Pending because the node has no available secondary IPs, and intermittent DNS resolution failures caused by insufficient CoreDNS replicas. Use kubectl describe pod to check events, kubectl describe node to see allocated IP counts, and CloudWatch Container Insights to monitor DNS error rates at cluster scale.
# Enable prefix delegation to increase pod density per node
kubectl set env daemonset aws-node \
-n kube-system \
ENABLE_PREFIX_DELEGATION=true \
WARM_PREFIX_TARGET=1
# Check current IP usage on a node
kubectl describe node ip-10-0-1-100.ec2.internal | grep -A5 'Allocatable'Quick Check
Test your understanding of AWS Solutions Architect (SAA-C03) concepts from this lesson.
Lesson Recap
In this lesson you learned: the Amazon VPC CNI plugin assigns native VPC IPs to every pod for seamless VPC integration, the AWS Load Balancer Controller provisions ALBs for HTTP Ingress and NLBs for TCP/UDP Services, and Security Groups for Pods enable pod-level network access control. Next up we explore IRSA to bind fine-grained IAM roles to Kubernetes service accounts.
Frequently asked questions
Is the “EKS Networking: VPC CNI and Load Balancing” lesson free?
Yes — the full text of “EKS Networking: VPC CNI and Load Balancing” is free to read here on the web, and the AWS Solutions Architect course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the AWS Solutions Architect course, upgrade to CoddyKit PRO.
What will I learn in “EKS Networking: VPC CNI and Load Balancing”?
Use the Amazon VPC CNI plugin so pods get native VPC IP addresses, and expose services with the AWS Load Balancer Controller. You practise AWS Solutions Architect with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start AWS Solutions Architect?
No prior experience is required. AWS Solutions Architect on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “EKS Networking: VPC CNI and Load Balancing” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this AWS Solutions Architect lesson?
Yes. Every AWS Solutions Architect lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- EKS Control Plane and Worker Nodes
- Fargate Profiles for Serverless Pods
- EKS Networking: VPC CNI and Load Balancing
- IAM Roles for Service Accounts (IRSA)