Kubernetes Network Policies
Network Policies provide fine-grained control over traffic flow between pods in a Kubernetes clúster. They define how pods can communicate with each other and external servicios, implementing a zero-trust reding model. Esta guía cubre ingreso and egress rules, espacio de nombres isolation, and implementations using Calico and Cilium CNI plugins.
Tabla de contenidos
- Network Policy Fundamentals
- Network Policy Syntax
- Ingress Rules
- Egress Rules
- [Namespace Isolation](#espacio de nombres-isolation)
- Calico Implementation
- Cilium Implementation
- Practical Examples
- Conclusion
Network Policy Fundamentals
What are Network Policies?
Network Policies are Kubernetes objects that specify how pods communicate with each other and with red endpoints. They work like reglas de firewall for pod-to-pod traffic.
Requisitos previos
Network Policies require a red plugin que soporta them. Default red plugins (like Flannel) don't support policies. You need:
- Calico: Fully-featured red policy support
- Cilium: Advanced policy with eBPF-based implementation
- Kube-router: Lightweight option
- Weave Net: Network policy support available
Policy Evaluation
When a Network Policy is defined, it creates a whitelist of allowed traffic. By default:
- All traffic is allowed (if no policies exist)
- Once a policy targets pods, only traffic matching that policy is allowed
- Multiple policies combine with OR logic (traffic allowed if ANY policy permits it)
Network Policy Syntax
Basic Structure
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: production
spec:
podSelector: {} # Applies to all pods in namespace
policyTypes:
- Ingress
- Egress
ingress: [] # No ingress traffic allowed
egress: [] # No egress traffic allowed
Pod Selection
Target specific pods:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: production
spec:
podSelector:
matchLabels:
tier: backend
policyTypes:
- Ingress
- Egress
Policy Types
- Ingress: Controls incoming traffic to pods
- Egress: Controls outgoing traffic from pods
- Both: Restricts both directions
Ingress Rules
Allow All Ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- {} # Empty rule allows all traffic
Allow from Specific Pods
Allow traffic from pods in the same espacio de nombres:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
namespace: production
spec:
podSelector:
matchLabels:
tier: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: frontend
ports:
- protocol: TCP
port: 8080
Allow from Namespace
Allow traffic from any pod in another espacio de nombres:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-monitoring
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 9090
Allow from External Networks
Allow traffic from specific external reds:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-external-api
namespace: production
spec:
podSelector:
matchLabels:
app: api-gateway
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 203.0.113.0/24 # External network
except:
- 203.0.113.5/32 # Exclude specific IP
ports:
- protocol: TCP
port: 443
Multiple Sources
Allow traffic from multiple sources:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-multiple-sources
namespace: production
spec:
podSelector:
matchLabels:
tier: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: backend
- podSelector:
matchLabels:
tier: admin
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 5432
- protocol: TCP
port: 9100 # Prometheus exporter
Egress Rules
Allow All Egress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- {} # Allow all egress
Restrict Egress to Specific Pods
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-egress
namespace: production
spec:
podSelector:
matchLabels:
tier: frontend
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
tier: backend
ports:
- protocol: TCP
port: 8080
Allow DNS and External Access
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-external
namespace: production
spec:
podSelector:
matchLabels:
tier: app
policyTypes:
- Egress
egress:
# DNS
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
# External HTTPS
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 169.254.169.254/32 # Block AWS metadata
ports:
- protocol: TCP
port: 443
Namespace Isolation
Deny All Traffic to Namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress: []
egress: []
Apply to all espacio de nombress:
# Create the policy in each namespace
for ns in production staging development; do
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: $ns
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
EOF
done
Allow Traffic Within Namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {} # Any pod in same namespace
Allow Ingress from Specific Namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
Calico Implementation
Instalaing Calico
Instala Calico as your CNI:
# Download Calico manifest
curl https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/tigera-operator.yaml -o tigera-operator.yaml
# Apply operator
kubectl apply -f tigera-operator.yaml
# Wait for operator to be ready
kubectl wait --for=condition=ready pod -l k8s-app=tigera-operator -n tigera-operator --timeout=300s
Instala Calico custom resource:
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
calicoNetwork:
ipPools:
- blockSize: 26
cidr: 10.0.0.0/16
encapsulation: VXLAN
natOutgoing: Enabled
nodeSelector: all()
nodeAddressAutodetectionV4:
interface: eth0
Calico NetworkPolicy Extensions
Calico supports additional NetworkPolicy features:
apiVersion: crd.projectcalico.org/v1
kind: NetworkPolicy
metadata:
name: advanced-policy
namespace: production
spec:
selector: tier == "backend"
types:
- Ingress
- Egress
ingress:
- action: Allow
protocol: TCP
destination:
ports:
- 8080
egress:
- action: Allow
protocol: TCP
destination:
nets:
- 10.0.0.0/8
- action: Allow
protocol: UDP
destination:
ports:
- 53
Calico Policy Rules
Calico allows more granular control:
# View Calico workload endpoints
calicoctl get workloadendpoints -n production
# View Calico policies
calicoctl get networkpolicies -n production
# Describe a policy
calicoctl get networkpolicies production.allow-frontend -o yaml
Cilium Implementation
Instalaing Cilium
Instala Cilium with Helm:
helm repo add cilium https://helm.cilium.io
helm repo update
helm install cilium cilium/cilium \
--namespace kube-system \
--set kubeProxyReplacement=disabled \
--set k8sServiceHost=10.0.0.10 \
--set k8sServicePort=6443 \
--set image.tag=v1.14.0
Wait for Cilium to be ready:
kubectl rollout status -n kube-system ds/cilium
Cilium Network Policies
Cilium supports standard Kubernetes NetworkPolicy plus extended features:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: production
spec:
podSelector:
matchLabels:
tier: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
tier: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
tier: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
Cilium CLI for Debugging
# Install cilium CLI
curl -L --remote-name-all https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
# Check Cilium status
cilium status
# Inspect connectivity between pods
cilium connectivity test
# View policy enforcement
cilium policy get
Practical Examples
Ejemplo: Three-Tier Application
Frontend, backend, and database isolation:
---
# Deny all by default
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress: []
---
# Allow external traffic to frontend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-ingress
namespace: production
spec:
podSelector:
matchLabels:
tier: frontend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
---
# Allow frontend to backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend
namespace: production
spec:
podSelector:
matchLabels:
tier: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: frontend
ports:
- protocol: TCP
port: 8080
---
# Allow backend to database
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-database
namespace: production
spec:
podSelector:
matchLabels:
tier: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: backend
ports:
- protocol: TCP
port: 5432
---
# Allow DNS for all pods
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
Ejemplo: Multi-Namespace Communication
Allow specific espacio de nombress to communicate:
---
# Label namespaces
# kubectl label namespace production environment=prod
# kubectl label namespace monitoring environment=monitoring
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
environment: monitoring
ports:
- protocol: TCP
port: 9090
Ejemplo: Microservicios Communication
Complex servicio mesh with specific rules:
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: order-service-policy
namespace: microservices
spec:
podSelector:
matchLabels:
service: order
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
service: api-gateway
ports:
- protocol: TCP
port: 8080
egress:
# To payment service
- to:
- podSelector:
matchLabels:
service: payment
ports:
- protocol: TCP
port: 8080
# To inventory service
- to:
- podSelector:
matchLabels:
service: inventory
ports:
- protocol: TCP
port: 8080
# To databases
- to:
- podSelector:
matchLabels:
service: postgres
ports:
- protocol: TCP
port: 5432
# DNS
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
Conclusión
Network Policies are essential for implementing zero-trust reding in Kubernetes. By carefully planning your communication requirements and implementing deny-all-by-default policies with explicit allow rules, you create a secure red architecture. Whether using Calico for comprehensive red policy support or Cilium for advanced eBPF-based enforcement, proper red segmentation protects your applications on VPS and baremetal infrastructure. Start with liberal policies and gradually restrict traffic as you understand your application requirements, then maintain clear documentation of each policy's purpose and scope.


