Dudas sobre escalado de aplicación web

squ4r3

Buenas, en primer lugar no soy desarrollador profesional, así que es probable que alguna de las suposiciones que hago sean erroneas

Quiero escalar una aplicación web que he desarrollado, pero no tengo ni idea de cómo hacerlo. Digamos que la aplicación es un front al que el usuario accede, introduce unos datos, y eso envía una task a un worker, que la ejecuta. Esta task puede durar poco (5min) o mucho (10h+).

La web en sí consume muy pocos recursos, lo que consume son los workers, ya que ejecutan tareas de ffmpeg (codificar vídeo). Si los workers están idle, consumen poco, si están activos, consumen mucha cpu. Ejecuto 6 porque sé que es todo lo que soporta mi hardware.

Ahora mismo la tengo deployeada con docker en una máquina mía. Tengo varios servicios (servidor web con flask, BBDD, redis, 6 workers).

El caso es que me gustaría poder convertir esto de un proyecto personal a algo más serio, que pudiera utilizar más gente. El problema es que no sé cómo afrontar la variabilidad de demanda que podría tener.

Una situación ideal, creo, sería que el número de workers escalase de forma variable según los usuarios vayan demandando, y que también escalase hacia abajo cuando hubiera workers idle para que los costes no se disparen, obviamente.

Creo que para esto podría utilizarse algo como k8s, pero no sé si es matar moscas a cañonazos y si será tremendamente complicado. Lo que no acabo de entender es si se puede conectar estos tres niveles para que se comuniquen entre ellos: nivel app (cuando un usuario entra y manda una nueva task), nivel contenedor (que la app pueda "pedir" que se cree un contenedor nuevo) y nivel infraestructura (que el contenedor se genere automáticamente en una instancia nueva de EC2 y que se destruya al terminar la tarea).

Nombres de servicios que he mirado:
AWS ECS
AWS Fargate
k8s
Docker Swarm (he leído que el escalado es manual, no se puede automatizar)

Creo que con una combinación de ECS + Fargate podría poner los contenedores de los workers, pero sigo sin saber cómo sabe la aplicación que necesita provisionar más workers.

También he estado mirando Auto Scaling de EC2, pero no sé bien si es lo que busco.

Necesitaría que toda esa infraestructura que se genera cuando hay necesidad de workers, desapareciera si no la hay, para ahorrar costes. Puede que en ocasiones tuviera necesidad de 50 workers a la vez, y en otras ocasiones que necesitase 0.

Muchas gracias

cabron

Si usas amazon como tienes pensado te aviso de que no hay límite en el autoescalado, lo máximo que puedes hacer es que si te pasas de X pasta te mande un aviso para que lo sepas.

Lo digo por que si lo abres al público tienes que tener cuidado por que internet está lleno de bots y gente con ganas de tocar las pelotas y como alguien consiga forzar tu servicio de forma que se dispare el trabajo de tu servidor te puedes encontrar de la noche a la mañana con una factura que te puede dejar tieso.

que sepas que a más de uno le ha pasado, así que no es una riesgo teórico, es algo que ocurre de verdad

2 respuestas
Mushuu

Si tiras por la opcion de AWS como comenta #2 podrías pensar en añadir algun tipo de proteccion como Cloudflare.

1 respuesta
djamb

No se muy bien que estás streameabdo pero ffmpeg usa un montón de recurso, a lo mejor si usas servidores como wowza en local ahorras recursos.
Si me explicas un poco mejor lo que quieres hacer con el streaming te puedo ayudar.

1 respuesta
squ4r3

#2 #3 eso tiene que estar contemplado, claro, en cualquier caso no sería un servicio gratuito así que calcularía costes para que quien lo quiera usar compre créditos o me pague de alguna manera para asumir los gastos de AWS. Hablando a largo plazo, claro, primero lo haría en privado y lo utilizaríamos solo unas personas que lo usamos ya. Pero si, que se quedase un proceso colgando o se ejecuten 173954 contenedores sería un problema

#4 estoy cogiendo un streaming HLS, le aplicó un filtro con ffmpeg y lo envío a un punto rtmp para ser emitido. Miraré wowza, pero no entiendo muy bien como haría para codificar el vídeo gastando menos recursos… wowza por debajo no usa ffmpeg?

1 respuesta
djamb

#5 a ver si lo entiendo, estás cogiendo hls en directo de una fuente de terceros en el servidor, le metes un filtro y lo restreameas en rtmp.
No estoy seguro si vas a poder meterle ese filtro a la imagen con wowza. Se pueden hacer algunas cosas de este tipo:
https://www.wowza.com/docs/how-to-add-graphic-overlays-to-live-streams-with-wowza-transcoder
Wowza no sé si está usando ffmpeg para hacer transcoding, no creo, pero vete a saber.

