Kubernetes Networking: Ingress and Network Policies
Service Types
# ClusterIP (default) - internal only
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
selector:
app: api
ports:
- port: 80
targetPort: 3000
type: ClusterIP # Only accessible within cluster
---
# NodePort - expose on each node's IP
spec:
type: NodePort
ports:
- port: 80
targetPort: 3000
nodePort: 30080 # 30000-32767
---
# LoadBalancer - provision cloud LB
spec:
type: LoadBalancer
ports:
- port: 443
targetPort: 3000
Nginx Ingress Controller
# Install Nginx Ingress
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
---
# Ingress with TLS
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: api-tls-cert
rules:
- host: api.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
cert-manager for Automatic TLS
# ClusterIssuer for Let's Encrypt
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ops@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
Network Policies (Zero Trust)
# Default deny all ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {} # Applies to all pods
policyTypes:
- Ingress
---
# Allow only specific traffic to API pods
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-ingress
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx # Only from ingress controller
ports:
- protocol: TCP
port: 3000
egress:
- to:
- podSelector:
matchLabels:
app: postgres # Can reach database
ports:
- protocol: TCP
port: 5432
- to:
- podSelector:
matchLabels:
app: redis
ports:
- protocol: TCP
port: 6379
DNS and Service Discovery
# Service DNS format: <service>.<namespace>.svc.cluster.local
# Within same namespace: just use service name
curl http://api-service/health
# Cross-namespace
curl http://api-service.production.svc.cluster.local/health
# Debug DNS
kubectl run debug --image=busybox --rm -it -- nslookup api-service.production.svc.cluster.local
kubectl run debug --image=nicolaka/netshoot --rm -it -- bash
Debugging Network Issues
# Check service endpoints (is your pod selected?)
kubectl get endpoints api-service
# Test connectivity from pod
kubectl exec -it <pod-name> -- curl http://api-service/health
kubectl exec -it <pod-name> -- nc -zv postgres-service 5432
# Check network policies
kubectl describe networkpolicy default-deny-ingress
# View Ingress status
kubectl describe ingress api-ingress
# Check Ingress controller logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller
NetworkPolicies implement microsegmentation - the principle of least privilege for pod communication.