Did you know? Pods can have public IP address and a dedicated security group
Summary
Recently I was working on deploying telephony systems on AWS EKS, While doing so I realized that running media servers based on RTP (Real-time Transport Protocol) behind a NAT gateway is not a feasible option.
Problem
For RTP to work both the ends should be able to communicate directly over a Network (Internet / Intranet).
The AWS NAT Gateway doesn't allow ingress traffic to flow in, making it not possible to handle real-time streaming in a private subnet. image ref
An Easy Solution:
An easy solution would be to make an EKS worker node public, open up the security groups, and voila – things would start working.
Security issues with this solution:
However, this approach comes with a significant security flaw. RTP, by nature, requires a large range of ports to enable concurrent streaming. To achieve this, around 10,000 ports would need to be whitelisted in the security group. If higher concurrency is required, even more ports would be necessary.
This scenario opens up ports used by NodePort, potentially granting unwanted access to your environment.
The Ideal Solution:
- The pod has a Public static IP
- The pod has a dedicated network interface
- The pod has a dedicated Security Group
If the above conditions are met it will make the environment a reliable and secure one.
How to achieve this is AWS EKS
Prerequisite
- AWS EKS Cluster with AWS VPC-CNI
- Elastic IP
- Security Group
Step1: Enabling dedicated Network interface for pods.
The first step is to configure VPC-CNI to assign a dedicated network interface to a pod.
To do so add the following variable to the aws-node daemonset
"ENABLE_POD_ENI": "true"
If you are using AWS Managed VPC-CNI add the following to the advanced configuration
{
"env": {
"ENABLE_POD_ENI": "true"
}
}
Once this change is implemented the CNI (VPC-CNI) is ready to assign specific network interfaces to pods.
By default nothing will change all the existing and newly created will run and behave as expected.
Step2: Assigning Security Group to the pod
AWS offers a CRD(custom resource definition) vpcresources.k8s.aws/v1beta1
using this a SecurityGroupPolicy
can be created as follows.
cat > securitygrouppolicy.yaml <<EOF
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: media-stream-sg-policy
namespace: myns
spec:
podSelector:
matchLabels:
app: media-servers
securityGroups:
groupIds:
- sg-e3edxxxxx
EOF
The security group sg-e3edxxxxx
is expected to be existing in the VPC
Apply the manifest
kubectl apply -f securitygrouppolicy.yaml
Create a pod with label app: media-servers
cat > pod.yaml <<EOF
# This is a sample pod
apiVersion: v1
kind: Pod
metadata:
labels:
app: media-servers
name: media-servers-pod
namespace: myns
spec:
containers:
image: public.ecr.aws/docker/library/nginx:stable-alpine
EOF
Apply the manifest
kubectl apply -f pod.yaml
Once the pod is running state get the IP address of the pod.
# To get the IP address
kubectl get pods -n myns -o wide
# output
#NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
#media-servers-pod 1/1 Running 0 5m57s 110.46.35.231 ip-110-46-4-191.eu-west-1.compute.internal <none> <none>
Copy the IP address and look it up on the AWS Console EC2 > Network & Security > Network interfaces
This IP now will be associated to a dedicated Network Interface which also has the security group attached to it.
Now you have a pod with a dedicated network interface and a security group attached to it
- Note the interface ID.
Step3: Assigning Elastic IP to the pod
By default a Public IP is not associated to the network interface as well as you need a set of static IP so that the external world can communicate with [ Helps with whitelisting ]
Goto AWS Console EC2 > Elastic IP
Allocate a new IP or use an existing one.
Once the Elastic IP is allocated, Associate the IP address with the network interface obtained in step2.
Lets make it simpler
Run the following command to achieve the binding easily
ALLOCATION_ID="eipalloc-xxxx" # Get it from the Elastic IP Description
POD_IP="110.46.35.231"
AWS_REGION="eu-west-1"
aws ec2 associate-address --allocation-id $ALLOCATION_ID --network-interface-id $(aws ec2 describe-network-interfaces --filters "Name=private-ip-address,Values=$POD_IP" --query "NetworkInterfaces[].NetworkInterfaceId" --output text --no-paginate) --private-ip-address $POD_IP --allow-reassociation
The above command can be run in an init-container
to make sure the IP is always bound to the pod.
Top comments (0)