Any developer who works with containerized apps needs to know how Kubernetes networking works. Learning these three basic parts—Services, Ingress, and Network Policies—will make your development process much more efficient, whether you’re routing traffic between services, making apps available to outside users, or keeping communication between pods secure.
This detailed book will look at each part in depth, with real-world examples and important instructions that will make your daily development chores easier.
What Kubernetes Services Are?
In Kubernetes, services provide a reliable approach to make your apps available and accessible. Think of them as the network that links your pods to each other and to the rest of the world. Services give your apps a consistent endpoint, unlike pods, which are temporary and can be made or terminated at any time.
Types of Services
ClusterIP (Default) The most common service type, ClusterIP creates an internal IP address accessible only within the cluster. This is perfect for internal communication between your microservices.
# Create a ClusterIP service
kubectl create service clusterip my-app --tcp=80:8080
# Or using YAML
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
EOF
NodePort NodePort exposes your service on a specific port across all cluster nodes. This is useful for development and testing scenarios.
# Create a NodePort service
kubectl create service nodeport my-app --tcp=80:8080 --node-port=30080
# Check the assigned port
kubectl get svc my-app -o jsonpath='{.spec.ports[0].nodePort}'
LoadBalancer LoadBalancer integrates with cloud providers to provision external load balancers. This is the go-to choice for production applications that need external access.
# Create a LoadBalancer service
kubectl create service loadbalancer my-app --tcp=80:8080
# Monitor the external IP assignment
kubectl get svc my-app --watch
Essential Service Commands
# List all services
kubectl get services
# Get detailed service information
kubectl describe service my-app
# View service endpoints
kubectl get endpoints my-app
# Test service connectivity from within the cluster
kubectl run test-pod --image=busybox --rm -it --restart=Never -- wget -qO- http://my-app-service
# Port forward for local testing
kubectl port-forward service/my-app 8080:80
# Delete a service
kubectl delete service my-app
Mastering Kubernetes Ingress
Ingress makes your HTTP (or HTTPS) network service available using a protocol-aware configuration mechanism, that understands web concepts like URIs, hostnames, paths, and more. It acts as the smart gateway that routes external traffic to your internal services based on rules you define.
Setting Up Ingress
Before creating Ingress resources, you need an Ingress Controller. In order for an Ingress to work in your cluster, there must be an ingress controller running. The most popular choice is NGINX Ingress Controller.
# Install NGINX Ingress Controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.0/deploy/static/provider/cloud/deploy.yaml
# For Minikube users
minikube addons enable ingress
# Verify installation
kubectl get pods -n ingress-nginx
Creating Ingress Resources
Basic Ingress Example
# Create a simple ingress using kubectl
kubectl create ingress simple --rule="foo.com/bar=svc1:8080,tls=my-cert"
# Or using YAML for more control
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-service
port:
number: 80
EOF
Advanced Ingress with Multiple Paths
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-path-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: api.example.com
http:
paths:
- path: /v1/users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
- path: /v1/orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 8080
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 3000
Ingress with TLS/SSL
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: secure-ingress
spec:
tls:
- hosts:
- secure.example.com
secretName: tls-secret
rules:
- host: secure.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: secure-app
port:
number: 80
Essential Ingress Commands
# List all ingress resources
kubectl get ingress
# Get detailed ingress information
kubectl describe ingress my-app-ingress
# Edit ingress resource
kubectl edit ingress my-app-ingress
# Check ingress controller logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
# Test ingress connectivity
curl -H "Host: myapp.example.com" http://$(kubectl get ingress my-app-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
# Port forward to ingress controller for local testing
kubectl port-forward -n ingress-nginx service/ingress-nginx-controller 8080:80
Implementing Network Policies for Security
NetworkPolicies allow you to specify rules for traffic flow within your cluster, and also between Pods and the outside world. They’re essential for implementing zero-trust networking and microservice security.
Prerequisites
Your cluster must use a network plugin that supports NetworkPolicy enforcement. Popular options include:
- Calico
- Cilium
- Weave Net
# Check if your cluster supports NetworkPolicy
kubectl api-versions | grep networking.k8s.io
# For Calico installation
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
Network Policy Best Practices
Start with a deny-all policy: Start by denying all network traffic and gradually allow only the necessary traffic as you identify it. This approach, known as “zero-trust” networking, significantly reduces your attack surface.
Default Deny-All Policy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Allow Internal Communication
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-internal
namespace: production
spec:
podSelector:
matchLabels:
app: web-app
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
Allow External Access
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-external
namespace: production
spec:
podSelector:
matchLabels:
app: api-gateway
policyTypes:
- Ingress
- Egress
ingress:
- from: [] # Allow from anywhere
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
egress:
- to: [] # Allow to anywhere
ports:
- protocol: TCP
port: 443 # HTTPS
- protocol: TCP
port: 53 # DNS
- protocol: UDP
port: 53 # DNS
Advanced Network Policy Examples
Namespace-Based Access Control
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-namespace
namespace: backend
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
ports:
- protocol: TCP
port: 8080
Time-Based Access (Using Annotations)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: business-hours-only
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
spec:
podSelector:
matchLabels:
app: business-app
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: business-user
ports:
- protocol: TCP
port: 8080
Essential Network Policy Commands
# List all network policies
kubectl get networkpolicies
# Get detailed policy information
kubectl describe networkpolicy default-deny-all
# Test network connectivity
kubectl run test-pod --image=busybox --rm -it --restart=Never -- wget -qO- --timeout=2 http://target-service:8080
# Debug network policy issues
kubectl get pods -o wide
kubectl exec -it source-pod -- nslookup target-service
# Check policy effectiveness
kubectl get networkpolicy -o yaml
# Delete network policy
kubectl delete networkpolicy policy-name
Putting It All Together: Complete Example
Let’s create a complete example that demonstrates Services, Ingress, and Network Policies working together:
# Application Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: web-app
tier: frontend
template:
metadata:
labels:
app: web-app
tier: frontend
spec:
containers:
- name: web-app
image: nginx:1.21
ports:
- containerPort: 80
---
# ClusterIP Service
apiVersion: v1
kind: Service
metadata:
name: web-app-service
namespace: production
spec:
selector:
app: web-app
ports:
- protocol: TCP
port: 80
targetPort: 80
---
# Ingress Resource
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-app-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: webapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-app-service
port:
number: 80
---
# Network Policy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-app-netpol
namespace: production
spec:
podSelector:
matchLabels:
app: web-app
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 80
egress:
- to: []
ports:
- protocol: TCP
port: 443
- protocol: TCP
port: 53
- protocol: UDP
port: 53
Troubleshooting Common Issues
Service Discovery Problems
# Check service endpoints
kubectl get endpoints service-name
# Verify pod labels match service selector
kubectl get pods --show-labels
kubectl get service service-name -o yaml
# Test DNS resolution
kubectl run debug --image=busybox --rm -it --restart=Never -- nslookup service-name
Ingress Not Working
# Check ingress controller status
kubectl get pods -n ingress-nginx
# Verify ingress resource
kubectl get ingress -o wide
# Check ingress controller logs
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
# Test with curl
curl -H "Host: your-domain.com" http://ingress-ip
Network Policy Blocking Traffic
# List all policies affecting a pod
kubectl get networkpolicy -o wide
# Check policy selectors
kubectl describe networkpolicy policy-name
# Test connectivity step by step
kubectl exec -it source-pod -- telnet target-service port
Performance Optimization Tips
Service Optimization
# Use headless services for direct pod communication
kubectl create service clusterip my-service --clusterip="None"
# Enable session affinity for stateful applications
kubectl patch service my-service -p '{"spec":{"sessionAffinity":"ClientIP"}}'
Ingress Optimization
# Use appropriate annotations for better performance
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-buffer-size: "8k"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
Network Policy Optimization
Use specific pod selectors to avoid unintentionally including new pods and leverage monitoring tools to evaluate how your ingress and egress policies perform.
Monitoring and Observability
# Monitor service health
kubectl get services --watch
# Check ingress metrics
kubectl top pods -n ingress-nginx
# View network policy logs (if supported by CNI)
kubectl logs -n kube-system -l k8s-app=calico-node
# Use kubectl events for troubleshooting
kubectl get events --sort-by='.lastTimestamp'
Conclusion
To develop strong, safe, and scalable apps, you need to know how to use Services, Ingress, and Network Policies to manage Kubernetes networking. Services are the building blocks of internal communication, Ingress manages exterior traffic routing in a smart way, and Network Policies make sure your apps follow security best practices.
Keep these important points in mind:
- Always use ClusterIP services for internal communication and only let others outside of your network see them when you need to.
- When you can, use Ingress instead of LoadBalancer services to route HTTP and HTTPS traffic.
- Use a deny-all strategy for network policies and only let in traffic that is needed over time.
- Check the performance of your network setup and test it often.
You should be able to handle most Kubernetes networking situations well with these commands and examples in your toolkit. The most important thing is to start with simple things, test them well, and then add more complicated things as your apps expand.
If you keep using these commands, you’ll quickly discover that Kubernetes networking becomes second nature in your development process.