Veröffentlicht am

Kubernetes für Medien: Streaming, CMS und Transcoding

Teilen:
Authors

Kubernetes fuer Medienunternehmen: Streaming, CMS und Content-Delivery

TL;DR

  • Video-Transcoding-Pipelines mit FFmpeg als Kubernetes Jobs skalieren automatisch und verarbeiten Hunderte Videos parallel.
  • Streaming-Plattformen (HLS/DASH) profitieren von HPA-gesteuertem Autoscaling bei Live-Events mit Millionen gleichzeitiger Zuschauer.
  • Headless-CMS-Systeme auf Kubernetes liefern Content ueber APIs an Web, App und Smart-TV -- ohne Downtime bei Deployments.
  • GPU-Transcoding mit NVIDIA-Nodes reduziert die Verarbeitungszeit um den Faktor 5-10 gegenueber CPU-only. CDN-Integration wird ueber Ingress und ExternalDNS automatisiert.

Ausgangslage: Warum Medienunternehmen Kubernetes brauchen

Die Medienbranche ist gepraegt von extremen Lastschwankungen. Ein viraler Clip, ein Live-Sportevent oder eine Breaking-News-Meldung kann den Traffic innerhalb von Minuten verzehnfachen. Gleichzeitig laufen im Hintergrund rechenintensive Prozesse: Video-Transcoding, Bildverarbeitung, automatische Untertitelung.

Klassische VM-basierte Infrastrukturen koennen dieses Lastprofil nicht wirtschaftlich abbilden. Entweder wird dauerhaft fuer Peak-Last provisioniert (teuer) oder die Plattform bricht bei Spitzen zusammen (inakzeptabel).

AspektVM-basiertKubernetes-basiert
Skalierung bei Live-Eventmanuell, Stunden Vorlaufautomatisch, unter 2 Min (HPA)
Transcoding-Durchsatzfest, an Hardware gebundenelastisch, Jobs skalieren mit Bedarf
CMS-DeploymentWartungsfenster, DowntimeRolling Update, Zero Downtime
Kosten bei Niedriglast100 % der Peak-Kosten20-30 % durch Autoscaling

Video-Transcoding-Pipeline mit FFmpeg

Transcoding ist der ressourcenintensivste Prozess in der Medienproduktion. Jedes hochgeladene Video muss in mehrere Formate und Aufloesungen konvertiert werden (1080p, 720p, 480p, verschiedene Codecs). Kubernetes Jobs sind dafuer ideal: Sie starten, verarbeiten und beenden sich automatisch.

Transcoding Job

apiVersion: batch/v1
kind: Job
metadata:
  name: transcode-video-8472
  namespace: transcoding
  labels:
    pipeline: video-ingest
    priority: standard
spec:
  backoffLimit: 2
  activeDeadlineSeconds: 7200
  template:
    spec:
      restartPolicy: Never
      nodeSelector:
        workload-type: transcoding
      containers:
      - name: ffmpeg
        image: registry.internal/media/ffmpeg-worker:6.1.2
        command: ["/bin/sh", "-c"]
        args:
        - |
          ffmpeg -i /input/source.mp4 \
            -map 0:v -map 0:a \
            -c:v libx264 -preset medium \
            -vf "scale=1920:1080" -b:v 5000k \
            /output/1080p.mp4 && \
          ffmpeg -i /input/source.mp4 \
            -map 0:v -map 0:a \
            -c:v libx264 -preset medium \
            -vf "scale=1280:720" -b:v 2500k \
            /output/720p.mp4 && \
          ffmpeg -i /input/source.mp4 \
            -map 0:v -map 0:a \
            -c:v libx264 -preset fast \
            -vf "scale=854:480" -b:v 1200k \
            /output/480p.mp4
        resources:
          requests:
            cpu: "4"
            memory: "8Gi"
          limits:
            cpu: "8"
            memory: "16Gi"
        volumeMounts:
        - name: input
          mountPath: /input
        - name: output
          mountPath: /output
      volumes:
      - name: input
        persistentVolumeClaim:
          claimName: video-ingest-pvc
      - name: output
        persistentVolumeClaim:
          claimName: video-output-pvc

GPU-beschleunigtes Transcoding

Fuer grosse Medienhaeuser, die taeglich Hunderte Videos verarbeiten, lohnt sich GPU-Transcoding mit NVIDIA NVENC. Die Verarbeitungszeit sinkt um den Faktor 5-10. Mehr zum Aufbau von GPU-Clustern unter GPU-Cluster mit Kubernetes.

apiVersion: batch/v1
kind: Job
metadata:
  name: gpu-transcode-8473
  namespace: transcoding
