Lab 05: Übung: Network Policies mit Cilium in AKS¶
Erzeuge dir für diese Übung einen Cluster wie in Aufgabe 1 und setze dir Umgebungsvariablen wie dort beschrieben.
Teil 1: Test-Umgebung aufbauen¶
Namespaces erstellen¶
Wir setzen für unser Testszenario drei getrennte Namespaces für unterschiedliche Teams ein. In der Realität stellt sich immer die Frage, ob man Namespaces pro Team oder pro Anwendung nutzen sollte. Das kann man nicht pauschal beantworten. Wir verwenden hier das teambasierte Modell.
# Drei Namespaces für verschiedene Teams/Anwendungen
kubectl create namespace team-frontend
kubectl create namespace team-backend
kubectl create namespace team-database
# Labels für Policy-Selektion hinzufügen
kubectl label namespace team-frontend environment=production tier=frontend
kubectl label namespace team-backend environment=production tier=backend
kubectl label namespace team-database environment=production tier=database
Test-Pods deployen¶
Wir erstellen drei Pods, je einen in unseren drei Namespaces:
# Frontend-Pod (Nginx)
kubectl run frontend --namespace=team-frontend \
--image=nginx:alpine \
--labels="app=frontend,tier=web" \
--port=80
# Backend-Pod (mit curl für Tests)
kubectl run backend --namespace=team-backend \
--image=curlimages/curl:latest \
--labels="app=backend,tier=api" \
--command -- sleep infinity
# Datenbank-Pod (simuliert)
kubectl run database --namespace=team-database \
--image=nginx:alpine \
--labels="app=database,tier=data" \
--port=80
# Services erstellen
kubectl expose pod frontend --namespace=team-frontend --port=80
kubectl expose pod database --namespace=team-database --port=80
Baseline-Konnektivität testen¶
Im aktuellen Zustand sollten sich alle Pods gegenseitig erreichen können.
Lasst uns das testen, indem wir mit exec einige curl-Befehle absetzen:
# Vom Backend zum Frontend (sollte funktionieren)
kubectl exec -n team-backend backend -- \
curl -s --max-time 3 frontend.team-frontend.svc.cluster.local
# Vom Backend zur Datenbank (sollte funktionieren)
kubectl exec -n team-backend backend -- \
curl -s --max-time 3 database.team-database.svc.cluster.local
# Vom Frontend zur Datenbank (sollte funktionieren)
kubectl exec -n team-frontend frontend -- \
curl -s --max-time 3 database.team-database.svc.cluster.local
Teil 2: Kubernetes-native NetworkPolicies¶
Default-Deny für einen Namespace¶
Erstellen wir nun eine Policy, die allen eingehenden Traffic zum Database-Namespace blockiert:
# Datei: 01-default-deny-database.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: team-database
spec:
podSelector: {}
policyTypes:
- Ingress
kubectl apply -f 01-default-deny-database.yaml
Konnektivität erneut testen¶
Nun sollte kein Zugriff mehr aus den anderen Namespaces auf Pods im Database- Namespace erlaubt sein.
# Vom Backend zur Datenbank (sollte NICHT mehr funktionieren)
kubectl exec -n team-backend backend -- \
curl -s --max-time 3 database.team-database.svc.cluster.local
# Erwartung: Timeout nach 3 Sekunden
Selektiven Zugriff erlauben¶
Erlauben wir nun dem Backend-Namespace Zugriff auf die Datenbank:
# Datei: 02-allow-backend-to-database.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-database
namespace: team-database
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
tier: backend
ports:
- protocol: TCP
port: 80
kubectl apply -f 02-allow-backend-to-database.yaml
Validierung¶
Jetzt sollte zwar der Backend-Pod die simulierte Datenbank erreichen können, aber nicht mehr das Frontend.
# Backend → Database (sollte funktionieren)
kubectl exec -n team-backend backend -- \
curl -s --max-time 3 database.team-database.svc.cluster.local
# Frontend → Database (sollte NICHT funktionieren)
kubectl exec -n team-frontend frontend -- \
curl -s --max-time 3 database.team-database.svc.cluster.local
Für die nächste Aufgabe räumen wir die Deny-Regel wieder auf:
kubectl delete netpol default-deny-ingress -n team-database
3 Globale Network Policies mit Cilium¶
Cilium unterstützt nicht nur auf Namespaces beschränkte Network Policies, sondern kann auch globale Network Policies definieren. Wir rollen gleich eine Network Policy aus, die den gesamten eingehenden Ingress-Verkehr auf dem Cluster blockiert. Zuerst legen wir ein Deployment mit Loadbalancer an und testen seine externe IP:
# LoadBalancer-Service für Frontend erstellen
kubectl expose pod frontend --namespace=team-frontend \
--name=frontend-lb \
--type=LoadBalancer \
--port=80
# Warten bis External-IP zugewiesen ist (kann 1-2 Minuten dauern)
kubectl get svc frontend-lb -n team-frontend -w
# External-IP speichern
FRONTEND_IP=$(kubectl get svc frontend-lb -n team-frontend -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "Frontend LoadBalancer IP: $FRONTEND_IP"
# Von außen testen (sollte funktionieren)
curl -s --max-time 5 http://$FRONTEND_IP
# Erwartung: Nginx-Willkommensseite
Nun blockieren wir über Cilium den gesamten eingehenden Ingress-Verkehr auf dem Cluster:
# 03-ccnp-default-deny-ingress.yaml
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: ccnp-default-deny-ingress
spec:
endpointSelector: {}
ingressDeny:
- fromEntities:
- all
kubectl apply -f 03-ccnp-default-deny-ingress.yaml
Daraufhin sollte nach kurzer Zeit der Cluster über die externe IP nicht mehr erreichbar sein:
curl -s --max-time 5 http://$FRONTEND_IP
Wenn du die Policy wieder löschst, wird die IP nach kurzer Zeit wieder erreichbar sein.
WICHTIG: Lösche nun wieder die CiliumClusterwideNetworkPolicy:
kubectl delete ccnp ccnp-default-deny-ingress