Kubernetes Networking Model
Kubernetes implements a flat network model with several fundamental requirements: every Pod gets its own IP address, Pods on any node can communicate with all Pods on all nodes without NAT, and agents on a node can communicate with all Pods on that node. This model simplifies networking and makes it easier to port applications from VMs to containers.
Networking Fundamentals
- Pod-to-Pod: All Pods can communicate with each other directly using their IP addresses
- Pod-to-Service: Services provide stable endpoints for a set of Pods
- External-to-Service: Services can be exposed externally via NodePort, LoadBalancer, or Ingress
- DNS: CoreDNS provides cluster-internal DNS for service discovery
Service Types
ClusterIP (Default)
Exposes the Service on a cluster-internal IP. Only reachable from within the cluster. This is the default Service type and is used for internal communication between microservices.
# clusterip-service.yaml
apiVersion: v1
kind: Service
metadata:
name: api-service
labels:
app: api
spec:
type: ClusterIP
selector:
app: api-server
ports:
- name: http
protocol: TCP
port: 80 # Port the service listens on
targetPort: 8080 # Port on the container
- name: grpc
protocol: TCP
port: 9090
targetPort: 9090
NodePort
Exposes the Service on each node's IP at a static port (30000-32767). A ClusterIP Service is automatically
created. You can reach the service externally via <NodeIP>:<NodePort>.
# nodeport-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service-nodeport
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 3000
nodePort: 30080 # Optional: auto-assigned if omitted (30000-32767)
LoadBalancer
Exposes the Service externally using the cloud provider's load balancer. This creates a NodePort and ClusterIP Service automatically, and then configures a cloud load balancer to forward traffic to the NodePort.
# loadbalancer-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service-lb
annotations:
# AWS-specific annotations
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
spec:
type: LoadBalancer
selector:
app: web
ports:
- name: http
port: 80
targetPort: 3000
- name: https
port: 443
targetPort: 3000
Headless Service
A headless Service (ClusterIP: None) does not allocate a cluster IP. Instead, DNS returns the Pod IPs directly. This is useful for stateful applications where clients need to connect to specific Pods.
# headless-service.yaml
apiVersion: v1
kind: Service
metadata:
name: postgres-headless
spec:
clusterIP: None
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
DNS in Kubernetes
CoreDNS provides DNS resolution inside the cluster. Every Service gets a DNS entry in the format:
<service-name>.<namespace>.svc.cluster.local.
# Service DNS examples:
# Same namespace: api-service
# Cross-namespace: api-service.production.svc.cluster.local
# Test DNS resolution from inside a pod
kubectl run dns-test --image=busybox:1.36 --rm -it -- nslookup api-service
# Full DNS output:
# Server: 10.96.0.10
# Address: 10.96.0.10:53
# Name: api-service.default.svc.cluster.local
# Address: 10.100.200.50
Network Policies
Network Policies are Kubernetes resources that control traffic flow between Pods. By default, all Pods can communicate with all other Pods. Network Policies let you restrict this communication for security.
# network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-network-policy
namespace: production
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
- Egress
ingress:
# Allow traffic from web frontend pods
- from:
- podSelector:
matchLabels:
app: web-frontend
ports:
- protocol: TCP
port: 8080
# Allow traffic from monitoring namespace
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 9090
egress:
# Allow DNS
- to: []
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# Allow traffic to database
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
Key Takeaways
- ClusterIP provides internal-only access, NodePort exposes on a static port, LoadBalancer integrates with cloud LBs
- CoreDNS enables service discovery via DNS names like service.namespace.svc.cluster.local
- Network Policies implement firewall rules between Pods for zero-trust networking
- Headless Services return Pod IPs directly, useful for stateful workloads
- Always define Network Policies in production to restrict unauthorized pod-to-pod traffic