spec:
  template:
    spec:
      restartPolicy: Never
      nodeSelector:
        gpu-type: nvidia-t4
      tolerations:
      - key: "nvidia.com/gpu"
        operator: "Exists"
        effect: "NoSchedule"
      containers:
      - name: ffmpeg-gpu
        image: registry.internal/media/ffmpeg-nvidia:6.1.2-cuda12
        command: ["/bin/sh", "-c"]
        args:
        - |
          ffmpeg -hwaccel cuda -hwaccel_output_format cuda \
            -i /input/source.mp4 \
            -c:v h264_nvenc -preset p4 -tune hq \
            -vf "scale_cuda=1920:1080" -b:v 5000k \
            /output/1080p.mp4
        resources:
          requests:
            cpu: "2"
            memory: "4Gi"
            nvidia.com/gpu: "1"
          limits:
            cpu: "4"
            memory: "8Gi"
            nvidia.com/gpu: "1"
        volumeMounts:
        - name: input
          mountPath: /input
        - name: output
          mountPath: /output
      volumes:
      - name: input
        persistentVolumeClaim:
          claimName: video-ingest-pvc
      - name: output
        persistentVolumeClaim:
          claimName: video-output-pvc

Streaming-Plattform: HLS und DASH

Fuer Live-Streaming und Video-on-Demand werden Inhalte als HLS- oder DASH-Segmente ausgeliefert. Die Origin-Server laufen auf Kubernetes und skalieren per HPA basierend auf der Anzahl aktiver Streams. Details zum Autoscaling unter Kubernetes HPA: Horizontales Pod Autoscaling.

Origin Server Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: stream-origin
  namespace: streaming
  labels:
    app: stream-origin
    tier: origin
spec:
  replicas: 5
  selector:
    matchLabels:
      app: stream-origin
  template:
    metadata:
      labels:
        app: stream-origin
    spec:
      containers:
      - name: nginx-rtmp
        image: registry.internal/media/nginx-rtmp:1.24.0
        ports:
        - containerPort: 8080
          name: http
        - containerPort: 1935
          name: rtmp
        resources:
          requests:
            cpu: "1"
            memory: "2Gi"
          limits:
            cpu: "4"
            memory: "8Gi"
        volumeMounts:
        - name: stream-cache
          mountPath: /var/cache/stream
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          periodSeconds: 5
      volumes:
      - name: stream-cache
        emptyDir:
          sizeLimit: 20Gi
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: stream-origin-hpa
  namespace: streaming
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: stream-origin
  minReplicas: 5
  maxReplicas: 50
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60
  - type: Pods
    pods:
      metric:
        name: active_streams
      target:
        type: AverageValue
        averageValue: "200"
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
      - type: Pods
        value: 10
        periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300

Das scaleUp-Verhalten ist bewusst aggressiv konfiguriert: Bei einem Live-Event muss die Plattform innerhalb von 30 Sekunden reagieren. Das Herunterskalieren erfolgt konservativ mit 5 Minuten Stabilisierung, um Flapping zu vermeiden. Weitere Deployment-Strategien finden Sie unter Kubernetes Deployment-Strategien.

Headless CMS auf Kubernetes

Moderne Medienunternehmen setzen auf Headless-CMS-Systeme (Strapi, Directus), die Content ueber APIs bereitstellen. Die Ausspielung erfolgt entkoppelt auf verschiedenen Kanaelen: Website, Mobile App, Smart-TV.

CMS Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: headless-cms
  namespace: editorial
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: headless-cms
  template:
    metadata:
      labels:
        app: headless-cms
    spec:
      containers:
      - name: strapi
        image: registry.internal/media/strapi-cms:4.25.0
        ports:
        - containerPort: 1337
        env:
        - name: DATABASE_CLIENT
          value: "postgres"
        - name: DATABASE_HOST
          value: "postgres.editorial.svc.cluster.local"
        - name: DATABASE_USERNAME
          valueFrom:
            secretKeyRef:
              name: cms-db-credentials
              key: username
        - name: DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: cms-db-credentials
              key: password
        resources:
          requests:
            cpu: "500m"
            memory: "1Gi"
          limits:
            cpu: "2"
            memory: "4Gi"
        readinessProbe:
          httpGet:
            path: /_health
            port: 1337
          initialDelaySeconds: 10
          periodSeconds: 5

Die maxUnavailable: 0 Strategie stellt sicher, dass waehrend eines Deployments immer alle Replicas verfuegbar bleiben. Fuer eine Redaktion, die rund um die Uhr Content publiziert, ist Downtime nicht akzeptabel.

CDN-Integration und Content Delivery