S

En AWS tienes varias opciones para escalar una app de este tipo:

AWS elastic beanstalk
https://aws.amazon.com/elasticbeanstalk/
Según la demanda en cada momento levanta más o menos instancias de tu worker. Pagas por el numero de instancias activas en cada momento.

AWS Lambda
https://aws.amazon.com/lambda/
Ejecuta trabajos a demanda, es perfecto para tareas cortas. Coste cero mientras no hay trabajos y puede escalar a miles de trabajos en paralelo.

Con ambas soluciones necesitas una cola donde mandar los trabajos:
https://aws.amazon.com/sqs/

Gigi_men

Te planteo por aquí varias opciones que hay desde mi punto de vista y según costes ya decidirás. Mas que nada xq no sabemos que volumetría vas a necesitar y no podemos hacer una estimación de costes. Las opciones que planteo son en AWS ya que es el Cloud que tu mismo has indicado o en BareMetal ya que dices que ya dispones un hardware para esto.

EC2: Aquí podrías generarte AMIs con Packer y a partir de ahí montar un ASG. Eso te da de saque la opción de escalar en función de métricas que definas. Todo esto de la IAC lo puedes hacer con Terraform y así lo tendrías como código y sería muy fácilmente modificable. Por delante del grupo de autoescalado deberás montar un ALB para que balancee la carga. En los grupos de autoescalado puedes poner un máximo y un mínimo de instancas que quieres y así por lo menos el coste de la infra lo tendrás controlado. Aunque AWS donde te pega el susto de verdad es en el tráfico de red.

K8S/K3S: Aquí te irías al paradigma de los contenedores (que comentas que ya lo tienes montado así), de manera que parte del curro ya la tendrás hecha. Al hacerlo en K8S o K3S tendrías que montar un Deployment con un Service por delante. Para el escalado tendrás que montar un HPA (Horizontal Pod Autoscaling). En el caso de que la plataforma que está en K8S/K3S se consuma desde fuera del cluster tendrás que montar un Ingress Gateway o en su defecto montar un NodePort, pero esto último de complicaría un poco la gestión. En este caso una de las principales ventajas que tienes es que las pruebas y los primeros pasos los puedes hacer en el Hardware que ya dispones y en caso de querer migrarlo al Cloud, las definiciones ya las tendrías y sería relativamente sencillo.

Lambdas: Aquí directamente te olvidas de cualquier tipo de escalado ya que es el propio servicio gestionado de AWS el que se encarga de ello. Para poder hacer los despliegues de manera mas sencilla lo suyo sería utilizar Serverless o algo similar que ya te proporciona un API Gateway para dirigir el tráfico. Esta opción no es mi favorita ya que no controlas el volumen del escalado. Por otro lado, si dices que tienes ejecuciones de +10h, puede dispararse mucho el coste.

ECS: En este caso no tengo experiencia con el escalado y no te puedo ayudar ahí. Pero personalmente la gestión de ECS me parece un dolor de cabeza gordo. Únicamente tengo Services desplegados con una única Task y personalmente no me convence como se gestiona. Pero a lo mejor alguien del foro puede iluminarnos.

Esos son los servicios con los que tengo experiencia y puedo dar algo de opinión.

wdaoajw

Esto lo hacía en mi antigua empresa, aunque en nuestro caso era transcodificacion en tiempo real, esto es relativamente más sencillo al ser async.

Ahora mismo, por lo que cuentas, necesitas por un lado un gestor de colas (RabbitMQ o el mismo SQS de AWS). Y por otro tienes varias opciones para el tema de los workers:

EC2 y auto-scaling (creo que sería lo ideal para lo tuyo) o irte ya a K8s, pero esto creo que de momento no sería necesario.

Si quieres pregunta por MP y te cuento un poco más

squ4r3

Bueno, gracias a todos por las respuestas de momento he dado un paso hacia atrás y estoy estudiando si hay alguna forma mejor o más eficiente de hacer el transcoding sin tener que levantar yo toda mi infraestructura.

Estoy pensando utilizar Elastic Transcoder y así quitarme de líos de k8s y colas y escalados. Cuando necesite hacer un stream lo mando a Elastic Transcoder, me da de output los chunks .ts y la playlist .m3u8 y eso lo puedo utilizar desde ffmpeg para enviar a distintos rtmps sin tener que reencodear.

El tema es que en mi aplicación ahora mismo un mismo input de vídeo puede tener varios outputs. Es decir, yo tengo una url http://asdfasdf.com/playlist.m3u8 y quiero, por un lado, meterle un filtro de ffmpeg para añadir mis gráficos por encima, y por otro lado enviarlo a varios servidores rtmp.

