Despliega tu propia Plataforma de Video Streaming con Transcodificación y CDN Local en Kubernetes
Hoy vamos a llevar Kubernetes a otro nivel montando una plataforma de video streaming con transcodificación automática y un pequeño CDN local. Así, podrás crear tu propio clon de YouTube o Twitch usando tu VPS, mientras aprendes a desplegar los microservicios más demandados: ensamblaremos Nginx para servir vídeos estáticos, FFmpeg en un pod para transcodificar y un backend ligero (Node.js) para gestionar las colas y la subida de archivos.
¿Por qué es útil este proyecto?
- Escalabilidad: Podrás añadir réplicas de tus servicios según aumente tu tráfico.
- Práctica real: Usarás patrones usados por servicios de streaming profesionales.
- Automatización: FFmpeg trabaja en segundo plano generando versiones adaptativas de los vídeos.
- Entrega eficiente: El CDN con Nginx minimiza latencia localmente, ideal para audiencias cercanas.
Arquitectura rápida del sistema
- Usuario sube vídeo al backend (Node.js).
- El backend almacena el vídeo y ordena a FFmpeg que lo transcodifique a varios formatos.
- Los archivos resultantes se sirven mediante Nginx (nuestro mini CDN local).
Ficheros yaml
: Despliegue completo en Kubernetes
1. Namespace del proyecto
apiVersion: v1
kind: Namespace
metadata:
name: videostream
2. Volumen Persistente compartido (vídeos y transcodificados)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: video-pvc
namespace: videostream
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 30Gi
3. Backend para subida de vídeos (Node.js)
apiVersion: apps/v1
kind: Deployment
metadata:
name: video-backend
namespace: videostream
spec:
replicas: 1
selector:
matchLabels:
app: video-backend
template:
metadata:
labels:
app: video-backend
spec:
containers:
- name: node-backend
image: ghcr.io/tuusuario/video-backend:latest
ports:
- containerPort: 3000
volumeMounts:
- name: videodata
mountPath: /data
volumes:
- name: videodata
persistentVolumeClaim:
claimName: video-pvc
---
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: videostream
spec:
selector:
app: video-backend
ports:
- protocol: TCP
port: 80
targetPort: 3000
Este backend acepta uploads, los guarda en /data/input, y comunica vía API con FFmpeg para la transcodificación.
4. Worker FFmpeg: transcodificación automática
apiVersion: apps/v1
kind: Deployment
metadata:
name: transcode-worker
namespace: videostream
spec:
replicas: 1
selector:
matchLabels:
app: transcode-worker
template:
metadata:
labels:
app: transcode-worker
spec:
containers:
- name: ffmpeg-worker
image: jrottenberg/ffmpeg:5-scratch
command: ["/bin/sh"]
args: ["-c", "while true; do node /worker.js; sleep 5; done"]
volumeMounts:
- name: videodata
mountPath: /data
volumes:
- name: videodata
persistentVolumeClaim:
claimName: video-pvc
El script worker.js
monitoriza una carpeta de entrada y ejecuta FFmpeg para crear varias versiones del vídeo (baja/HD), dejando resultados en /data/output
.
5. Nginx (CDN local) para servir los vídeos transcodificados
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-cdn
namespace: videostream
spec:
replicas: 2
selector:
matchLabels:
app: nginx-cdn
template:
metadata:
labels:
app: nginx-cdn
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: videodata
mountPath: /usr/share/nginx/html
subPath: output
volumes:
- name: videodata
persistentVolumeClaim:
claimName: video-pvc
---
apiVersion: v1
kind: Service
metadata:
name: cdn
namespace: videostream
spec:
selector:
app: nginx-cdn
ports:
- protocol: TCP
port: 8080
targetPort: 80
Los vídeos transcodificados estarán disponibles en rutas tipo http://.../video.mp4
o adaptativamente si incluyes HLS.
Extra: Ingreso externo (Nginx Ingress recomendado)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: videostream-ingress
namespace: videostream
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: vstream.tudominio.com
http:
paths:
- pathType: Prefix
path: /api(/|$)(.*)
backend:
service:
name: backend
port:
number: 80
- pathType: Prefix
path: /cdn(/|$)(.*)
backend:
service:
name: cdn
port:
number: 8080
¡A jugar!
- Despliega los
yaml
en un VPS con almacenamiento suficiente. - Compila tu backend y tu worker FFmpeg en imágenes propias (puedes usar Node.js y un Dockerfile sencillo).
- Disfruta subiendo vídeos y viendo cómo se transcodifican y sirven por tu propio miniCDN.
Tips y Troubleshooting
- Básico: Verifica permisos de lectura/escritura en el PVC para evitar errores de acceso.
- Escalado: Para aguantar más tráfico, sube
replicas
solo en el Nginx o en el backend. - Colas: Si crecen los uploads, implementa un sistema de colas en tu backend (ejemplo: Redis y BullMQ).
- Transcodificación: Los pods FFmpeg pueden consumir mucha CPU, no los sobredimensiones; limita recursos en el yaml si ves que colapsan el nodo.
- Vídeos lentos: Usa
kubectl logs
para ver si hay cuellos de botella en la transcodificación o delivery. - HTTPS: Recuerda proteger tu Ingress con TLS (Let’s Encrypt + cert-manager recomendado).
Esta plataforma modular te servirá tanto para pruebas internas, servicios privados de streaming o como base para proyectos mucho más grandes. ¿Te animas? ¡Déjame tus dudas en los comentarios!