Guardrails im Detail¶
Diese Seite beschreibt alle Guardrails der ayedo Software Delivery Plattform im Detail. Guardrails sind automatische Sicherheitsmaßnahmen, die mittels Kyverno Policies durchgesetzt werden.
Standard-Modus: Enforce
Die meisten Guardrails sind standardmäßig im Enforce-Modus aktiviert und blockieren Deployments, die gegen die Policy verstoßen. Dies verhindert, dass unsichere oder nicht-compliant Konfigurationen in Production landen.
Security Guardrails¶
Verbot privilegierter Container¶
Compliance: ISO 27001 Annex A 8.18, NIST SP 800-171 3.1.7
Zweck
Minimiert Blast Radius von Container- und OS-Schwachstellen durch Verhinderung von Root-Zugriff.
Problem¶
Viele Container Runtime- und Betriebssystem-Schwachstellen benötigen Root-Rechte, um zu einer Bedrohung zu werden. Anwendungen sollten nur als Root laufen, wenn absolut notwendig.
Leider werden viele Dockerfiles - und Container Base Images - heute standardmäßig als Root ausgeliefert. Dies macht es einfach, versehentlich Code mit Root-Rechten in Production zu deployen.
Wie hilft die ayedo SDP?¶
Die ayedo SDP schützt Sie davor, versehentlich Anwendungen als Root zu deployen. Kyverno prüft automatisch:
securityContext.runAsNonRootmusstrueseinsecurityContext.runAsUserdarf nicht0sein (Root-UID)
Fehlerme¶
ldung
Error from server: admission webhook "validate.kyverno.svc" denied the request:
policy Pod/default/myapp for resource violation:
disallow-privileged-containers:
validate-runAsNonRoot: 'validation error: Running as root is not allowed.
The field spec.securityContext.runAsNonRoot must be set to true.'
Lösung¶
Option 1: Dockerfile anpassen (bevorzugt)
FROM node:18-alpine
# Create non-root user
RUN addgroup -g 1000 appuser && \
adduser -D -u 1000 -G appuser appuser
# Switch to non-root user (numeric UID)
USER 1000
COPY --chown=1000:1000 . /app
WORKDIR /app
CMD ["node", "server.js"]
Option 2: Pod SecurityContext
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
containers:
- name: app
image: myapp:1.0.0
Best Practice
Bevorzugen Sie Änderungen am Dockerfile, damit Ihre Anwendung auch in Development und Testing als non-root läuft. Je kleiner der Unterschied zwischen den Umgebungen, desto weniger Überraschungen.
Weitere Informationen:
Keine latest Tags¶
Compliance: ISO 27001 Annex A 8.32 (Change Management)
Zweck
Verhindert unerwartete Änderungen und ermöglicht kontrollierte, nachvollziehbare Deployments.
Problem¶
Die Verwendung des :latest Tags führt zu:
- Inkonsistenten Deployments: Schwer nachzuvollziehen, welche Version deployed ist
- Rollback-Problemen: Schwierig, auf vorherige Version zurückzukehren
- Unerwarteten Änderungen:
:latestist nur ein Tag, keine dynamische Referenz
Häufiges Missverständnis
Auch wenn kein Tag angegeben wird, nutzt Kubernetes :latest - aber das bedeutet NICHT, dass die neueste Version verwendet wird! :latest ist nur ein Tag wie jeder andere.
Wie hilft die ayedo SDP?¶
Kyverno blockiert Images mit :latest Tag oder ohne explizites Tag.
Fehlermeldung¶
Error from server: admission webhook "validate.kyverno.svc" denied the request:
policy Pod/default/myapp for resource violation:
disallow-latest-tag:
validate-image-tag: 'validation error: Image tag "latest" is not allowed.
Images must use explicit version tags.'
Lösung¶
Verwenden Sie immer explizite, immutable Tags:
Gut:
image: harbor.ayedo.cloud/myapp:v1.2.3
image: harbor.ayedo.cloud/myapp:sha256-abc123def
image: myapp:2024-01-15-f6451806
Schlecht:
image: myapp:latest
image: myapp # Impliziert :latest
image: myapp:dev # Mutable tag
image: myapp:prod # Mutable tag
Best Practice für Tags
- Semantic Versioning:
v1.2.3,v2.0.0 - Git Commit Hash:
sha256-f6451806,git-abc123 - Timestamp + Hash:
2024-01-15-abc123 - Behandeln Sie alle Tags als immutable: Erstellen Sie immer neue Tags statt bestehende zu überschreiben
Weitere Informationen:
Resource Requests erforderlich¶
Compliance: ISO 27001 Annex A 8.6 (Kapazitätsplanung)
Zweck
Verhindert Downtime durch Resource Exhaustion und ermöglicht optimale Pod-Platzierung.
Problem¶
Eine Hauptursache für Anwendungsausfälle ist unzureichende Kapazität:
- CPU-Überlastung: Node erreicht 100% CPU → Anwendung läuft langsam
- Memory Pressure: Node hat zu wenig Memory → Page Cache wird kleiner → Anwendung langsamer
- OOM Killer: Bei extremem Memory Pressure tötet der Out-of-Memory Killer Prozesse
Lösung¶
Kubernetes erlaubt es, Resource Requests und Limits zu definieren. Dies bietet zwei Vorteile:
- Scheduling: Pods werden nur auf Nodes platziert, die genug Ressourcen haben
- Isolation: Pods können ihre Limits nicht überschreiten und schützen so andere Pods
Wie hilft die ayedo SDP?¶
Kyverno erzwingt, dass alle Container CPU und Memory Requests definieren müssen.
Fehlermeldung¶
Error from server: admission webhook "validate.kyverno.svc" denied the request:
policy Deployment/default/myapp for resource violation:
require-requests-limits:
validate-resources: 'validation error: CPU and memory resource requests
are required. Container "myapp" is missing requests.'
Lösung¶
Definieren Sie Requests (und optional Limits) für alle Container:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: myapp
image: myapp:v1.0.0
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
Sizing Guidelines
Requests: Was die Anwendung normal benötigt
- Start mit konservativen Schätzungen
- Beobachten Sie tatsächliche Nutzung in VictoriaMetrics/Grafana
- Passen Sie basierend auf Daten an
Limits: Maximum, das die Anwendung nutzen darf
- CPU Limit: 2-3x Request (Bursts erlauben)
- Memory Limit: 1.5-2x Request (OOM vermeiden)
- Für kritische Workloads: Limit = Request (garantierte Ressourcen)
CPU-Einheiten:
1000m=1= 1 CPU Core100m= 0.1 CPU Core500m= 0.5 CPU Core
Memory-Einheiten:
Mi= Mebibyte (1024²)Gi= Gibibyte (1024³)- Beispiel:
256Mi,1Gi,512Mi
Weitere Informationen:
Network Policies erforderlich¶
Compliance: ISO 27001 Annex A 8.20 (Networks Controls), BSI APP.4.4.A19
Zweck
Implementiert Netzwerk-Segmentierung und minimiert laterale Bewegung bei Kompromittierung.
Problem¶
Ohne Network Policies können alle Pods miteinander kommunizieren. Bei einer Kompromittierung kann ein Angreifer sich lateral durch das Cluster bewegen.
Wie hilft die ayedo SDP?¶
Kyverno erzwingt, dass jeder Namespace mindestens eine NetworkPolicy definiert hat. Cilium setzt diese Policies auf Kernel-Ebene durch.
Fehlermeldung¶
Error from server: admission webhook "validate.kyverno.svc" denied the request:
policy Namespace/myapp for resource violation:
require-networkpolicy:
check-networkpolicy-exists: 'validation error: Namespace must have at
least one NetworkPolicy defined.'
Lösung¶
Definieren Sie NetworkPolicies für Ihren Namespace:
Beispiel: Default Deny All
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: myapp
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Beispiel: Allow from Ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-ingress
namespace: myapp
spec:
podSelector:
matchLabels:
app: myapp
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 8080
Beispiel: Allow to Database
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-to-database
namespace: myapp
spec:
podSelector:
matchLabels:
app: myapp
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
name: database
ports:
- protocol: TCP
port: 5432
- to: # DNS
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
Best Practice
- Start mit Default Deny: Blockieren Sie zunächst allen Traffic
- Whitelist Approach: Erlauben Sie explizit nur notwendigen Traffic
- Label-basiert: Nutzen Sie Labels statt IP-Adressen
- Testen Sie: Verifizieren Sie Policies mit
kubectl exec ... -- curl
Weitere Informationen:
Trusted Registries¶
Compliance: ISO 27001 Annex A 8.19 (Security in Development/Support)
Zweck
Verhindert Nutzung von Images aus nicht-vertrauenswürdigen Quellen und reduziert Supply Chain Risiken.
Problem¶
Images aus öffentlichen oder unbekannten Registries können:
- Malware enthalten
- Schwachstellen haben
- Backdoors enthalten
- Nicht compliance-konform sein
Wie hilft die ayedo SDP?¶
Kyverno erlaubt nur Images aus konfigurierten vertrauenswürdigen Registries (z.B. Harbor).
Fehlermeldung¶
Error from server: admission webhook "validate.kyverno.svc" denied the request:
policy Pod/default/myapp for resource violation:
restrict-image-registries:
validate-registries: 'validation error: Image must be from an approved
registry. Allowed registries: harbor.ayedo.cloud'
Lösung¶
Pushen Sie Ihre Images zu Harbor und referenzieren Sie sie von dort:
Falsch:
Richtig:
image: harbor.ayedo.cloud/myproject/myapp:v1.0.0
image: harbor.ayedo.cloud/myproject/nginx:1.25-alpine
Image Mirror Workflow
Für externe Images:
- Pull von öffentlicher Registry:
docker pull nginx:1.25-alpine - Re-tag:
docker tag nginx:1.25-alpine harbor.ayedo.cloud/myproject/nginx:1.25-alpine - Scan: Harbor scannt automatisch auf Vulnerabilities
- Push:
docker push harbor.ayedo.cloud/myproject/nginx:1.25-alpine - Verwenden Sie das gespiegelte Image
Weitere Informationen:
Reliability Guardrails¶
Minimum Replicas¶
Compliance: ISO 27001 Annex A 8.6, GDPR Art. 32 (Availability)
Zweck
Stellt Hochverfügbarkeit sicher und verhindert Single Points of Failure.
Problem¶
Deployments mit nur 1 Replica haben keinen Schutz gegen:
- Pod-Ausfälle
- Node-Ausfälle
- Rolling Updates (führen zu Downtime)
Wie hilft die ayedo SDP?¶
Kyverno erzwingt mindestens 2 Replicas für Deployments in Production-Namespaces.
Fehlermeldung¶
Error from server: admission webhook "validate.kyverno.svc" denied the request:
policy Deployment/production/myapp for resource violation:
minimum-replicas:
check-replicas: 'validation error: Minimum 2 replicas required in
production namespaces. Current: 1'
Lösung¶
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: production
spec:
replicas: 3 # Mindestens 2, besser 3+
template:
# ...
Replica Count Guidelines
- Development: 1 Replica OK
- Staging: 2 Replicas
- Production: 3+ Replicas
- Kritische Services: 5+ Replicas über mehrere Zones
Weitere Informationen:
PodDisruptionBudgets¶
Compliance: ISO 27001 Annex A 8.6, GDPR Art. 32 (Resilience)
Zweck
Schützt vor Downtime während Wartungsarbeiten und Node-Drains.
Problem¶
Ohne PodDisruptionBudget kann Kubernetes während:
- Rolling Updates
- Node Drains
- Cluster Upgrades
alle Pods einer Anwendung gleichzeitig beenden, was zu Downtime führt.
Wie hilft die ayedo SDP?¶
Kyverno warnt, wenn Deployments mit mehreren Replicas keine PodDisruptionBudgets haben (Audit-Mode).
Lösung¶
Definieren Sie PodDisruptionBudgets:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb
namespace: production
spec:
minAvailable: 2 # Mindestens 2 Pods müssen laufen
selector:
matchLabels:
app: myapp
Alternativ mit Prozent:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb
spec:
maxUnavailable: 25% # Maximal 25% dürfen gleichzeitig down sein
selector:
matchLabels:
app: myapp
PDB Guidelines
- minAvailable: Garantiert Mindestanzahl laufender Pods
- maxUnavailable: Limitiert gleichzeitig ausfallende Pods
- Für 3 Replicas:
minAvailable: 2odermaxUnavailable: 1 - Für 5 Replicas:
minAvailable: 3odermaxUnavailable: 2
Weitere Informationen:
Kein Pod ohne Controller¶
Compliance: ISO 27001 Annex A 8.6
Zweck
Stellt sicher, dass Pods automatisch neu gestartet werden und Self-Healing funktioniert.
Problem¶
"Nackte" Pods (ohne Deployment, StatefulSet, DaemonSet, Job) werden bei Ausfall nicht neu gestartet.
Wie hilft die ayedo SDP?¶
Kyverno verhindert direkte Pod-Erstellung und erzwingt Nutzung von Controllern.
Fehlermeldung¶
Error from server: admission webhook "validate.kyverno.svc" denied the request:
policy Pod/default/myapp for resource violation:
require-controller:
check-controller: 'validation error: Pods must be created via Deployment,
StatefulSet, DaemonSet, or Job.'
Lösung¶
Verwenden Sie Controller statt direkter Pod-Erstellung:
Falsch:
Richtig:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1.0.0
Weitere Informationen:
Operational Guardrails¶
Keine LoadBalancer Services¶
Compliance: Kostenoptimierung, Security
Zweck
Erzwingt Nutzung von Ingress für externe Zugriffe und reduziert Kosten.
Problem¶
LoadBalancer Services:
- Kosten Geld (Cloud Provider Fees)
- Sind schwer zu verwalten (viele externe IPs)
- Keine zentralen TLS-Zertifikate
- Kein einheitliches Routing
Wie hilft die ayedo SDP?¶
Kyverno erlaubt nur ClusterIP und NodePort Services, externe Zugriffe via Ingress.
Fehlermeldung¶
Error from server: admission webhook "validate.kyverno.svc" denied the request:
policy Service/default/myapp for resource violation:
disallow-loadbalancer:
check-service-type: 'validation error: LoadBalancer Services are not
allowed. Use Ingress instead.'
Lösung¶
Verwenden Sie Ingress:
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
type: ClusterIP # Statt LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: myapp
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp
port:
number: 80
Weitere Informationen:
Kein lokaler Storage (emptyDir)¶
Compliance: ISO 27001 Annex A 8.13 (Information Backup)
Zweck
Verhindert Datenverlust bei Pod-Neustart und erzwingt Nutzung von persistentem Storage.
Problem¶
emptyDir Volumes:
- Gehen bei Pod-Neustart verloren
- Können nicht gesichert werden
- Sind nicht hochverfügbar
Wie hilft die ayedo SDP?¶
Kyverno warnt vor emptyDir-Nutzung (Audit-Mode) oder blockiert diese (Enforce-Mode, konfigurierbar).
Lösung¶
Verwenden Sie PersistentVolumeClaims:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myapp-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: longhorn
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: myapp
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: myapp-data
emptyDir erlaubt für:
- Temporäre Caches
- Scratch Space
- Data-sharing zwischen Containern im selben Pod
- NICHT für persistente Daten!
Weitere Informationen:
Job TTL (Time to Live)¶
Compliance: Kostenoptimierung, Resource Management
Zweck
Verhindert, dass abgeschlossene Jobs unbegrenzt im Cluster verbleiben.
Problem¶
Jobs ohne TTL bleiben nach Abschluss im Cluster und:
- Verbrauchen API Server-Ressourcen
- Machen
kubectl get podsunübersichtlich - Stapeln sich über Zeit
Wie hilft die ayedo SDP?¶
Kyverno mutiert Jobs automatisch und fügt ttlSecondsAfterFinished hinzu (falls nicht definiert).
Lösung¶
Automatisch (via Kyverno Mutation):
Jobs erhalten automatisch ein TTL von 3600 Sekunden (1 Stunde).
Manuell konfigurieren:
apiVersion: batch/v1
kind: Job
metadata:
name: data-processing
spec:
ttlSecondsAfterFinished: 3600 # Lösche nach 1 Stunde
template:
spec:
containers:
- name: processor
image: myapp:v1.0.0
restartPolicy: OnFailure
TTL Guidelines
- Short-lived Jobs: 300-600 Sekunden (5-10 Minuten)
- Standard Jobs: 3600 Sekunden (1 Stunde)
- Debug Jobs: 86400 Sekunden (24 Stunden)
- Wichtige Logs: Sichern Sie Logs vor Löschung!
Weitere Informationen:
Default Pod Topology Spread¶
Compliance: ISO 27001 Annex A 8.6 (High Availability)
Zweck
Verteilt Pods automatisch über Nodes für bessere Availability.
Problem¶
Ohne Topology Spread Constraints können alle Replicas auf demselben Node landen, was zu Single Point of Failure führt.
Wie hilft die ayedo SDP?¶
Kyverno fügt automatisch Default Topology Spread Constraints hinzu, die Pods gleichmäßig über Nodes verteilen.
Automatisch angewendet¶
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: myapp
Erklärung:
maxSkew: 1: Maximal 1 Pod Unterschied zwischen NodestopologyKey: kubernetes.io/hostname: Verteile über NodeswhenUnsatisfiable: ScheduleAnyway: Soft Constraint (bevorzugt, aber nicht erzwungen)
Manuell überschreiben¶
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone # Verteile über Zones
whenUnsatisfiable: DoNotSchedule # Hard Constraint
labelSelector:
matchLabels:
app: myapp
Weitere Informationen:
Policy Violations überprüfen¶
Via Grafana Dashboard¶
Das Policy as Code Dashboard zeigt alle Policy Violations.
Via kubectl¶
# Alle Policy Reports anzeigen
kubectl get policyreport -A
# Details zu einem Report
kubectl describe policyreport -n myapp
# Nur Failures
kubectl get policyreport -A -o json | jq '.items[] | select(.summary.fail > 0)'
Via Kyverno CLI¶
# Policy lokal testen
kyverno apply policy.yaml --resource deployment.yaml
# Cluster-wide Scan
kyverno scan --policy-report
Policy Exceptions¶
In begründeten Fällen können Ausnahmen gewährt werden:
apiVersion: kyverno.io/v2
kind: PolicyException
metadata:
name: allow-root-for-special-app
namespace: special
spec:
exceptions:
- policyName: disallow-privileged-containers
ruleNames:
- validate-runAsNonRoot
match:
any:
- resources:
kinds:
- Pod
namespaces:
- special
names:
- special-app-*
Exceptions müssen dokumentiert werden!
- Grund: Warum ist die Ausnahme nötig?
- Risk Assessment: Welches Risiko wird akzeptiert?
- Review Date: Wann wird die Ausnahme überprüft?
- Approval: Wer hat die Ausnahme genehmigt?
Support¶
Bei Fragen zu Guardrails:
- E-Mail: support@ayedo.de
- Discord: ayedo Discord