Ahora mismo esto lo hago reencodeando cada vez con ffmpeg, lo cual es absurdo porque si quiero enviar el mismo input a 4 outputs estoy gastando 3 veces la cpu a lo tonto. Como es mi infraestructura, pues no me importa, pero quiero montarlo bien.

Así que he pensado coger el input http://asdfasdf.com/playlist.m3u8 , pasarlo a elastic transcode, meterle watermark (Que el propio elastic transcode te deja) outputearlo a un bucket y que mi aplicación pille con ffmpeg de ese bucket y lo reestreamee, sin reencodear, a los distintos servidores rtmp que quiero.

Esto me ahorraria todo el tema de las colas y orquestración de los workers, pero por otro lado no tengo ni idea de si es más caro ni si Elastic transcode permite usar como input una url (me da que no). Tendría que encontrar una forma de pasarlo de http://asdfasdf.com/playlist.m3u8 a un bucket de s3 de forma rápida, y luego usar eso como input en el Elastic Transcode.

Vamos, que le sigo dando vueltas a todo el proceso, y a ver si saco algo en claro.

1 1 respuesta
MTX_Anubis
#10squ4r3:

Elastic transcode permite usar como input una url (me da que no).

Sí te deja. Vamos, por el elastic transcoder imagino que te refieres a MediaConvert si no me equivoco es lo que se recomienda. El precio pues más o menos 1cnt/min por fichero de salida para lo basico (meter watermark añade precio).

Vamos que si tienes un input de 1 video y quieres 5 resoluciones distintas, vas a pagar la duración del video x5.

Así que cuidado que dependiendo de lo que hagas se te pude disparar el precio, si vas a tener un flujo constante pudes meterte una cola reservada por el modico precio de 450$/mes

1 respuesta
squ4r3

#11 había estado viendo tanto MediaConvert como Elastic Transcoder y no me ha terminado de quedar claro las diferencias entre ambos.

Así a primera vista me da la sensación de que media convert es más avanzado y “nuevo” , con más features, pero aún así dejaron Elastic Transcoder, que es más viejo, para los clientes que todavía lo usan?

Es por eso que hoy en día, si empiezas con algo, se recomienda MediaConvert?

En principio para cada vídeo será una resolución solo. Usando un m3u8 como input, poniéndole una watermark y dándome un m3u8 y sus respectivos chunks como output, que luego desde ffmpeg puedo enviar, sin reencodear, a distintos rtmps

1 respuesta
MTX_Anubis

#12 Si entro en Elastic Transcoder me sale este mensaje:

Try the New File-Based Video Processing Option
AWS Elemental MediaConvert is a new file-based video transcoding service that provides a comprehensive suite of advanced transcoding features, with Basic tier rates starting at $0.0075/minute. Read more or try MediaConvert

Si no me equivoco, MediaConvert está integrado dentro de un paquete Elemental que son varios servicios e imagino que estarán mejor integrados entre ellos y tendrán más sinergia.

Tampoco lo he tocado mucho, solo para un proyecto en el que era inviable hacerlo en nuestros propios servers con ffmpeg simplemente por el tiempo que tardamos. Hicimos la prueba en MediaConvert y videos de 1 o 2 horas tardaban menos de 1min en convertirlos, videos más cortos que eran casi todos, en pocos segundos ya estsaban disponibles (además de poder tener 10 colas para paralelizarlos). Hechamos cuentas y solo el precio en servidores y tener que montar todo el tinglado superaba con creces lo que nos gastabamos en MediaConvert xD

1 respuesta
squ4r3

#13 Gracias! A mí también me salió ese mensaje recomendando MediaConvert.

Ya que has estado mirando tema de precios, igual te suena o recuerdas: Como yo voy a hacer streamings en directo, no aprovecharé el encodear más rápido que realtime. Crees que saldrá más caro utilizar MediaConvert para encodear, digamos, 3h de streaming que levantarme un EC2 muy limitado de recursos, meterle ffmpeg y encodear con ffmpeg "a mano", y luego tirar el EC2 una vez acabe el streaming?

En ambos casos, si mi input dura 3h, el output y el tiempo de procesado será 3h, use MediaConvert, ffmpeg ejecutado en ec2 o ffmpeg ejecutado en mi hardware propio

2 respuestas
wdaoajw

#14 si, es más caro el SaS que la EC2 siempre y cuando le estés dando uso

MTX_Anubis

#14 pues eso, calcula que el media convert esas 3 horas van a ser 180 centimos, casi 2€. Por ese precio puedes tener durante 3 horas un pepino de máquina (dentro de EC2 que ni se como rinden ni nada)

Usuarios habituales