Veröffentlicht am

Kubernetes Schwachstellen finden und patchen

Teilen:
Authors

Kubernetes Vulnerability Management: Automatisierte Schwachstellenerkennung und Patching

TL;DR

  • Image-Scanning in der CI/CD-Pipeline mit Trivy oder Grype erkennt bekannte CVEs, bevor Container in den Cluster gelangen. Ein Quality Gate blockiert Images mit Critical-Schwachstellen.
  • Admission Controller (Kyverno, OPA Gatekeeper) verhindern das Deployment von ungescannten oder verwundbaren Images -- die letzte Verteidigungslinie vor dem Cluster.
  • Runtime-Scanning mit Trivy Operator prueft bereits laufende Workloads kontinuierlich gegen aktuelle CVE-Datenbanken und meldet neue Schwachstellen in bestehenden Deployments.
  • Patch-SLAs definieren klare Zeitfenster: Critical innerhalb 24 Stunden, High innerhalb 7 Tagen, Medium innerhalb 30 Tagen.
  • Automatisiertes Node-Patching mit kured (Kubernetes Reboot Daemon) fuehrt OS-Updates ohne manuelle Intervention durch.

Warum Vulnerability Management in Kubernetes komplex ist

In der Welt vor Containern war Patching ueberschaubar: Paketmanager aktualisieren, Server neustarten, fertig. In Kubernetes gibt es fuenf verschiedene Ebenen, die Schwachstellen enthalten koennen:

  • Container Images: Jedes Image enthaelt ein OS, Libraries und die Applikation. Jede Schicht kann CVEs enthalten.
  • Kubernetes selbst: Die Control Plane (API Server, etcd, Controller Manager, Scheduler) braucht regelmaessige Updates.
  • Node OS: Das Betriebssystem der Worker Nodes (Ubuntu, RHEL, Flatcar) hat eigene Sicherheitsluecken.
  • Cluster-Addons: Ingress Controller, CNI Plugins, Service Meshes und Monitoring-Tools sind eigene Angriffsvektoren.
  • Konfiguration: Fehlkonfigurationen (privilegierte Container, fehlende Network Policies) sind keine CVEs, aber genauso gefaehrlich.

Ein mittelstaendisches Unternehmen mit 200 Deployments und 50 verschiedenen Base Images hat leicht 1.000+ bekannte CVEs im Cluster -- die meisten davon irrelevant, einige kritisch. Ohne System ertrinkt das Team in Rauschen.

Grundlagen der Kubernetes-Security: Kubernetes Security Hardening.

Image-Scanning in der CI/CD-Pipeline

Trivy: Der Industriestandard

# Installation
brew install trivy

# Image scannen
trivy image registry.example.com/order-service:v2.3.1

# Nur Critical und High anzeigen
trivy image --severity CRITICAL,HIGH registry.example.com/order-service:v2.3.1

# Als JSON fuer Weiterverarbeitung
trivy image --format json --output results.json registry.example.com/order-service:v2.3.1

# SBOM generieren (Software Bill of Materials)
trivy image --format spdx-json --output sbom.json registry.example.com/order-service:v2.3.1

CI/CD-Integration (GitHub Actions)

# .github/workflows/security-scan.yaml
name: Security Scan
on: [push]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build Image
        run: docker build -t my-app:${{ github.sha }} .

      - name: Trivy Scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: "my-app:${{ github.sha }}"
          format: "table"
          exit-code: "1"
          severity: "CRITICAL,HIGH"
          ignore-unfixed: true

      - name: Upload SBOM
        if: always()
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: "my-app:${{ github.sha }}"
          format: "spdx-json"
          output: "sbom.json"

      - name: Upload Scan Results
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: "trivy-results.sarif"

Grype als Alternative

# Installation
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin

# Image scannen
grype registry.example.com/order-service:v2.3.1

# Mit Schwellwert (Exit Code 1 bei Critical)
grype registry.example.com/order-service:v2.3.1 --fail-on critical
FeatureTrivyGrype
MaintainerAqua SecurityAnchore
Scan-GeschwindigkeitSchnell (lokaler Cache)Schnell
OS-PaketeJaJa
Language PackagesJa (Go, Java, Node, Python, Rust)Ja
IaC-ScanningJa (Terraform, Helm, K8s Manifests)Nein
Kubernetes-OperatorJa (Trivy Operator)Nein
SBOM-SupportSPDX, CycloneDXSPDX, CycloneDX
LizenzApache 2.0Apache 2.0

Fuer einen detaillierten Tool-Vergleich: Kubernetes Security Scanning Tools.

Runtime-Scanning mit Trivy Operator

CI/CD-Scanning reicht nicht aus. Neue CVEs werden taeglich veroeffentlicht -- ein Image, das gestern sauber war, kann heute verwundbar sein. Der Trivy Operator scannt laufende Workloads kontinuierlich.

