How to Create Kubernetes Cluster and Security Groups for Pods in AWS EKS: Complete Tutorial
By Braincuber Team
Published on March 5, 2026
In the standard EKS networking setup, every pod on a node inherits the same security group. Ten different applications on one node. Same network permissions. Your database pod and your frontend pod — identical access rules. That's not security. That's a liability. Amazon EKS Security Groups for Pods changes this by assigning dedicated security groups to individual pods based on their specific needs. A payment processing pod gets strict database access. A logging pod only reaches your log aggregation service. A frontend pod only touches the internet. Same node, completely different security profiles. This complete tutorial walks you through implementing pod-level security groups from scratch — cluster creation to validated, tested deployment.
What You'll Learn:
- How traditional EKS networking works and why it's not enough
- How Security Groups for Pods assigns dedicated ENIs to individual pods
- How to set up IAM roles, VPC, and networking infrastructure
- How to create an EKS cluster with managed node groups
- How to configure pod-level security groups and database access
- How to enable CNI plugin branch networking for pod ENIs
- How to test with authorized (green) and unauthorized (red) pod access
Why Node-Level Security Is a Problem
In traditional EKS, every EC2 worker node gets assigned a security group. All pods on that node inherit the same settings. If one pod needs database access and another shouldn't have it — you can't enforce that distinction. The security boundary exists at the node level, creating a coarse-grained model where all pods share identical network permissions.
Pod-Level Security Groups
Assign dedicated security groups to individual pods using SecurityGroupPolicy CRDs. Each pod gets its own Elastic Network Interface (ENI) with custom security group assignments — true application-level network isolation.
Dedicated ENI Per Pod
An ENI is a virtual network card. When assigned to a pod, that pod gets its own dedicated network identity — separate IP address, security groups, and network settings — independent from the node it runs on.
VPC Resource Controller
An AWS component that watches for pods matching your SecurityGroupPolicy. When a matching pod is created, it provisions ENIs, attaches security groups, and configures network interfaces — automatically handling cleanup on pod deletion.
AWS VPC CNI Plugin
Enhanced to support branch networking — attaches ENIs to pod network namespaces, configures routing rules, and ensures traffic flows through dedicated interfaces rather than the node's primary network interface.
Step by Step: Building the Infrastructure
Set Up IAM Roles and Policies
Create IAM roles for the EKS cluster and worker nodes. The cluster role needs AmazonEKSClusterPolicy. The node role needs AmazonEKSWorkerNodePolicy, AmazonEKS_CNI_Policy, and AmazonEC2ContainerRegistryReadOnly. Attach trust policies that allow EKS and EC2 to assume these roles. These permissions are the foundation — without them, pods can't get ENIs assigned and security groups can't be attached.
Create VPC and Networking Infrastructure
Build a VPC with public and private subnets across multiple availability zones. Configure an Internet Gateway for public subnet access and NAT Gateways for private subnet outbound traffic. Tag subnets with the required EKS tags for load balancer discovery. The networking setup must support ENI provisioning — each pod with a custom security group gets its own network interface, requiring sufficient IP address space in your subnets.
Create the EKS Cluster and Node Group
Create the EKS cluster using the AWS CLI or Terraform, specifying your VPC subnets and cluster IAM role. Then create a managed node group with instance types that support multiple ENIs (t3.medium supports 3, m5.large supports 4). The VPC CNI plugin uses these additional ENI slots to create branch interfaces. Configure cluster access entries for management. Instance type selection directly affects how many pods can receive custom security groups.
Configure Security Groups and Database
Create pod-level security groups that will be assigned to specific pods. Create a database security group with ingress rules that only allow connections from the pod security group — not from the node security group. Set up an RDS instance in private subnets with the database security group. Configure inter-service communication rules. This is where the magic happens — the database explicitly allows traffic only from pods carrying the right security group.
Enable CNI Plugin Pod ENI Support
Patch the aws-node DaemonSet to enable the ENABLE_POD_ENI environment variable. This activates branch networking in the VPC CNI plugin, allowing it to provision dedicated ENIs for pods. Restart the aws-node pods and verify the configuration. Without this step, the CNI plugin won't create branch interfaces and pods will continue using the node's security group. Verify with troubleshooting checks for trunk interface creation on nodes.
Create SecurityGroupPolicy CRDs
Create a SecurityGroupPolicy custom resource that tells Kubernetes which pods should receive which security groups. Use standard label selectors to identify pods, then specify AWS security group IDs. When a pod matching the labels is created, the VPC Resource Controller automatically provisions the ENI and attaches the specified security groups. Create Kubernetes Secrets for database connectivity so authorized pods can connect securely.
Test with Authorized and Unauthorized Pods
Deploy a "green" pod with labels matching the SecurityGroupPolicy — it should connect to the database successfully. Deploy a "red" pod without matching labels — it should be denied database access even though it runs on the same node. Verify ENI assignments show the green pod has a dedicated branch ENI while the red pod uses the node's primary interface. This test confirms true pod-level security isolation is working.
# SecurityGroupPolicy — Assign Security Groups to Pods
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: db-access-policy
namespace: my-app
spec:
podSelector:
matchLabels:
role: db-access # Only pods with this label
securityGroups:
groupIds:
- sg-0abc123def456789 # Pod security group
- sg-0xyz987wvu654321 # Cluster security group
# Green Pod (Authorized) — Gets custom ENI + SG
apiVersion: v1
kind: Pod
metadata:
name: green-pod
labels:
role: db-access # Matches SecurityGroupPolicy
spec:
containers:
- name: app
image: postgres:15
command: ["psql", "-h", "db-endpoint", "-U", "admin"]
# Red Pod (Unauthorized) — Uses node's default SG
apiVersion: v1
kind: Pod
metadata:
name: red-pod
labels:
role: frontend # Does NOT match policy
spec:
containers:
- name: app
image: postgres:15
command: ["psql", "-h", "db-endpoint", "-U", "admin"]
# Connection will be REFUSED
ENI Limits Matter
EC2 instances have hard limits on ENIs. A t3.medium supports 3 ENIs, an m5.large supports 4. Each pod with a custom security group consumes one branch ENI slot. If you run out of ENI capacity, new pods matching the SecurityGroupPolicy will remain pending. Choose your instance types based on how many pods need custom security groups — not just compute requirements. This is the most common gotcha we see in production deployments.
Frequently Asked Questions
What are Security Groups for Pods in EKS?
Security Groups for Pods is an EKS feature that enables fine-grained network security at the pod level. Instead of all pods inheriting the node's security group, individual pods can get dedicated Elastic Network Interfaces with custom security group assignments using SecurityGroupPolicy CRDs.
How many ENIs can an EC2 instance support?
ENI limits vary by instance type. A t3.medium supports 3 ENIs, an m5.large supports 4. Each pod needing a custom security group consumes one branch ENI slot. Choose instance types based on both compute requirements and the number of pods needing custom security groups.
What is the VPC CNI plugin and why is it needed?
The AWS VPC CNI plugin handles low-level networking on worker nodes. When ENABLE_POD_ENI is set, it supports branch networking — attaching dedicated ENIs to pods, configuring routing rules, and ensuring traffic flows through dedicated interfaces. Without it, pods can't receive individual security groups.
What happens if a pod doesn't match any SecurityGroupPolicy?
Pods without matching SecurityGroupPolicy labels continue using the node's default security group and primary network interface — the traditional EKS networking model. Only pods with labels matching a SecurityGroupPolicy receive dedicated ENIs and custom security groups.
How do I clean up resources after testing?
Clean up in reverse order: Kubernetes resources first, then RDS instances, then EKS cluster deletion, management instance cleanup, VPC infrastructure removal (NAT gateways, subnets, route tables, Internet Gateway, VPC), and finally IAM role and policy cleanup. Deleting in the wrong order causes dependency errors.
Running Kubernetes Without Pod-Level Security?
We'll audit your EKS cluster security, implement pod-level security groups, configure proper IAM roles and CNI plugins, and validate the setup with authorized vs unauthorized access tests. Stop sharing security groups across unrelated workloads.
