AWS EKS DNS Services Guide for Network Engineers
Note: This guide is specifically designed for network engineers who may not have extensive container experience. We'll explain EKS (Elastic Kubernetes Service) components and how they relate to traditional networking concepts you already know.
Container and EKS Fundamentals for Network Engineers
What is EKS and How Does it Differ from ECS?
EKS (Elastic Kubernetes Service) is AWS's managed Kubernetes service. Think of it as AWS managing the control plane (like a network controller) while you manage the worker nodes (like switches/routers in your network).
ECS (Elastic Container Service) is AWS's proprietary container orchestration service. It's simpler but less flexible than EKS.
Key Difference: EKS uses Kubernetes (open-source, industry standard), while ECS uses AWS's proprietary orchestration. For DNS services, EKS provides more granular control similar to how you might configure DNS in a traditional network.
EKS Components - Network Engineer Perspective
graph TB
A[EKS Cluster
Control Plane] --> B[Worker Node 1]
A --> C[Worker Node 2]
A --> D[Worker Node 3]
B --> E[Pod 1
Application Container]
B --> F[Pod 2
Application Container]
C --> G[Pod 3
Application Container]
D --> H[Pod 4
Application Container]
I[AWS Load Balancer
Controller] --> J[Application Load Balancer]
J --> K[Target Group]
K --> E
K --> F
K --> G
K --> H
L[CoreDNS
DNS Service] --> M[kube-dns Service]
M --> N[DNS Queries from Pods]
style A fill:#ff9900,stroke:#232f3e,stroke-width:3px,color:#fff
style L fill:#146eb4,stroke:#232f3e,stroke-width:2px,color:#fff
style J fill:#28a745,stroke:#232f3e,stroke-width:2px,color:#fff
EKS Architecture Explained:
• Control Plane: Like your network management system - AWS manages this for you
• Worker Nodes: Similar to your switches/routers - EC2 instances that run your applications
• Pods: Think of these as VLANs or network segments containing your applications
• CoreDNS: The DNS server for your cluster (like your internal DNS servers)
• Load Balancer Controller: Routes traffic to healthy pods (like your F5 or NetScaler)
DNS in EKS - Deep Dive
DNS Traffic Flow in EKS
sequenceDiagram
participant Client as External Client
participant ALB as Application Load Balancer
participant Pod as Application Pod
participant CoreDNS as CoreDNS Pod
participant ExtDNS as External DNS
Client->>ALB: DNS Query for app.example.com
ALB->>Pod: Forward to healthy pod
Pod->>CoreDNS: Internal DNS Query (service.namespace.svc.cluster.local)
CoreDNS->>CoreDNS: Check local cache
CoreDNS->>Pod: Return service IP
Pod->>ExtDNS: External DNS Query (api.external.com)
ExtDNS->>Pod: Return external IP
Pod->>ALB: Response with data
ALB->>Client: Final response
DNS Flow Explanation:
This sequence shows how DNS queries work in EKS:
1. External clients query your application through Route 53 or external DNS
2. Application Load Balancer receives the request and forwards to healthy pods
3. Pods use CoreDNS for internal service discovery (finding other services in the cluster)
4. CoreDNS resolves internal Kubernetes service names to IP addresses
5. External DNS queries (like third-party APIs) go through the node's DNS configuration
CoreDNS Configuration Architecture
graph LR
A[CoreDNS ConfigMap] --> B[Corefile Configuration]
B --> C[kubernetes Plugin]
B --> D[forward Plugin]
B --> E[cache Plugin]
B --> F[errors Plugin]
C --> G[Service Discovery
cluster.local]
D --> H[Upstream DNS
168.63.129.16]
E --> I[DNS Cache
30 seconds]
F --> J[Error Logging]
K[kube-dns Service] --> L[CoreDNS Deployment]
L --> M[CoreDNS Pod 1]
L --> N[CoreDNS Pod 2]
style A fill:#ff9900,stroke:#232f3e,stroke-width:2px,color:#fff
style K fill:#146eb4,stroke:#232f3e,stroke-width:2px,color:#fff
CoreDNS Architecture:
• ConfigMap: Stores DNS configuration (like your DNS server config files)
• Corefile: Main configuration file defining DNS behavior
• kubernetes Plugin: Handles internal service discovery
• forward Plugin: Forwards external queries to upstream DNS
• kube-dns Service: ClusterIP service that pods use for DNS (like your internal DNS VIP)
Setup Commands and Configuration Order
🔧 Setup Order Diagram
graph TD
A[1Create EKS Cluster] --> B[2Configure kubectl]
B --> C[3Install AWS Load Balancer Controller]
C --> D[4Configure CoreDNS]
D --> E[5Deploy External DNS]
E --> F[6Configure Route 53]
F --> G[7Deploy Applications]
G --> H[8Configure DNS Policies]
style A fill:#ff9900,stroke:#232f3e,stroke-width:2px,color:#fff
style H fill:#28a745,stroke:#232f3e,stroke-width:2px,color:#fff
Step 1: Create EKS Cluster
# Create EKS cluster with proper DNS configuration
aws eks create-cluster \
--name my-cluster \
--version 1.28 \
--role-arn arn:aws:iam::123456789012:role/eks-service-role \
--resources-vpc-config subnetIds=subnet-12345,subnet-67890,securityGroupIds=sg-12345 \
--endpoint-config privateAccess=true,publicAccess=true \
--logging '{"enable":[{"types":["api","audit","authenticator","controllerManager","scheduler"]}]}'
Parameter Explanation:
• --name: Your cluster identifier (like a hostname)
• --version: Kubernetes version (similar to OS version)
• --role-arn: IAM role for EKS service (like service account permissions)
• --resources-vpc-config: Network configuration (your subnets and security groups)
• --endpoint-config: API server accessibility (like management interface access)
• --logging: Enable control plane logging for troubleshooting
What this creates: The EKS control plane in AWS-managed infrastructure. This is like setting up your network management system - AWS handles the underlying infrastructure while you get the API endpoints to manage your cluster.
Step 2: Configure kubectl Access
# Configure kubectl to connect to your cluster
aws eks update-kubeconfig --region us-west-2 --name my-cluster
# Verify connection
kubectl get nodes
kubectl get pods -n kube-system
Purpose: This configures your local kubectl tool to authenticate with your EKS cluster. It's similar to setting up SSH keys or SNMP credentials to manage your network devices.
Step 3: Install AWS Load Balancer Controller
# Create IAM role for AWS Load Balancer Controller
aws iam create-role \
--role-name AmazonEKSLoadBalancerControllerRole \
--assume-role-policy-document file://load-balancer-role-trust-policy.json
# Attach the required IAM policy
aws iam attach-role-policy \
--role-name AmazonEKSLoadBalancerControllerRole \
--policy-arn arn:aws:iam::aws:policy/ElasticLoadBalancingFullAccess
# load-balancer-role-trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller",
"oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
}
}
}
]
}
Trust Policy Parameters:
• Federated: Your EKS cluster's OIDC provider (get this from EKS console)
• StringEquals conditions: Ensures only the load balancer controller can assume this role
• sub: Service account that will use this role
• aud: AWS STS audience for token validation
# Install AWS Load Balancer Controller using Helm
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=my-cluster \
--set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::123456789012:role/AmazonEKSLoadBalancerControllerRole \
--set region=us-west-2 \
--set vpcId=vpc-12345678
Helm Installation Parameters:
• clusterName: Must match your EKS cluster name
• serviceAccount.annotations: Links the controller to the IAM role
• region: AWS region where your cluster is deployed
• vpcId: VPC where your EKS cluster is running
What this does: Installs a controller that automatically creates and manages AWS Load Balancers when you deploy applications. It's like having an automated system that configures your hardware load balancers based on application requirements.
Step 4: Configure CoreDNS
# Get current CoreDNS configuration
kubectl get configmap coredns -n kube-system -o yaml > coredns-config.yaml
# Edit the configuration
kubectl edit configmap coredns -n kube-system
# CoreDNS ConfigMap - Enhanced Configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . 168.63.129.16 8.8.8.8 {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
log
}
company.local:53 {
errors
cache 300
forward . 10.0.0.10 10.0.0.11
}
CoreDNS Configuration Breakdown:
• .:53 - Default zone handling all DNS queries on port 53
• errors - Log DNS errors for troubleshooting
• health - Health check endpoint with 5-second lameduck period
• ready - Readiness probe endpoint
• kubernetes cluster.local - Handle internal cluster DNS
• pods insecure - Enable pod DNS records (A/AAAA)
• ttl 30 - Cache internal DNS records for 30 seconds
• prometheus :9153 - Metrics endpoint for monitoring
• forward . 168.63.129.16 8.8.8.8 - Upstream DNS servers
• cache 30 - Cache external DNS queries for 30 seconds
• company.local:53 - Custom zone for internal company DNS
Network Engineer Note: This configuration is similar to your DNS server zones file. The first block handles internet and cluster DNS, while the second block handles your internal corporate DNS zone.
# Apply the configuration and restart CoreDNS
kubectl apply -f coredns-config.yaml
kubectl rollout restart deployment coredns -n kube-system
kubectl rollout status deployment coredns -n kube-system
Step 5: Deploy External DNS
# Create IAM policy for External DNS
aws iam create-policy \
--policy-name ExternalDNSPolicy \
--policy-document file://external-dns-policy.json
# Create IAM role for External DNS
aws iam create-role \
--role-name ExternalDNSRole \
--assume-role-policy-document file://external-dns-trust-policy.json
# Attach policy to role
aws iam attach-role-policy \
--role-name ExternalDNSRole \
--policy-arn arn:aws:iam::123456789012:policy/ExternalDNSPolicy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource": "*"
}
]
}
External DNS IAM Policy:
• route53:ChangeResourceRecordSets: Create/update/delete DNS records
• route53:ListHostedZones: Discover available DNS zones
• route53:ListResourceRecordSets: Read existing DNS records
This is like giving your DNS management system permissions to update your authoritative DNS servers.
# external-dns-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: kube-system
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: registry.k8s.io/external-dns/external-dns:v0.14.0
args:
- --source=service
- --source=ingress
- --domain-filter=example.com
- --provider=aws
- --policy=upsert-only
- --aws-zone-type=public
- --registry=txt
- --txt-owner-id=my-cluster
- --log-format=json
- --log-level=info
- --interval=1m
env:
- name: AWS_DEFAULT_REGION
value: us-west-2
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/ExternalDNSRole
External DNS Configuration:
• --source=service,ingress: Watch Kubernetes services and ingresses for DNS annotations
• --domain-filter=example.com: Only manage DNS records for this domain
• --provider=aws: Use AWS Route 53 as the DNS provider
• --policy=upsert-only: Only create/update records, never delete
• --registry=txt: Use TXT records to track ownership
• --txt-owner-id: Unique identifier for this cluster's DNS records
• --interval=1m: Check for changes every minute
What this does: Automatically creates DNS records in Route 53 when you deploy services with specific annotations. It's like having an automated system that updates your DNS zone files when you add new services.
Step 6: Configure Route 53 Integration
# Create Route 53 hosted zone (if not exists)
aws route53 create-hosted-zone \
--name example.com \
--caller-reference $(date +%s) \
--hosted-zone-config Comment="EKS cluster DNS zone"
# Get hosted zone ID
aws route53 list-hosted-zones-by-name --dns-name example.com
# Sample service with External DNS annotation
apiVersion: v1
kind: Service
metadata:
name: my-app
annotations:
external-dns.alpha.kubernetes.io/hostname: app.example.com
external-dns.alpha.kubernetes.io/ttl: "300"
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: my-app
Service DNS Annotations:
• external-dns.alpha.kubernetes.io/hostname: DNS name to create
• external-dns.alpha.kubernetes.io/ttl: DNS record TTL (300 seconds)
• service.beta.kubernetes.io/aws-load-balancer-type: Load balancer type (nlb/alb)
This automatically creates an A record pointing app.example.com to your load balancer.
Step 7: DNS Policies and Network Policies
# DNS Network Policy - Restrict DNS access
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: dns-policy
namespace: default
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to: []
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
DNS Network Policy:
• podSelector: {}: Applies to all pods in the namespace
• policyTypes: [Egress]: Controls outbound traffic
• ports 53 UDP/TCP: Allow DNS queries
• namespaceSelector kube-system: Allow queries to CoreDNS
This is like creating firewall rules that only allow DNS traffic on ports 53.
Advanced DNS Configuration
Custom DNS Resolution Flow
graph TD
A[Application Pod] --> B{DNS Query Type}
B -->|service.namespace.svc.cluster.local| C[CoreDNS - Kubernetes Plugin]
B -->|company.local| D[CoreDNS - Custom Zone]
B -->|external.com| E[CoreDNS - Forward Plugin]
C --> F[Return Service ClusterIP]
D --> G[Forward to Internal DNS
10.0.0.10]
E --> H[Forward to Public DNS
8.8.8.8]
G --> I[Internal DNS Response]
H --> J[Public DNS Response]
F --> K[Pod connects to Service]
I --> L[Pod connects to Internal Resource]
J --> M[Pod connects to External Resource]
style A fill:#ff9900,stroke:#232f3e,stroke-width:2px,color:#fff
style C fill:#146eb4,stroke:#232f3e,stroke-width:2px,color:#fff
style D fill:#28a745,stroke:#232f3e,stroke-width:2px,color:#fff
style E fill:#dc3545,stroke:#232f3e,stroke-width:2px,color:#fff
Advanced DNS Resolution:
This diagram shows how CoreDNS handles different types of DNS queries:
• Internal Service Discovery: Handled by the kubernetes plugin
• Company Internal DNS: Forwarded to your corporate DNS servers
• External Internet DNS: Forwarded to public DNS servers
This allows your applications to resolve both internal Kubernetes services and external dependencies.
DNS Performance Optimization
# Scale CoreDNS for better performance
kubectl scale deployment coredns --replicas=3 -n kube-system
# Configure DNS caching on nodes
kubectl apply -f node-local-dns.yaml
# Node Local DNS Cache Configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: node-local-dns
namespace: kube-system
data:
Corefile: |
cluster.local:53 {
errors
cache {
success 9984 30
denial 9984 5
}
reload
loop
bind 169.254.20.10
forward . 10.100.0.10 {
force_tcp
}
prometheus :9253
}
in-addr.arpa:53 {
errors
cache 30
reload
loop
bind 169.254.20.10
forward . 10.100.0.10 {
force_tcp
}
prometheus :9253
}
ip6.arpa:53 {
errors
cache 30
reload
loop
bind 169.254.20.10
forward . 10.100.0.10 {
force_tcp
}
prometheus :9253
}
.:53 {
errors
cache 30
reload
loop
bind 169.254.20.10
forward . 8.8.8.8 8.8.4.4 {
force_tcp
}
prometheus :9253
}
Node Local DNS Configuration:
• bind 169.254.20.10: Link-local IP address for DNS cache
• cache success 9984 30: Cache successful responses for 30 seconds
• cache denial 9984 5: Cache NXDOMAIN responses for 5 seconds
• force_tcp: Use TCP for upstream queries (more reliable)
• prometheus :9253: Metrics endpoint for monitoring
This creates a local DNS cache on each node, reducing latency and load on CoreDNS.
Monitoring and Troubleshooting
# Monitor CoreDNS performance
kubectl top pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns
# Test DNS resolution from a pod
kubectl run debug-pod --image=nicolaka/netshoot --rm -it -- bash
nslookup kubernetes.default.svc.cluster.local
dig @10.100.0.10 google.com
# Check DNS configuration
kubectl exec -it debug-pod -- cat /etc/resolv.conf
Troubleshooting Commands:
• kubectl top pods: Monitor CPU and memory usage
• kubectl logs: View DNS query logs and errors
• nslookup/dig: Test DNS resolution from within the cluster
• /etc/resolv.conf: Check DNS configuration in pods
These tools help you diagnose DNS issues similar to how you'd troubleshoot traditional DNS servers.
Best Practices for Network Engineers
Security Considerations:
• Always use Network Policies to restrict DNS access
• Monitor DNS query logs for suspicious activity
• Use separate DNS zones for different environments
• Implement proper RBAC for DNS management
• Regular security audits of DNS configurations
Performance Tips:
• Use Node Local DNS for better performance
• Configure appropriate TTL values for different record types
• Monitor DNS cache hit rates
• Scale CoreDNS replicas based on cluster size
• Use health checks and readiness probes
Summary Configuration Flow
graph TD
A[1. Create EKS Cluster] --> B[2. Configure kubectl]
B --> C[3. Install Load Balancer Controller]
C --> D[4. Configure CoreDNS]
D --> E[5. Deploy External DNS]
E --> F[6. Configure Route 53]
F --> G[7. Apply DNS Policies]
G --> H[8. Monitor and Optimize]
I[IAM Roles] --> C
I --> E
J[Network Policies] --> G
K[ConfigMaps] --> D
L[Helm Charts] --> C
style A fill:#ff9900,stroke:#232f3e,stroke-width:2px,color:#fff
style H fill:#28a745,stroke:#232f3e,stroke-width:2px,color:#fff
style I fill:#146eb4,stroke:#232f3e,stroke-width:2px,color:#fff
Complete Setup Flow:
This diagram shows the complete setup process for EKS DNS services. Each component depends on the previous ones, and supporting elements like IAM roles, network policies, and configurations are applied at the appropriate stages. Follow this sequence to ensure proper DNS functionality in your EKS cluster.
Next Steps:
After completing this setup, you'll have a fully functional DNS system in your EKS cluster that can handle internal service discovery, external DNS management, and integration with your existing network infrastructure. Monitor the logs and metrics to ensure optimal performance and security.