El stack de arquitectura de una startup tecnológica de una sola persona
(anthonynsimon.com)-
Explicación de la arquitectura de un desarrollador solitario que opera un SaaS sin estrés y a un ritmo tranquilo
-
Armó una infraestructura para operar varios proyectos al mismo tiempo
-
Explica tomando como referencia PanelBear, un SaaS que creó recientemente
→ empezó con SQLite + Django en el VPS más pequeño
→ tras 6 meses de iteración, pasó a Django monolítico + Postgres + ClickHouse (analítica) + Redis (caché) + Celery (tareas programadas) sobre EKS
→ casi todo está automatizado: autoscaling, ingress, certificados TLS, failover, logging, monitoreo, etc.
→ como usa esta configuración en varios proyectos, puede reducir costos e iniciar experimentos realmente fácil
→ casi no le dedica tiempo a administrar la infraestructura (0 a 2 horas al mes)
→ usa la mayor parte del tiempo en desarrollar funciones, dar soporte a clientes y hacer crecer el negocio -
Usa Kubernetes en AWS, pero no es obligatorio. Aun así, cree que puede operarlo de forma estable porque ya le es familiar.
→ lo aprendió usando esta herramienta durante años en un equipo paciente (que toleraba y ayudaba a contener los errores)
→ "Kubernetes hace complejas las cosas simples, pero también puede simplificar las cosas complejas" -
DNS, SSL y balanceo de carga automáticos
→ todo el tráfico se envía desde CloudFlare Proxy a AWS L4 NLB (Network Load Balancer)
→ cuando entra una request, el LB la reenvía a uno de los nodos del clúster de k8s
→ estos nodos están en subredes privadas distribuidas en varias AZ (Availability Zone)
→ ingress-nginx (clúster de Nginx) se encarga de que k8s identifique a qué servicio debe ir la solicitud
→ antes de reenviar el tráfico, nginx aplica reglas de rate limiting y traffic shaping
→ en el caso de PanelBear, el contenedor de la app es Django servido con Uvicorn
→ hay algunos archivos de configuración entre Terraform y K8s, compartidos por la mayoría de los proyectos
→ desplegar un proyecto nuevo requiere unas 20 líneas de configuración de ingress -
Rollout y rollback automáticos
→ cada vez que hace push a master, se ejecuta un pipeline de CI con GitHub Actions
→ inspecciona la base de código y crea un entorno completo con Docker-Compose para pruebas end-to-end
→ si las verificaciones pasan, construye una nueva imagen de Docker y la sube a ECR (el Docker Registry de AWS)
→ un componente de flux en el clúster de k8s ( https://fluxcd.io/ ) sincroniza automáticamente la imagen dentro del clúster
→ Flux ejecuta automáticamente un incremental rollout -
Horizontal Autoscaling
→ autoscaling basado en uso de CPU/memoria
→ si hay demasiados Pods por nodo en el clúster, crea automáticamente más servidores para aumentar la capacidad y reducir la carga; cuando no hay trabajo, reduce la escala
→ en el caso de PanelBear, ajusta automáticamente las réplicas de los Pods de la API de 2 a 8 -
Caché de static assets usando CDN
→ configura CloudFlare en el DNS para manejar todas las solicitudes y también mitigar DDoS
→ para servir archivos estáticos usa Whitenoise ( https://github.com/evansd/whitenoise ), así que no necesita subir archivos a Nginx/Cloudfront/S3
→ para algunos sitios web estáticos como la landing de PanelBear, usa NextJS -
Caché de datos de la aplicación
→ en algunas partes usa la caché LRU en memoria que ofrece Python
→ la mayoría de los endpoints usan Redis dentro del clúster -
Rate limiting por endpoint
→ nginx-ingress aplica rate limiting global, pero a veces necesita límites específicos por endpoint/método
→ usa la librería Django Ratelimit para declarar límites por vista de Django
→ está configurado para rastrear a los clientes que hacen requests a cada endpoint usando Redis como backend (hash basado en clave de cliente, no en IP) -
Administración de la app
→ el Admin Panel de Django ya ofrece funciones para ver y editar datos
→ agregó funciones como bloquear acceso a cuentas sospechosas / enviar emails de aviso / procesar solicitudes de eliminación de cuenta (al principio hace soft delete y luego borrado completo dentro de 72 horas) -
Ejecución de tareas programadas
→ en un SaaS se ejecutan varias tareas programadas: reportes diarios para clientes, cálculo de estadísticas de uso cada 15 minutos, emails de métricas para empleados, etc.
→ ejecuta varios workers de Celery y el scheduler Celery beat dentro del clúster; usa Redis como task queue
→ usa HealthChecks.io para recibir avisos por SMS/Slack/Email cuando una tarea programada no se ejecuta correctamente -
Configuración de la app
→ toda la configuración usa variables de entorno. Es algo antiguo, pero portable y bien soportado -
Manejo de secretos
→ usa kubeseal. Cifra los Secrets con criptografía asimétrica. Solo los clústeres con permisos para acceder a la clave de descifrado pueden desencriptarlos
→ para proteger los Secrets dentro del clúster usa claves de cifrado de AWS KMS -
Datos relacionales: Postgres
→ para experimentos opera un contenedor vanilla de Postgres dentro del clúster y hace respaldos diarios a S3 con un K8s Cronjob
→ cuando el proyecto crece, mueve la base de datos fuera del clúster hacia RDS, y deja que AWS se encargue de respaldos cifrados y actualizaciones de seguridad
→ para reforzar la seguridad, la DB de AWS solo es accesible desde la red privada -
Datos columnares: ClickHouse
→ usa ClickHouse para almacenar y consultar en tiempo real de forma eficiente los datos analíticos de PanelBear
→ es una excelente base de datos columnar, extremadamente rápida y, si la estructura está bien diseñada, logra una alta tasa de compresión (menos almacenamiento = más ingresos)
→ hace self-hosting de una instancia de ClickHouse dentro del clúster de K8s
→ creó un CronJob para respaldar periódicamente los datos columnares en S3
→ tiene algunos scripts para respaldar y restaurar manualmente los datos desde S3 en caso de desastre -
Descubrimiento de servicios basado en DNS
→ K8s administra automáticamente los registros DNS dentro del clúster para enrutar el tráfico al servicio correspondiente
→ incluso durante el autoscaling, sincroniza automáticamente los registros DNS para conectar con Pods saludables -
Infraestructura controlada por versión
→ administra Docker, Terraform y los manifests de K8s en un único repositorio (infra mono-repo)
→ permite crear y eliminar infraestructura con comandos simples, y es reproducible mediante control de versiones -
Terraform para recursos cloud
→ la mayoría de los recursos en la nube se administran con Terraform
→ esto permite documentar y rastrear los recursos y la configuración de la infraestructura -
K8s manifest para desplegar apps
→ los K8s manifests están escritos en archivos YAML dentro del mono-repo de infraestructura
→ está dividido en dos carpetas:clusteryapps
→clusterincluye configuraciones relacionadas con servicios de todo el clúster, como nginx-ingress, secrets cifrados y scrapers de Prometheus
→appsguarda la información de un namespace por proyecto -
Suscripciones y pagos
→ procesa todos los pagos con Stripe Checkout
→ como no necesita involucrarse con la información de pago en sí, puede enfocarse en el producto
→ basta con crear una sesión del cliente, redirigir a la página de Stripe y recibir el resultado por WebHook -
Logging
→ sin usar un agente de logging, basta con imprimir logs en stdout para que k8s los recopile y también haga rotación automáticamente
→ podría enviarlos a Elasticsearch/Kibana mediante FluentBit, etc., pero todavía no lo hace para mantener todo simple
→ para inspeccionar logs usa la herramienta CLIstern -
Monitoreo y alertas
→ al principio hizo self-hosting de Prometheus / Grafana, pero cuando había problemas en el clúster también se caía el sistema de alertas, lo que era inconveniente
→ por eso cambió a New Relic
→ todos los servicios tienen una integración con Prometheus que recopila métricas automáticamente y puede enviarlas a Datadog, New Relic, Grafana Cloud, etc.; para migrar a New Relic bastó con usar la imagen Docker de Prometheus que ellos ofrecen -
Seguimiento de errores
→ recopila errores de la aplicación usando Sentry
→ centraliza todas las alertas —downtime, fallas de cron jobs, alertas de seguridad, regresiones de rendimiento, excepciones de la aplicación, etc.— usando el canal#alertsde Slack -
Profiling y otras cosas útiles
→ cuando necesita análisis profundo usa herramientas comocProfileosnakeviz
→ en la máquina local usa Django Debug Toolbar
11 comentarios
Gracias
¿Hay mucha diferencia entre las funciones de Sentry y New Relic?
Pensaba que hacían cosas parecidas, pero todavía no he usado ninguna.
Oh, en nuestra empresa también estamos evaluando adoptar k8s, y es un artículo bastante bueno incluso aunque no se trate de una startup de una sola persona.
Gracias por el buen artículo. Me voy muy inspirado.
Es un buen artículo incluso si no se trata específicamente de una startup tecnológica de una sola persona.
Un typo menor,,
→ usando Sentry para recopilar los errores de la aplicación
=> creo que debería decir “recopilar”
Gracias. ¡Ya lo corregí~!
Espero que en nuestro país también aparezcan más desarrolladores independientes o equipos pequeños que ganen dinero con sus propios servicios.
Ojalá que GeekNews crezca como un espacio donde esos servicios puedan darse a conocer y recibir retroalimentación saludable.
Reflexión tras 6 meses operando una startup SaaS unipersonal https://es.news.hada.io/topic?id=2415
Operar una startup de software con el mínimo esfuerzo https://es.news.hada.io/topic?id=1534
Informe sobre el estado del SaaS independiente en 2021 [diapositivas de 63 páginas] https://es.news.hada.io/topic?id=3728
La historia de haber intentado crear una empresa de 1 billón de wones y fracasar https://es.news.hada.io/topic?id=2
Vendo cebollas en internet https://es.news.hada.io/topic?id=3
Lo que aprendió un CEO de startup ex Samsung tras perder 1.200 millones de wones https://es.news.hada.io/topic?id=3015
Operar una startup por 6 dólares al año https://es.news.hada.io/topic?id=1621
Gracias
Estoy de acuerdo. Gracias :)
👍