Kubernetes dient als Origin -- die eigentliche Auslieferung an Endnutzer erfolgt ueber ein CDN (Cloudflare, Akamai, AWS CloudFront). Die Integration laesst sich ueber ExternalDNS und Ingress automatisieren.

Die wichtigsten Konfigurationspunkte am Ingress:

  • Cache-Header setzen: s-maxage=86400 weist das CDN an, statische Inhalte 24 Stunden zu cachen. Der Origin wird damit nur bei Cache-Misses angefragt.
  • Proxy-Buffering aktivieren: Verhindert, dass langsame Clients die Origin-Pods blockieren.
  • TLS-Terminierung: cert-manager stellt automatisch Zertifikate fuer die Origin-Domain aus.
  • ExternalDNS: Erstellt DNS-Records automatisch basierend auf Ingress-Annotations.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: media-cdn-origin
  namespace: streaming
  annotations:
    nginx.ingress.kubernetes.io/proxy-buffering: "on"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      add_header Cache-Control "public, max-age=3600, s-maxage=86400";
    external-dns.alpha.kubernetes.io/hostname: origin.media.example.com
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - origin.media.example.com
    secretName: media-origin-tls
  rules:
  - host: origin.media.example.com
    http:
      paths:
      - path: /video
        pathType: Prefix
        backend:
          service:
            name: stream-origin
            port:
              number: 8080

Live-Event-Skalierung

Live-Events -- Bundesliga-Streams, Konzert-Uebertragungen, Nachrichtensendungen -- erfordern eine Skalierung, die innerhalb von Sekunden reagiert. Detaillierte Autoscaling-Strategien unter Kubernetes Autoscaling.

Vorbereitung (1 Stunde vor Event):

# Pre-Scale: Origin-Server vorab hochfahren
kubectl scale deployment stream-origin \
  --namespace streaming \
  --replicas=30

# Cache aufwaermen
kubectl exec -n streaming deploy/stream-origin -- \
  /scripts/warm-cache.sh --event-id=bundesliga-2026-02

# Cluster-Autoscaler: Minimum-Nodes erhoehen
kubectl patch nodepool media-standard \
  --type merge \
  -p '{"spec":{"limits":{"cpu":"512"}}}'

Waehrend des Events: Der HPA uebernimmt die Feinsteuerung basierend auf der Metrik active_streams. Bei einem ueberraschenden Lastanstieg (Tor, Breaking News) skaliert der Cluster innerhalb von 60 Sekunden hoch. Nach dem Event skalieren Sie manuell zurueck auf die Baseline (kubectl scale deployment stream-origin --namespace streaming --replicas=5) und raeumen temporaere Event-Ressourcen auf.

Kostenvergleich

PostenKlassisch (pro Jahr)Kubernetes (pro Jahr)
Compute (Peak-Provisioning)180.000 - 400.000 EUR60.000 - 150.000 EUR
Transcoding-Hardware80.000 - 200.000 EUR30.000 - 80.000 EUR
Betrieb (Personal)120.000 - 250.000 EUR80.000 - 180.000 EUR

Die groessten Einsparungen entstehen durch elastisches Scaling: Nachts und ausserhalb von Live-Events faehrt der Cluster auf Minimum-Kapazitaet herunter.

Typische Stolpersteine

  • Storage-Durchsatz unterschaetzt: Video-Workloads erfordern hohen I/O-Durchsatz. Planen Sie lokale NVMe-Disks fuer Transcoding-Nodes ein.
  • Netzwerk-Bandbreite vergessen: Streaming-Origin-Server generieren enorme ausgehende Bandbreite. Pruefen Sie die Netzwerk-Limits Ihres Cloud-Providers.
  • GPU-Nodes dauerhaft laufen lassen: GPU-Instanzen sind teuer. Nutzen Sie Cluster-Autoscaler und Node-Taints, damit GPU-Nodes nur bei Bedarf gestartet werden.

Fazit

Kubernetes ist fuer Medienunternehmen die Plattform, die das zentrale Problem der Branche loest: extreme Lastschwankungen wirtschaftlich abfangen. Die Kombination aus Autoscaling fuer Live-Events, GPU-Jobs fuer Transcoding und stabilen CMS-Deployments ergibt eine Infrastruktur, die sowohl technisch als auch finanziell ueberlegen ist. Der Einstieg gelingt am besten ueber die Transcoding-Pipeline oder das CMS -- zwei klar abgegrenzte Workloads mit schnell messbarem Mehrwert. Wenn Sie Unterstuetzung beim Aufbau Ihrer Medien-Plattform auf Kubernetes brauchen, sprechen Sie uns an unter /kontakt.

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