Kubernetes Networking: Services, Ingress, and Network Policies
Kubernetes Networking: Services, Ingress, and Network Policies
Kubernetes Networking: Services, Ingress, and Network Policies
Master Kubernetes networking concepts including Services, Ingress controllers, and Network Policies for secure communication between pods.
Lab: Kubernetes Networking in Action
Prerequisites
- Completed "Introduction to Kubernetes" module
- Access to a Kubernetes cluster
- kubectl CLI configured
- Ingress controller installed (e.g., nginx-ingress)
- Cluster can pull public container images (e.g.,
curlimages/curl
)
Step 1: Create a Namespace and Deployment
Create a namespace:
kubectl create namespace networking-lab
Create a deployment with multiple replicas:
kubectl create deployment web --image=nginx:latest --replicas=3 --namespace=networking-lab
Verify the pods are running:
kubectl get pods -n networking-lab -o wide
Note the IP addresses of each pod.
Step 2: Create a ClusterIP Service
Create a file named service-clusterip.yaml
:
apiVersion: v1
kind: Service
metadata:
name: web-service
namespace: networking-lab
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Apply the Service:
kubectl apply -f service-clusterip.yaml
Get the Service details:
kubectl get service web-service -n networking-lab
Test the Service from within the cluster using a lightweight curl image:
kubectl run test-client --image=curlimages/curl:8.5.0 --namespace=networking-lab --rm -it --restart=Never -- -s http://web-service
Step 3: Explore Service Discovery
Services are automatically registered in DNS:
kubectl run dns-test --image=busybox --namespace=networking-lab --rm -it --restart=Never -- nslookup web-service
The service is accessible at: web-service.networking-lab.svc.cluster.local
Step 4: Create a NodePort Service
Create a file named service-nodeport.yaml
:
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
namespace: networking-lab
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
type: NodePort
Apply the NodePort Service:
kubectl apply -f service-nodeport.yaml
Get the Service info:
kubectl get service web-nodeport -n networking-lab
Access the service on any node's IP at port 30080.
Step 5: Create a LoadBalancer Service
Create a file named service-loadbalancer.yaml
:
apiVersion: v1
kind: Service
metadata:
name: web-loadbalancer
namespace: networking-lab
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
Apply the LoadBalancer Service:
kubectl apply -f service-loadbalancer.yaml
Wait for external IP assignment:
kubectl get service web-loadbalancer -n networking-lab --watch
(This requires a cloud provider or MetalLB)
Step 6: Create an Ingress Resource
First, create a second deployment:
kubectl create deployment api --image=hashicorp/http-echo --namespace=networking-lab -- -text="API Response"
Create a Service for the API:
kubectl expose deployment api --port=5678 --namespace=networking-lab
Create a file named ingress.yaml
:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
namespace: networking-lab
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 5678
Apply the Ingress:
kubectl apply -f ingress.yaml
Check Ingress status:
kubectl get ingress -n networking-lab
Test with curl by resolving the hostnames to the Ingress IP (either update /etc/hosts
or use --resolve
):
curl --resolve web.example.com:80:<ingress-ip> http://web.example.com
curl --resolve api.example.com:80:<ingress-ip> http://api.example.com
Step 7: Implement Network Policies
By default, all pods can communicate with each other. Let's restrict this.
Create a file named network-policy-deny-all.yaml
:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: networking-lab
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Apply the policy:
kubectl apply -f network-policy-deny-all.yaml
Test connectivity (it should fail). --max-time
stops curl after five seconds so the command exits quickly:
kubectl run deny-check --image=curlimages/curl:8.5.0 --namespace=networking-lab --rm -it --restart=Never -- --max-time 5 -sf http://web-service
Step 8: Allow Specific Traffic
Create a file named network-policy-allow-web.yaml
:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-web-traffic
namespace: networking-lab
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
ports:
- protocol: TCP
port: 80
Apply the policy:
kubectl apply -f network-policy-allow-web.yaml
Also allow DNS:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: networking-lab
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
kubectl apply -f network-policy-allow-dns.yaml
Now test again (should work):
kubectl run allow-check --image=curlimages/curl:8.5.0 --namespace=networking-lab --rm -it --restart=Never -- -sf http://web-service
Step 9: Verify Network Policy Enforcement
Try accessing from a different namespace (should fail):
kubectl create namespace other-namespace
kubectl run external-check --image=curlimages/curl:8.5.0 --namespace=other-namespace --rm -it --restart=Never -- --max-time 5 -sf http://web-service.networking-lab
Step 10: Clean Up
Delete the namespace:
kubectl delete namespace networking-lab
kubectl delete namespace other-namespace
Concepts: Understanding Kubernetes Networking
The Kubernetes Networking Model
Kubernetes imposes the following fundamental requirements on any networking implementation:
- Pods can communicate with all other pods on any node without NAT
- Agents on a node can communicate with all pods on that node
- Pods in the host network can communicate with all pods on all nodes without NAT
This creates a "flat" network where every pod gets its own IP address and can communicate directly with other pods.
Services: The Abstraction Layer
Pods are ephemeral—they can be created, destroyed, and moved around. Their IP addresses change. Services provide a stable endpoint for accessing a set of pods.
How Services Work:
- Service gets a stable virtual IP (ClusterIP)
- kube-proxy maintains iptables/IPVS rules on each node
- Traffic to the Service IP is load-balanced to backend pods
- Service selector determines which pods receive traffic
Service Types
ClusterIP (Default)
- Service is only accessible within the cluster
- Gets a virtual IP from the service CIDR range
- Used for internal communication between services
NodePort
- Exposes service on each node's IP at a static port (30000-32767)
- Automatically creates a ClusterIP service
- External traffic → NodePort → ClusterIP → Pods
- Use case: Simple external access, development environments
LoadBalancer
- Exposes service externally using cloud provider's load balancer
- Automatically creates NodePort and ClusterIP services
- Cloud provider provisions external load balancer
- Use case: Production external access on cloud platforms
ExternalName
- Maps service to a DNS name
- No proxying, just DNS CNAME record
- Use case: Accessing external services with a consistent internal name
Ingress: HTTP/HTTPS Routing
Ingress provides HTTP and HTTPS routing to services based on hostnames and paths. Unlike Services, Ingress is not a service type—it's a separate resource that sits in front of services.
Benefits of Ingress:
- Single entry point: One load balancer for multiple services
- Host-based routing: Route based on hostname (virtual hosting)
- Path-based routing: Route based on URL path
- TLS termination: Handle SSL/TLS certificates centrally
- Cost effective: One load balancer instead of many
Ingress Controllers:
Ingress resources don't do anything by themselves—you need an Ingress controller:
- NGINX Ingress Controller: Most popular, feature-rich
- Traefik: Modern, easy to use, automatic Let's Encrypt
- HAProxy Ingress: High performance
- Cloud-specific: AWS ALB, Google Cloud Load Balancer, Azure Application Gateway
DNS in Kubernetes
Kubernetes runs a DNS service (typically CoreDNS) that provides DNS resolution for services and pods.
Service DNS Names:
Format: <service-name>.<namespace>.svc.cluster.local
- Within same namespace: Just use
<service-name>
- Cross-namespace: Use
<service-name>.<namespace>
- Fully qualified: Use full FQDN
Pod DNS Names:
Format: <pod-ip-with-dashes>.<namespace>.pod.cluster.local
Example: 10-244-1-5.default.pod.cluster.local
Network Policies: Microsegmentation
By default, Kubernetes allows all pods to communicate with each other. Network Policies provide firewall rules to control pod-to-pod traffic.
Network Policy Features:
- Pod selector: Which pods the policy applies to
- Ingress rules: Incoming traffic controls
- Egress rules: Outgoing traffic controls
- Namespace selector: Allow traffic from specific namespaces
- IP block selector: Allow traffic from specific CIDR blocks
Important Notes:
- Network Policies are additive (allow-list, not deny-list)
- Requires a CNI plugin that supports Network Policies (Calico, Cilium, Weave)
- Default deny-all is a common starting point
- Policies are applied at the pod level, not the service level
Container Network Interface (CNI)
Kubernetes uses CNI plugins to set up pod networking. Popular CNI plugins include:
- Calico: Feature-rich, supports Network Policies, BGP routing
- Cilium: eBPF-based, high performance, observability
- Flannel: Simple, overlay network
- Weave Net: Encrypted overlay network
- AWS VPC CNI: Native AWS VPC networking
- Multus: Multiple network interfaces per pod
Common Networking Patterns
Service Mesh (Advanced):
- Istio, Linkerd, Consul Connect
- Advanced traffic management, security, observability
- Sidecar proxies for each pod
East-West Traffic:
- Service-to-service communication within the cluster
- Use ClusterIP services
- Implement Network Policies for security
North-South Traffic:
- External traffic entering/leaving the cluster
- Use LoadBalancer or Ingress
- Implement TLS termination at Ingress
Multi-Cluster Networking:
- Connect pods across multiple clusters
- Tools: Submariner, Cilium Cluster Mesh, Istio multi-cluster
Best Practices
- Use Services for discovery: Don't rely on pod IPs
- Implement Network Policies: Start with default deny-all
- Use Ingress for HTTP/HTTPS: More cost-effective than multiple LoadBalancers
- Monitor network traffic: Use tools like Cilium Hubble
- Plan IP address space: Avoid CIDR conflicts
- Secure with TLS: Use cert-manager for automatic certificate management
- Test network policies: Verify policies work as expected
- Document network architecture: Maintain diagrams of traffic flows
Understanding Kubernetes networking is essential for building secure, scalable applications.