IP-Based Pod DNS Resolution in Kubernetes: Advanced Service Mesh Integration and Enterprise Networking Patterns
IP-based Pod DNS resolution enables direct pod-to-pod communication patterns that are essential for advanced Kubernetes networking architectures, service mesh implementations, and enterprise applications requiring precise control over network connectivity. This comprehensive guide demonstrates production-ready configurations, security patterns, and operational strategies for implementing sophisticated pod networking solutions.
Executive Summary
Modern Kubernetes applications increasingly require direct pod communication capabilities that bypass traditional service abstractions. IP-based Pod DNS resolution provides the foundation for advanced networking patterns including service mesh integration, database clustering, distributed system coordination, and high-performance application architectures. This guide presents enterprise-grade configurations and security patterns for implementing IP-based pod resolution while maintaining operational excellence and security compliance.
IP-Based Pod DNS Architecture
CoreDNS Pod Resolution Configuration
CoreDNS supports multiple modes of Pod DNS resolution, each providing different levels of security and functionality:
# Advanced CoreDNS configuration for IP-based Pod DNS
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns-pod-dns-config
namespace: kube-system
labels:
app: coredns
component: pod-dns
data:
Corefile: |
# Core Kubernetes DNS configuration
cluster.local:53 {
errors {
consolidate 5m ".*" warning
}
# Comprehensive health monitoring
health {
lameduck 5s
}
ready
# Advanced Kubernetes plugin configuration
kubernetes cluster.local in-addr.arpa ip6.arpa {
# Pod DNS resolution modes:
# - disabled: No pod DNS records (default)
# - insecure: Pod DNS records without verification
# - verified: Pod DNS records with existence verification
pods verified
# Enable endpoint resolution
endpoint_pod_names
# TTL for pod records
ttl 30
# Fallthrough for reverse DNS
fallthrough in-addr.arpa ip6.arpa
# Upstream for external queries
upstream
# Namespace selection for pod DNS
namespaces default production staging monitoring
# Ignore empty service endpoints
ignore empty_service
}
# Enhanced caching for pod resolution
cache 300 {
success 10000 300
denial 5000 60
prefetch 50 60s 30%
}
# Loop detection and prevention
loop
# DNS forwarding for external domains
forward . /etc/resolv.conf {
max_concurrent 1000
policy sequential
health_check 30s
}
# Reload configuration automatically
reload
# Load balancing for multiple CoreDNS instances
loadbalance
# Prometheus metrics
prometheus :9153 {
path /metrics
}
# Query logging for debugging
log {
class error
}
}
# Reverse DNS for pod IPs
in-addr.arpa:53 {
errors
cache 300
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods verified
fallthrough
}
forward . /etc/resolv.conf
}
# IPv6 reverse DNS
ip6.arpa:53 {
errors
cache 300
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods verified
fallthrough
}
forward . /etc/resolv.conf
}
# Wildcard for all other queries
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods disabled
fallthrough in-addr.arpa ip6.arpa
}
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 300
loop
reload
loadbalance
}
---
# Enhanced CoreDNS deployment for pod DNS
apiVersion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: kube-system
labels:
k8s-app: kube-dns
app: coredns
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 10%
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
app: coredns
spec:
serviceAccountName: coredns
# Priority class for DNS stability
priorityClassName: system-cluster-critical
# Node selection for DNS reliability
nodeSelector:
kubernetes.io/os: linux
# Anti-affinity for high availability
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
k8s-app: kube-dns
topologyKey: kubernetes.io/hostname
# Tolerations for critical system pods
tolerations:
- key: CriticalAddonsOnly
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
# Security context
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: coredns
image: registry.k8s.io/coredns/coredns:v1.10.1
imagePullPolicy: IfNotPresent
# Resource allocation for pod DNS workloads
resources:
limits:
memory: 1Gi
cpu: 1000m
requests:
cpu: 100m
memory: 128Mi
# Security configuration
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- NET_BIND_SERVICE
drop:
- all
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65534
# Command line arguments
args: [ "-conf", "/etc/coredns/Corefile" ]
# Volume mounts
volumeMounts:
- name: config-volume
mountPath: /etc/coredns
readOnly: true
# Network ports
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
- containerPort: 9153
name: metrics
protocol: TCP
# Health checks optimized for pod DNS
livenessProbe:
httpGet:
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /ready
port: 8181
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
# DNS policy configuration
dnsPolicy: Default
volumes:
- name: config-volume
configMap:
name: coredns
items:
- key: Corefile
path: Corefile
# Restart policy for critical DNS service
restartPolicy: Always
Service Mesh Integration Patterns
IP-based Pod DNS resolution is essential for service mesh implementations that require direct pod communication:
# Istio service mesh configuration with pod DNS
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: istio-control-plane
namespace: istio-system
spec:
# Global mesh configuration
values:
global:
# Enable pod-level DNS resolution
meshID: mesh1
network: network1
# Proxy configuration for direct pod communication
proxy:
# Enable DNS capture for service mesh
dnsCapture: true
# DNS refresh rate for pod resolution
dnsRefreshRate: 300s
# Pilot configuration for service discovery
pilot:
# Enable cross-cluster endpoint discovery
enableCrossClusterWorkloadEntry: true
# DNS resolution timeout
dnsResolution: 30s
# Component configurations
components:
pilot:
k8s:
# Resource allocation for service discovery
resources:
requests:
cpu: 500m
memory: 2048Mi
limits:
cpu: 2000m
memory: 4096Mi
# Environment variables for pod DNS
env:
- name: PILOT_ENABLE_IP_AUTOALLOCATE
value: "true"
- name: PILOT_ENABLE_CROSS_CLUSTER_WORKLOAD_ENTRY
value: "true"
- name: PILOT_DNS_LOOKUP_FAMILY
value: "V4_PREFERRED"
# Ingress gateway configuration
ingressGateways:
- name: istio-ingressgateway
enabled: true
k8s:
service:
type: LoadBalancer
resources:
requests:
cpu: 1000m
memory: 1024Mi
---
# Service mesh networking configuration
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: default-sidecar
namespace: production
spec:
# Enable pod-level traffic interception
workloadSelector:
labels:
app: microservice
# Egress configuration for pod DNS
egress:
- port:
number: 53
name: dns-udp
protocol: UDP
hosts:
- "./*"
- "istio-system/*"
- port:
number: 53
name: dns-tcp
protocol: TCP
hosts:
- "./*"
- "istio-system/*"
# Enable pod IP discovery
- hosts:
- "./*"
- "istio-system/*"
port:
number: 15090
name: http-envoy-prom
protocol: HTTP
---
# Virtual service for pod-level routing
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: pod-direct-routing
namespace: production
spec:
hosts:
- "*.pod.cluster.local"
http:
- match:
- headers:
pod-direct:
exact: "true"
route:
- destination:
host: "*.pod.cluster.local"
# Enable pod-level load balancing
subset: pod-direct
- route:
- destination:
host: kubernetes.default.svc.cluster.local
port:
number: 443
---
# Destination rule for pod communication
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: pod-direct-destination
namespace: production
spec:
host: "*.pod.cluster.local"
# Traffic policy for pod communication
trafficPolicy:
# Connection pool settings for pod-to-pod
connectionPool:
tcp:
maxConnections: 100
connectTimeout: 30s
http:
http1MaxPendingRequests: 50
maxRequestsPerConnection: 2
# Load balancer settings
loadBalancer:
simple: LEAST_CONN
# Outlier detection for unhealthy pods
outlierDetection:
consecutiveGatewayErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
# Subsets for different pod types
subsets:
- name: pod-direct
labels:
pod-direct: "enabled"
trafficPolicy:
connectionPool:
tcp:
maxConnections: 200
Database Clustering with Pod DNS
Database clusters require direct pod communication for replication and coordination:
# PostgreSQL cluster with pod DNS resolution
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: postgres-cluster
namespace: database
spec:
instances: 3
# PostgreSQL configuration
postgresql:
parameters:
# Enable pod-level communication
listen_addresses: "*"
# DNS-based discovery
cluster_name: "postgres-cluster"
# Pod template for cluster nodes
template:
metadata:
labels:
app: postgres
cluster: postgres-cluster
pod-dns-enabled: "true"
spec:
# Affinity rules for pod distribution
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: postgres
topologyKey: kubernetes.io/hostname
# Service account for pod discovery
serviceAccountName: postgres-pod-discovery
containers:
- name: postgres
image: postgres:15
# Environment variables for pod DNS
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
# DNS configuration for cluster discovery
- name: POSTGRES_CLUSTER_DISCOVERY
value: "$(POD_NAME).postgres-cluster.$(POD_NAMESPACE).svc.cluster.local"
# Resource allocation
resources:
requests:
cpu: 1000m
memory: 2Gi
limits:
cpu: 2000m
memory: 4Gi
# Volume mounts for data persistence
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
# Health checks
livenessProbe:
exec:
command:
- sh
- -c
- pg_isready -h $(POD_IP) -p 5432 -U postgres
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- sh
- -c
- pg_isready -h $(POD_IP) -p 5432 -U postgres
initialDelaySeconds: 5
periodSeconds: 5
# Storage configuration
storage:
size: 100Gi
storageClass: fast-ssd
# Monitoring configuration
monitoring:
enabled: true
---
# Service for postgres cluster pod discovery
apiVersion: v1
kind: Service
metadata:
name: postgres-cluster-pods
namespace: database
labels:
app: postgres
service-type: pod-discovery
spec:
# Headless service for pod DNS resolution
clusterIP: None
# Expose postgres port
ports:
- name: postgres
port: 5432
targetPort: 5432
# Select all postgres pods
selector:
app: postgres
cluster: postgres-cluster
---
# Service account for pod discovery
apiVersion: v1
kind: ServiceAccount
metadata:
name: postgres-pod-discovery
namespace: database
---
# RBAC for pod discovery
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: postgres-pod-discovery
namespace: database
rules:
- apiGroups: [""]
resources: ["pods", "endpoints"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: postgres-pod-discovery
namespace: database
subjects:
- kind: ServiceAccount
name: postgres-pod-discovery
namespace: database
roleRef:
kind: Role
name: postgres-pod-discovery
apiGroup: rbac.authorization.k8s.io
Advanced Pod Discovery Patterns
Custom Pod Discovery Controller
#!/usr/bin/env python3
"""
Advanced Pod Discovery Controller for IP-based DNS resolution
"""
import asyncio
import json
import logging
import time
from typing import Dict, List, Set, Optional, Any
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from kubernetes import client, config, watch
import aiohttp
import aiodns
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@dataclass
class PodInfo:
name: str
namespace: str
ip: str
labels: Dict[str, str]
annotations: Dict[str, str]
phase: str
node_name: str
creation_timestamp: datetime
dns_names: List[str] = field(default_factory=list)
health_status: str = "unknown"
last_health_check: Optional[datetime] = None
class PodDiscoveryController:
def __init__(self, namespaces: List[str] = None):
# Initialize Kubernetes client
try:
config.load_incluster_config()
except:
config.load_kube_config()
self.v1 = client.CoreV1Api()
self.namespaces = namespaces or ["default", "production", "staging"]
# Pod tracking
self.pods: Dict[str, PodInfo] = {}
self.pod_dns_cache: Dict[str, str] = {}
# DNS resolver for validation
self.resolver = aiodns.DNSResolver()
# Configuration
self.health_check_interval = 60 # seconds
self.dns_validation_interval = 300 # seconds
async def start_monitoring(self):
"""Start monitoring pods for DNS resolution"""
logger.info("Starting pod discovery controller")
# Start concurrent tasks
tasks = [
asyncio.create_task(self.watch_pods()),
asyncio.create_task(self.health_check_loop()),
asyncio.create_task(self.dns_validation_loop()),
asyncio.create_task(self.cleanup_stale_pods())
]
await asyncio.gather(*tasks)
async def watch_pods(self):
"""Watch for pod changes"""
logger.info("Starting pod watcher")
w = watch.Watch()
while True:
try:
for event in w.stream(
self.v1.list_pod_for_all_namespaces,
timeout_seconds=300
):
await self.handle_pod_event(event)
except Exception as e:
logger.error(f"Error watching pods: {e}")
await asyncio.sleep(10)
async def handle_pod_event(self, event):
"""Handle pod lifecycle events"""
event_type = event['type']
pod = event['object']
# Filter by namespace
if pod.metadata.namespace not in self.namespaces:
return
pod_key = f"{pod.metadata.namespace}/{pod.metadata.name}"
if event_type == 'ADDED' or event_type == 'MODIFIED':
await self.process_pod(pod)
elif event_type == 'DELETED':
if pod_key in self.pods:
logger.info(f"Pod deleted: {pod_key}")
del self.pods[pod_key]
await self.update_dns_records(pod_key, [])
async def process_pod(self, pod):
"""Process pod for DNS registration"""
pod_key = f"{pod.metadata.namespace}/{pod.metadata.name}"
# Skip pods without IP
if not pod.status.pod_ip:
return
# Skip pods not in running state
if pod.status.phase != 'Running':
return
# Extract pod information
pod_info = PodInfo(
name=pod.metadata.name,
namespace=pod.metadata.namespace,
ip=pod.status.pod_ip,
labels=pod.metadata.labels or {},
annotations=pod.metadata.annotations or {},
phase=pod.status.phase,
node_name=pod.spec.node_name,
creation_timestamp=pod.metadata.creation_timestamp
)
# Generate DNS names for pod
dns_names = self.generate_pod_dns_names(pod_info)
pod_info.dns_names = dns_names
# Store pod information
self.pods[pod_key] = pod_info
# Update DNS records
await self.update_dns_records(pod_key, dns_names)
logger.info(f"Processed pod: {pod_key} with IP {pod_info.ip}")
def generate_pod_dns_names(self, pod_info: PodInfo) -> List[str]:
"""Generate DNS names for pod"""
dns_names = []
# Standard pod DNS name (IP-based)
ip_parts = pod_info.ip.replace('.', '-')
dns_names.append(f"{ip_parts}.{pod_info.namespace}.pod.cluster.local")
# Service-based DNS names if pod belongs to services
service_dns_names = self.get_service_dns_names(pod_info)
dns_names.extend(service_dns_names)
# Label-based DNS names
if 'app' in pod_info.labels:
app_name = pod_info.labels['app']
dns_names.append(f"{pod_info.name}.{app_name}.{pod_info.namespace}.pod.cluster.local")
# Custom DNS names from annotations
if 'pod-dns.kubernetes.io/names' in pod_info.annotations:
custom_names = pod_info.annotations['pod-dns.kubernetes.io/names'].split(',')
dns_names.extend([name.strip() for name in custom_names])
return dns_names
def get_service_dns_names(self, pod_info: PodInfo) -> List[str]:
"""Get service-based DNS names for pod"""
dns_names = []
try:
# Get services in the namespace
services = self.v1.list_namespaced_service(namespace=pod_info.namespace)
for service in services.items:
if self.pod_matches_service_selector(pod_info, service):
service_name = service.metadata.name
dns_names.append(f"{pod_info.name}.{service_name}.{pod_info.namespace}.svc.cluster.local")
except Exception as e:
logger.warning(f"Error getting service DNS names: {e}")
return dns_names
def pod_matches_service_selector(self, pod_info: PodInfo, service) -> bool:
"""Check if pod matches service selector"""
if not service.spec.selector:
return False
for key, value in service.spec.selector.items():
if key not in pod_info.labels or pod_info.labels[key] != value:
return False
return True
async def update_dns_records(self, pod_key: str, dns_names: List[str]):
"""Update DNS records for pod"""
try:
# Implementation would update CoreDNS or external DNS
# This is a placeholder for the actual DNS update logic
logger.debug(f"Updating DNS records for {pod_key}: {dns_names}")
# Update local cache
for dns_name in dns_names:
self.pod_dns_cache[dns_name] = self.pods[pod_key].ip
except Exception as e:
logger.error(f"Error updating DNS records for {pod_key}: {e}")
async def health_check_loop(self):
"""Continuously check pod health"""
while True:
await asyncio.sleep(self.health_check_interval)
tasks = []
for pod_key, pod_info in self.pods.items():
task = asyncio.create_task(self.check_pod_health(pod_info))
tasks.append(task)
if tasks:
await asyncio.gather(*tasks, return_exceptions=True)
async def check_pod_health(self, pod_info: PodInfo):
"""Check health of a specific pod"""
try:
# HTTP health check
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=5)) as session:
health_url = f"http://{pod_info.ip}:8080/health"
async with session.get(health_url) as response:
if response.status == 200:
pod_info.health_status = "healthy"
else:
pod_info.health_status = "unhealthy"
except Exception:
pod_info.health_status = "unhealthy"
pod_info.last_health_check = datetime.now()
async def dns_validation_loop(self):
"""Validate DNS resolution for pods"""
while True:
await asyncio.sleep(self.dns_validation_interval)
for pod_key, pod_info in self.pods.items():
for dns_name in pod_info.dns_names:
try:
result = await self.resolver.query(dns_name, 'A')
expected_ip = pod_info.ip
if result and str(result[0].host) == expected_ip:
logger.debug(f"DNS validation passed for {dns_name}")
else:
logger.warning(f"DNS validation failed for {dns_name}")
except Exception as e:
logger.warning(f"DNS validation error for {dns_name}: {e}")
async def cleanup_stale_pods(self):
"""Clean up stale pod entries"""
while True:
await asyncio.sleep(300) # 5 minutes
current_time = datetime.now()
stale_pods = []
for pod_key, pod_info in self.pods.items():
# Check if pod hasn't been health checked recently
if (pod_info.last_health_check and
current_time - pod_info.last_health_check > timedelta(minutes=10)):
# Verify pod still exists in Kubernetes
try:
self.v1.read_namespaced_pod(
name=pod_info.name,
namespace=pod_info.namespace
)
except client.exceptions.ApiException as e:
if e.status == 404:
stale_pods.append(pod_key)
# Remove stale pods
for pod_key in stale_pods:
logger.info(f"Removing stale pod: {pod_key}")
del self.pods[pod_key]
def get_pod_discovery_report(self) -> Dict[str, Any]:
"""Generate pod discovery report"""
total_pods = len(self.pods)
healthy_pods = sum(1 for pod in self.pods.values() if pod.health_status == "healthy")
unhealthy_pods = sum(1 for pod in self.pods.values() if pod.health_status == "unhealthy")
namespace_stats = {}
for pod in self.pods.values():
if pod.namespace not in namespace_stats:
namespace_stats[pod.namespace] = 0
namespace_stats[pod.namespace] += 1
return {
"timestamp": datetime.now().isoformat(),
"total_pods": total_pods,
"healthy_pods": healthy_pods,
"unhealthy_pods": unhealthy_pods,
"namespace_distribution": namespace_stats,
"dns_cache_entries": len(self.pod_dns_cache),
"monitored_namespaces": self.namespaces
}
if __name__ == "__main__":
controller = PodDiscoveryController(["default", "production", "staging", "database"])
# Start the controller
asyncio.run(controller.start_monitoring())
Enhanced DNS Security for Pod Resolution
# Security-enhanced CoreDNS configuration for pod DNS
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns-secure-pod-dns
namespace: kube-system
data:
Corefile: |
# Secure pod DNS configuration
(pod-dns-security) {
errors {
consolidate 5m ".*" warning
}
log {
class all
format "[POD-DNS] {type} {name} {rcode} {remote} {size} {duration}"
}
# Health checks
health {
lameduck 5s
}
ready
# Rate limiting for pod DNS queries
ratelimit {
per_second 100
per_client 20
window 60s
ipv4_mask 24
whitelist 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
}
# Caching with security considerations
cache 300 {
success 5000 300
denial 1000 60
prefetch 20 60s 25%
}
prometheus :9153 {
path /metrics
}
}
# Production namespace - verified pod DNS
cluster.local:53 {
import pod-dns-security
kubernetes cluster.local in-addr.arpa ip6.arpa {
# Verified pod DNS - checks pod existence
pods verified
# Enable endpoint names
endpoint_pod_names
# TTL for pod records
ttl 30
# Namespace restrictions for pod DNS
namespaces production database monitoring
# Security: ignore empty services
ignore empty_service
# Upstream fallback
upstream /etc/resolv.conf
# Fallthrough for reverse DNS
fallthrough in-addr.arpa ip6.arpa
}
# Access control for pod DNS queries
acl {
# Allow pod-to-pod communication within cluster
allow 10.0.0.0/8
allow 172.16.0.0/12
allow 192.168.0.0/16
# Deny external access to pod DNS
deny all
}
# Forward non-cluster queries
forward . /etc/resolv.conf {
max_concurrent 1000
}
# Standard configurations
loop
reload
loadbalance
}
# Staging environment - insecure pod DNS for development
staging.cluster.local:53 {
import pod-dns-security
kubernetes staging.cluster.local {
# Insecure pod DNS for development flexibility
pods insecure
# Limited to staging namespace
namespaces staging
# Reduced TTL for development
ttl 10
upstream /etc/resolv.conf
}
# More relaxed access control for staging
acl {
allow 192.168.100.0/24 # Staging network
allow 10.100.0.0/16 # Developer network
deny all
}
forward . /etc/resolv.conf
loop
reload
loadbalance
}
# Reverse DNS with security
in-addr.arpa:53 {
import pod-dns-security
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods verified
namespaces production database monitoring
fallthrough
}
forward . /etc/resolv.conf
}
# Default secure configuration
.:53 {
import pod-dns-security
# Disable pod DNS for external queries
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods disabled
fallthrough in-addr.arpa ip6.arpa
}
forward . /etc/resolv.conf {
max_concurrent 1000
}
loop
reload
loadbalance
}
---
# Network policy for pod DNS security
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: pod-dns-security
namespace: production
spec:
podSelector:
matchLabels:
pod-dns-enabled: "true"
policyTypes:
- Ingress
- Egress
ingress:
# Allow DNS queries from other pods in namespace
- from:
- namespaceSelector:
matchLabels:
name: production
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# Allow service mesh communication
- from:
- namespaceSelector:
matchLabels:
name: istio-system
ports:
- protocol: TCP
port: 15090
egress:
# Allow DNS resolution
- to: []
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# Allow pod-to-pod communication
- to:
- namespaceSelector:
matchLabels:
name: production
ports:
- protocol: TCP
port: 8080
- protocol: TCP
port: 8443
---
# Pod DNS monitoring service
apiVersion: v1
kind: Service
metadata:
name: pod-dns-monitor
namespace: monitoring
labels:
app: pod-dns-monitor
spec:
selector:
app: pod-dns-monitor
ports:
- name: metrics
port: 9090
targetPort: 9090
- name: health
port: 8080
targetPort: 8080
---
# Pod DNS monitoring deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-dns-monitor
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: pod-dns-monitor
template:
metadata:
labels:
app: pod-dns-monitor
spec:
serviceAccountName: pod-dns-monitor
containers:
- name: monitor
image: company/pod-dns-monitor:v1.0.0
# Environment configuration
env:
- name: NAMESPACES
value: "production,database,monitoring"
- name: DNS_SERVER
value: "kube-dns.kube-system.svc.cluster.local"
- name: CHECK_INTERVAL
value: "60"
# Resource allocation
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
# Health checks
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
# Metrics port
ports:
- containerPort: 9090
name: metrics
- containerPort: 8080
name: health
# Service account for monitoring
serviceAccountName: pod-dns-monitor
---
# RBAC for pod DNS monitoring
apiVersion: v1
kind: ServiceAccount
metadata:
name: pod-dns-monitor
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-dns-monitor
rules:
- apiGroups: [""]
resources: ["pods", "services", "endpoints"]
verbs: ["get", "list", "watch"]
- apiGroups: ["networking.k8s.io"]
resources: ["networkpolicies"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: pod-dns-monitor
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: pod-dns-monitor
subjects:
- kind: ServiceAccount
name: pod-dns-monitor
namespace: monitoring
Performance Testing and Validation
Comprehensive DNS Resolution Testing
#!/bin/bash
# Comprehensive Pod DNS resolution testing script
set -euo pipefail
# Configuration
NAMESPACE="production"
TEST_ITERATIONS=100
DNS_SERVER="kube-dns.kube-system.svc.cluster.local"
RESULTS_DIR="/tmp/pod-dns-tests"
# Create results directory
mkdir -p "$RESULTS_DIR"
# Test functions
test_pod_ip_resolution() {
local pod_name=$1
local pod_namespace=$2
local pod_ip=$3
echo "Testing IP-based DNS resolution for pod: $pod_name"
# Generate IP-based DNS name
local ip_dns_name="${pod_ip//./-}.$pod_namespace.pod.cluster.local"
# Test DNS resolution
local resolved_ip
resolved_ip=$(dig +short @$DNS_SERVER "$ip_dns_name" A 2>/dev/null | head -n1)
if [[ "$resolved_ip" == "$pod_ip" ]]; then
echo "✅ SUCCESS: $ip_dns_name resolves to $pod_ip"
return 0
else
echo "❌ FAILED: $ip_dns_name resolves to '$resolved_ip', expected '$pod_ip'"
return 1
fi
}
test_pod_dns_performance() {
local dns_name=$1
local iterations=${2:-$TEST_ITERATIONS}
echo "Testing DNS resolution performance for: $dns_name ($iterations iterations)"
local total_time=0
local successful_queries=0
local failed_queries=0
for ((i=1; i<=iterations; i++)); do
local start_time
start_time=$(date +%s.%N)
if dig +short @$DNS_SERVER "$dns_name" A >/dev/null 2>&1; then
((successful_queries++))
else
((failed_queries++))
fi
local end_time
end_time=$(date +%s.%N)
local query_time
query_time=$(echo "$end_time - $start_time" | bc)
total_time=$(echo "$total_time + $query_time" | bc)
done
# Calculate statistics
local avg_time
avg_time=$(echo "scale=4; $total_time / $iterations" | bc)
local success_rate
success_rate=$(echo "scale=2; $successful_queries * 100 / $iterations" | bc)
echo "Performance Results:"
echo " Average query time: ${avg_time}s"
echo " Success rate: ${success_rate}%"
echo " Successful queries: $successful_queries"
echo " Failed queries: $failed_queries"
# Save results
cat > "$RESULTS_DIR/performance_${dns_name//[\/\.]/_}.json" <<EOF
{
"dns_name": "$dns_name",
"total_iterations": $iterations,
"successful_queries": $successful_queries,
"failed_queries": $failed_queries,
"success_rate": $success_rate,
"average_query_time": $avg_time,
"total_time": $total_time
}
EOF
}
test_pod_dns_cache_behavior() {
local dns_name=$1
echo "Testing DNS cache behavior for: $dns_name"
# Clear DNS cache (if possible)
kubectl exec -n kube-system deployment/coredns -- \
pkill -SIGUSR1 coredns 2>/dev/null || true
sleep 2
# First query (should be uncached)
echo "Testing uncached query..."
local uncached_start
uncached_start=$(date +%s.%N)
dig +short @$DNS_SERVER "$dns_name" A >/dev/null
local uncached_end
uncached_end=$(date +%s.%N)
local uncached_time
uncached_time=$(echo "$uncached_end - $uncached_start" | bc)
# Second query (should be cached)
echo "Testing cached query..."
local cached_start
cached_start=$(date +%s.%N)
dig +short @$DNS_SERVER "$dns_name" A >/dev/null
local cached_end
cached_end=$(date +%s.%N)
local cached_time
cached_time=$(echo "$cached_end - $cached_start" | bc)
# Calculate performance improvement
local improvement
improvement=$(echo "scale=2; $uncached_time / $cached_time" | bc)
echo "Cache Performance:"
echo " Uncached query time: ${uncached_time}s"
echo " Cached query time: ${cached_time}s"
echo " Performance improvement: ${improvement}x"
}
test_cross_namespace_pod_dns() {
echo "Testing cross-namespace pod DNS resolution"
# Get pods from different namespaces
local source_namespace="production"
local target_namespace="database"
# Test from production pod to database pod
local production_pods
production_pods=$(kubectl get pods -n $source_namespace -o json | \
jq -r '.items[] | select(.status.phase=="Running") | .metadata.name' | head -1)
local database_pods
database_pods=$(kubectl get pods -n $target_namespace -o json | \
jq -r '.items[] | select(.status.phase=="Running") | .metadata.name' | head -1)
if [[ -n "$production_pods" && -n "$database_pods" ]]; then
# Get database pod IP
local db_pod_ip
db_pod_ip=$(kubectl get pod "$database_pods" -n $target_namespace -o jsonpath='{.status.podIP}')
# Generate DNS name
local db_dns_name="${db_pod_ip//./-}.$target_namespace.pod.cluster.local"
echo "Testing resolution of $db_dns_name from $source_namespace"
# Test DNS resolution from production pod
local result
result=$(kubectl exec -n $source_namespace "$production_pods" -- \
dig +short "$db_dns_name" A 2>/dev/null | head -n1)
if [[ "$result" == "$db_pod_ip" ]]; then
echo "✅ SUCCESS: Cross-namespace pod DNS resolution works"
else
echo "❌ FAILED: Cross-namespace pod DNS resolution failed"
fi
else
echo "⚠️ SKIPPED: No suitable pods found for cross-namespace test"
fi
}
validate_pod_dns_security() {
echo "Validating Pod DNS security configuration"
# Check if pod DNS is properly configured
local coredns_config
coredns_config=$(kubectl get configmap coredns -n kube-system -o jsonpath='{.data.Corefile}')
if echo "$coredns_config" | grep -q "pods verified"; then
echo "✅ SUCCESS: Pod DNS is configured with 'verified' mode"
elif echo "$coredns_config" | grep -q "pods insecure"; then
echo "⚠️ WARNING: Pod DNS is configured with 'insecure' mode"
else
echo "❌ FAILED: Pod DNS configuration not found or disabled"
fi
# Check for rate limiting
if echo "$coredns_config" | grep -q "ratelimit"; then
echo "✅ SUCCESS: Rate limiting is configured"
else
echo "⚠️ WARNING: Rate limiting not configured"
fi
# Check for access control
if echo "$coredns_config" | grep -q "acl"; then
echo "✅ SUCCESS: Access control is configured"
else
echo "⚠️ WARNING: Access control not configured"
fi
}
generate_test_report() {
echo "Generating comprehensive test report"
local report_file="$RESULTS_DIR/pod_dns_test_report.html"
cat > "$report_file" <<EOF
<!DOCTYPE html>
<html>
<head>
<title>Pod DNS Test Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.success { color: green; }
.warning { color: orange; }
.failure { color: red; }
.test-section { margin: 20px 0; padding: 10px; border: 1px solid #ccc; }
pre { background: #f5f5f5; padding: 10px; overflow-x: auto; }
</style>
</head>
<body>
<h1>Pod DNS Resolution Test Report</h1>
<p>Generated on: $(date)</p>
<div class="test-section">
<h2>Test Configuration</h2>
<ul>
<li>Namespace: $NAMESPACE</li>
<li>DNS Server: $DNS_SERVER</li>
<li>Test Iterations: $TEST_ITERATIONS</li>
</ul>
</div>
<div class="test-section">
<h2>Performance Test Results</h2>
<p>Performance test results are available in JSON format:</p>
<ul>
EOF
# Add performance test results to report
for result_file in "$RESULTS_DIR"/performance_*.json; do
if [[ -f "$result_file" ]]; then
local dns_name
dns_name=$(jq -r '.dns_name' "$result_file")
local success_rate
success_rate=$(jq -r '.success_rate' "$result_file")
local avg_time
avg_time=$(jq -r '.average_query_time' "$result_file")
echo " <li>$dns_name - Success: ${success_rate}%, Avg Time: ${avg_time}s</li>" >> "$report_file"
fi
done
cat >> "$report_file" <<EOF
</ul>
</div>
<div class="test-section">
<h2>Test Summary</h2>
<p>All performance data and detailed results are available in: $RESULTS_DIR</p>
</div>
</body>
</html>
EOF
echo "Test report generated: $report_file"
}
# Main test execution
main() {
echo "=== Pod DNS Resolution Testing Suite ==="
echo "Start time: $(date)"
echo
# Get test pods from namespace
local test_pods
test_pods=$(kubectl get pods -n $NAMESPACE -o json | \
jq -r '.items[] | select(.status.phase=="Running") | "\(.metadata.name) \(.status.podIP)"')
if [[ -z "$test_pods" ]]; then
echo "No running pods found in namespace: $NAMESPACE"
exit 1
fi
# Test individual pods
echo "=== Individual Pod DNS Tests ==="
local failed_tests=0
while IFS= read -r pod_line; do
if [[ -n "$pod_line" ]]; then
local pod_name
pod_name=$(echo "$pod_line" | cut -d' ' -f1)
local pod_ip
pod_ip=$(echo "$pod_line" | cut -d' ' -f2)
test_pod_ip_resolution "$pod_name" "$NAMESPACE" "$pod_ip" || ((failed_tests++))
# Performance test
local ip_dns_name="${pod_ip//./-}.$NAMESPACE.pod.cluster.local"
test_pod_dns_performance "$ip_dns_name" 50
# Cache behavior test
test_pod_dns_cache_behavior "$ip_dns_name"
fi
done <<< "$test_pods"
echo
echo "=== Cross-Namespace Tests ==="
test_cross_namespace_pod_dns
echo
echo "=== Security Validation ==="
validate_pod_dns_security
echo
echo "=== Test Report Generation ==="
generate_test_report
echo
echo "=== Test Summary ==="
echo "Failed individual tests: $failed_tests"
echo "Results directory: $RESULTS_DIR"
if [[ $failed_tests -eq 0 ]]; then
echo "✅ All Pod DNS tests completed successfully!"
exit 0
else
echo "❌ Some Pod DNS tests failed!"
exit 1
fi
}
# Execute main function
main "$@"
Conclusion
IP-based Pod DNS resolution provides the foundation for advanced Kubernetes networking patterns that enable direct pod communication, service mesh integration, and sophisticated distributed system architectures. The configurations and patterns presented in this guide demonstrate how organizations can implement secure, performant pod-to-pod networking while maintaining operational excellence and security compliance.
Key success factors include proper CoreDNS configuration with appropriate security modes, comprehensive network policies, effective service mesh integration, and proactive monitoring of DNS resolution performance. Organizations implementing these patterns can expect improved application performance, enhanced networking flexibility, and better support for complex distributed system requirements.
The combination of verified pod DNS resolution, advanced service discovery patterns, and comprehensive security controls provides a robust foundation for modern Kubernetes networking infrastructure capable of supporting enterprise-grade applications and evolving architectural requirements.