# Installation via Helm
helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm install trivy-operator aqua/trivy-operator \
  --namespace trivy-system \
  --create-namespace \
  --set trivy.severity="CRITICAL,HIGH,MEDIUM" \
  --set operator.scanJobsConcurrentLimit=3 \
  --set operator.scanJobsRetryDelay=30s

Der Operator erstellt VulnerabilityReport-Objekte fuer jeden gescannten Workload:

# Alle Vulnerability Reports anzeigen
kubectl get vulnerabilityreports -A

# Details fuer einen bestimmten Workload
kubectl get vulnerabilityreport -n production \
  -l trivy-operator.resource.name=order-service \
  -o jsonpath='{range .items[0].report.vulnerabilities[*]}{.severity}{"\t"}{.vulnerabilityID}{"\t"}{.title}{"\n"}{end}'
# Beispiel VulnerabilityReport (gekuerzt)
apiVersion: aquasecurity.github.io/v1alpha1
kind: VulnerabilityReport
metadata:
  name: replicaset-order-service-7d8f9b-order-service
  namespace: production
  labels:
    trivy-operator.resource.name: order-service
report:
  summary:
    criticalCount: 0
    highCount: 2
    mediumCount: 8
    lowCount: 15
  vulnerabilities:
    - vulnerabilityID: CVE-2024-38816
      severity: HIGH
      resource: spring-webmvc
      installedVersion: 6.1.12
      fixedVersion: 6.1.13
      title: "Path traversal in Spring Framework"

Admission Control: Verwundbare Images blockieren

Die letzte Verteidigungslinie: Ein Admission Controller, der Images ohne Scan-Ergebnis oder mit kritischen CVEs ablehnt.

Kyverno Policy

# Block images with critical vulnerabilities
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: block-vulnerable-images
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: check-vulnerability-report
      match:
        any:
          - resources:
              kinds:
                - Pod
      preconditions:
        all:
          - key: "{{ request.operation }}"
            operator: In
            value: ["CREATE", "UPDATE"]
      validate:
        message: >-
          Image {{ element.image }} hat kritische Schwachstellen.
          Bitte Base Image aktualisieren und erneut scannen.
        deny:
          conditions:
            any:
              - key: "{{ vulnerabilityReports[].report.summary.criticalCount }}"
                operator: GreaterThan
                value: 0

Alternativ laesst sich die gleiche Logik mit OPA Gatekeeper und Rego-Policies umsetzen. Kyverno ist fuer Teams ohne Rego-Erfahrung der einfachere Einstieg.

Mehr zu Runtime-Security: Kubernetes Runtime Security.

CVE-Tracking und Priorisierung

Nicht jede CVE erfordert sofortiges Handeln. Ein strukturierter Priorisierungs-Prozess verhindert, dass das Team im Rauschen untergeht.

Priorisierungs-Matrix

SeverityCVSS ScoreSLAAktion
Critical9.0 - 10.024 StundenSofortiger Hotfix, Eskalation an Security
High7.0 - 8.97 TageNaechster Sprint, Fix priorisieren
Medium4.0 - 6.930 TageNaechstes regulaeres Update-Fenster
Low0.1 - 3.990 TageNaechstes Base-Image-Update

Kontextuelle Bewertung

CVSS allein reicht nicht. Zusaetzliche Faktoren:

  • Erreichbarkeit: Ist der verwundbare Service aus dem Internet erreichbar? Ein interner Batch-Job hat ein niedrigeres Risiko.
  • Fix verfuegbar: CVEs ohne Fix (unfixed) erfordern Workarounds statt Patches.
  • Exploit bekannt: Hat die CVE einen bekannten Exploit in freier Wildbahn (EPSS Score)?
  • Betroffene Funktion: Nutzt die Applikation die verwundbare Library-Funktion ueberhaupt?
# Trivy mit EPSS-Score (Exploit Prediction)
trivy image --scanners vuln --format json registry.example.com/order-service:v2.3.1 | \
  jq '.Results[].Vulnerabilities[] | select(.EPSS.Score > 0.5) | {id: .VulnerabilityID, severity: .Severity, epss: .EPSS.Score}'

Automatisierte Patch-Strategien

Base-Image-Updates automatisieren

# Renovate Bot Konfiguration fuer Container Images
# renovate.json
{
  "extends": ["config:base"],
  "kubernetes": {
    "fileMatch": ["k8s/.+\\.yaml$"]
  },
  "packageRules": [
    {
      "matchDatasources": ["docker"],
      "matchUpdateTypes": ["patch"],
      "automerge": true,
      "labels": ["security-patch"]
    },
    {
      "matchDatasources": ["docker"],
      "matchUpdateTypes": ["minor"],
      "automerge": false,
      "labels": ["dependency-update"]
    }
  ]
}

