Kubernetes networking is complex but crucial for understanding how pods communicate, how services work, and how external traffic reaches your applications. This guide covers all aspects of Kubernetes networking.
Core Principles:
- Every pod gets its own IP: No NAT between pods
- Pods can communicate directly: Using pod IPs
- Containers in a pod share network: Same IP, can use localhost
- Service abstraction: Stable IP for pod groups
┌─────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Pod 1 │─────│ Pod 2 │ │
│ │ 10.0.1.5 │ │ 10.0.1.6 │ │
│ └──────────┘ └──────────┘ │
│ │ │ │
│ └──────────┬───────┘ │
│ │ │
│ ┌─────▼─────┐ │
│ │ Service │ │
│ │ 10.0.2.10 │ │
│ └───────────┘ │
│ │
└─────────────────────────────────────────┘
CNI Plugins:
- Calico: Policy-driven networking
- Flannel: Simple overlay network
- Weave: Encrypted networking
- Cilium: eBPF-based networking
- Antrea: VMware's CNI
Internal-only service
apiVersion: v1
kind: Service
metadata:
name: internal-service
spec:
type: ClusterIP
selector:
app: nginx
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
- port: 443
targetPort: 8443
protocol: TCP
name: httpsExternal access via node IP
apiVersion: v1
kind: Service
metadata:
name: nodeport-service
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 8080
nodePort: 30080 # Optional, auto-assigned if not specified
protocol: TCP
name: httpAccess: http://<node-ip>:30080
External access via cloud load balancer
apiVersion: v1
kind: Service
metadata:
name: lb-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 80
targetPort: 8080
protocol: TCP
loadBalancerIP: 1.2.3.4 # Optional, cloud-specificExternal service alias
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: database.example.com
ports:
- port: 5432Direct pod access (no load balancing)
apiVersion: v1
kind: Service
metadata:
name: headless-service
spec:
clusterIP: None # Headless
selector:
app: nginx
ports:
- port: 80
targetPort: 8080Use Cases:
- StatefulSets
- Service discovery
- Direct pod access
DNS-based discovery:
# Service DNS format
<service-name>.<namespace>.svc.cluster.local
# Examples
nginx.default.svc.cluster.local
api.production.svc.cluster.localIn Pod:
env:
- name: API_URL
value: "http://api-service:8080"apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-path-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: default-service
port:
number: 80apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080Popular Controllers:
- NGINX Ingress: Most popular
- Traefik: Modern, feature-rich
- HAProxy: High performance
- Istio Gateway: Service mesh integration
- AWS ALB Ingress: AWS-specific
Install NGINX Ingress:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yamlDeny all traffic:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: production
spec:
podSelector: {} # All pods
policyTypes:
- Ingress
- EgressapiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress
namespace: production
spec:
podSelector:
matchLabels:
app: app
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53 # DNS
- to: [] # Allow all external
ports:
- protocol: TCP
port: 443
- protocol: TCP
port: 80apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: advanced-policy
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
namespaceSelector:
matchLabels:
name: production
- ipBlock:
cidr: 10.0.0.0/8
except:
- 10.0.1.0/24
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to: []
ports:
- protocol: TCP
port: 443
port: 80apiVersion: 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 . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}Service DNS:
service-name.namespace.svc.cluster.localservice-name.namespace.svcservice-name.namespaceservice-name(same namespace)
Pod DNS:
pod-ip.namespace.pod.cluster.local
# Forward local port to pod
kubectl port-forward pod/pod-name 8080:80
# Forward to service
kubectl port-forward svc/service-name 8080:80
# Forward to deployment
kubectl port-forward deployment/deployment-name 8080:80# Service with NodePort
apiVersion: v1
kind: Service
metadata:
name: nodeport-service
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080Access: http://<any-node-ip>:30080
# Cloud LoadBalancer
apiVersion: v1
kind: Service
metadata:
name: lb-service
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 80
targetPort: 80# Check service endpoints
kubectl get endpoints service-name
# Describe service
kubectl describe svc service-name
# Test DNS resolution
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup service-name
# Test connectivity
kubectl run -it --rm debug --image=busybox --restart=Never -- wget -O- http://service-name:80
# Check network policies
kubectl get networkpolicies
kubectl describe networkpolicy policy-name
# View iptables rules (on node)
sudo iptables -t nat -L# Pod can't reach service
kubectl exec pod-name -- nslookup service-name
kubectl exec pod-name -- ping service-name
kubectl get endpoints service-name
# Service not accessible externally
kubectl get svc
kubectl describe svc service-name
kubectl get ingress
kubectl describe ingress ingress-name
# Network policy blocking
kubectl get networkpolicies -n namespace
kubectl describe networkpolicy policy-name# Don't use pod IPs directly
# Use service names# Start with deny-all
# Then allow specific traffic# Don't expose services directly
# Use Ingress with TLS# Know which CNI you're using
# Understand its capabilities# Use network monitoring tools
# Track bandwidth usage# Use TLS/SSL
# Implement network policies
# Use service mesh for advanced features- Understand pod networking
- Configure different service types
- Set up Ingress with TLS
- Implement network policies
- Troubleshoot network issues
- Use DNS for service discovery
- Configure external access
- Understand CNI plugins
- Monitor network traffic
- Secure network communication
Next Steps:
- Learn Service Mesh for advanced networking
- Explore Kubernetes Storage
- Master Kubernetes Operations
Remember: Kubernetes networking is complex but powerful. Start with services and ingress, then add network policies for security. Always test connectivity and monitor network traffic.