Node-OS-Patching mit kured

# kured installieren (Kubernetes Reboot Daemon)
helm repo add kubereboot https://kubereboot.github.io/charts
helm install kured kubereboot/kured \
  --namespace kube-system \
  --set configuration.rebootSentinelFile="/var/run/reboot-required" \
  --set configuration.period="1h" \
  --set configuration.rebootDays="mon,tue,wed,thu,fri" \
  --set configuration.startTime="02:00" \
  --set configuration.endTime="06:00" \
  --set configuration.timeZone="Europe/Berlin" \
  --set configuration.concurrency=1

Wie kured funktioniert: Unattended-Upgrades installieren Sicherheitsupdates und erstellen /var/run/reboot-required. kured erkennt die Sentinel-Datei, drainet den Node, rebootet ihn und gibt ihn per uncordon wieder frei -- ein Node nach dem anderen.

Kubernetes-Version-Upgrades

# Aktuelle Version pruefen
kubectl version --short

# Deprecated APIs erkennen vor dem Upgrade
kubectl get --raw /metrics | grep apiserver_requested_deprecated_apis

Der Upgrade-Plan: Zuerst Control Plane upgraden, dann Addons aktualisieren (CoreDNS, kube-proxy, CNI), anschliessend Worker Nodes per Rolling Update erneuern.

Fuer Security-Scanning-Strategien im Detail: Kubernetes Security Scanning.

Vulnerability Dashboard

Ein zentrales Dashboard gibt dem Security-Team den Ueberblick:

# PrometheusRule fuer Vulnerability-Alerts
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: vulnerability-alerts
  namespace: monitoring
spec:
  groups:
    - name: vulnerability.rules
      rules:
        - alert: CriticalVulnerabilityFound
          expr: |
            sum(trivy_image_vulnerabilities{severity="Critical"}) by (image_repository) > 0
          for: 15m
          labels:
            severity: critical
          annotations:
            summary: "Kritische Schwachstelle in {{ $labels.image_repository }}"
            description: "{{ $value }} kritische CVEs gefunden. Sofortiges Patching erforderlich."
        - alert: HighVulnerabilityUnpatched
          expr: |
            sum(trivy_image_vulnerabilities{severity="High"}) by (namespace) > 5
          for: 7d
          labels:
            severity: warning
          annotations:
            summary: "Namespace {{ $labels.namespace }}: Mehr als 5 ungepatcht High CVEs seit 7 Tagen"
# Grafana-PromQL fuer Dashboard-Panels

# Gesamt-CVEs pro Severity
sum(trivy_image_vulnerabilities{}) by (severity)

# CVEs pro Namespace
sum(trivy_image_vulnerabilities{severity=~"Critical|High"}) by (namespace)

# Images mit meisten CVEs
topk(10, sum(trivy_image_vulnerabilities{}) by (image_repository))

# Trend: Neue CVEs pro Woche
increase(trivy_image_vulnerabilities{}[7d])

Best Practices

  1. Shift Left: Scanning so frueh wie moeglich -- im Dockerfile, in der IDE, in der CI/CD-Pipeline. Je spaeter ein Problem erkannt wird, desto teurer der Fix.

  2. Minimale Base Images: distroless oder alpine statt ubuntu:latest. Weniger Pakete bedeuten weniger Angriffsflaeche und weniger CVEs.

# Vergleich: Anzahl CVEs
trivy image ubuntu:24.04        # ~50 CVEs
trivy image alpine:3.20         # ~5 CVEs
trivy image gcr.io/distroless/static-debian12  # ~0 CVEs
  1. Ignore-Listen pflegen: Nicht jede CVE ist relevant. False Positives und akzeptierte Risiken dokumentieren:
# .trivyignore
# CVE-2024-12345: Betrifft nur Windows, wir nutzen Linux
CVE-2024-12345
# CVE-2024-67890: Fix nicht verfuegbar, Workaround implementiert
CVE-2024-67890
  1. SBOM generieren und speichern: Software Bill of Materials fuer jedes produktive Image archivieren. Bei neuen CVEs laesst sich sofort pruefen, welche Deployments betroffen sind.

  2. Automatisierung vor Perfektion: Ein automatisierter Prozess, der 80% der Patches abdeckt, ist besser als ein manueller Prozess, der theoretisch 100% abdeckt aber in der Praxis an Kapazitaet scheitert.

Fuer die umfassende Security-Posture: Kubernetes Security Posture.

Verwandte Artikel


Wenn ihr ein systematisches Vulnerability Management fuer eure Kubernetes-Cluster aufbauen wollt, meldet euch unter /kontakt -- wir helfen von der Tool-Auswahl bis zur Implementierung der Patch-Prozesse.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen