La pile d’architecture d’une startup tech en solo
(anthonynsimon.com)-
Présentation de l’architecture d’un développeur solo qui exploite un SaaS lentement, sans stress
-
Il a mis en place une infrastructure permettant d’exploiter plusieurs projets en parallèle
-
Explication basée sur son SaaS récent, PanelBear
→ Démarrage sur le plus petit VPS avec SQLite + Django
→ Après 6 mois d’itérations : monolithe Django sur EKS + Postgres + ClickHouse (analytique) + Redis (cache) + Celery (tâches planifiées)
→ La plupart des éléments sont automatisés : autoscaling, ingress, certificats TLS, failover, logging, monitoring, etc.
→ Comme cette configuration est utilisée sur plusieurs projets, elle permet de réduire les coûts et de lancer des expérimentations très facilement
→ La gestion de l’infrastructure ne prend presque pas de temps (0 à 2 heures par mois)
→ L’essentiel du temps est consacré au développement de fonctionnalités, au support client et à la croissance de l’activité -
Il utilise Kubernetes sur AWS, mais ce n’est pas indispensable. Il estime simplement pouvoir l’exploiter de façon stable parce qu’il le maîtrise bien.
→ Il l’a appris au fil de plusieurs années dans une équipe patiente (capable de supporter les erreurs avec lui)
→ « Kubernetes complique les choses simples, mais peut aussi simplifier les choses complexes » -
DNS, SSL et load balancing automatiques
→ Tout le trafic est envoyé depuis le proxy CloudFlare vers AWS L4 NLB (Network Load Balancer)
→ Lorsqu’une requête arrive, le LB la transmet à l’un des nœuds du cluster k8s
→ Ces nœuds se trouvent dans des sous-réseaux privés répartis sur plusieurs AZ (Availability Zone)
→ C’est ingress-nginx (cluster Nginx) qui détermine à quel service la requête doit être envoyée
→ Nginx applique des règles de rate limiting et de traffic shaping avant de transmettre le trafic
→ Dans le cas de PanelBear, le conteneur applicatif est un Django servi par Uvicorn
→ Quelques fichiers de configuration sont partagés entre Terraform et K8s, ainsi qu’entre la plupart des projets
→ Le déploiement d’un nouveau projet se fait avec une vingtaine de lignes de configuration ingress -
Rollout et rollback automatiques
→ Un pipeline CI est lancé avec GitHub Actions à chaque push sur master
→ Inspection de la base de code et tests E2E dans un environnement complet créé avec Docker-Compose
→ Si tout passe, une nouvelle image Docker est construite puis poussée vers ECR (le registre Docker d’AWS)
→ Un composant flux dans le cluster k8s ( https://fluxcd.io/ ) synchronise automatiquement les images du cluster
→ Flux exécute automatiquement un rollout incrémental -
Horizontal Autoscaling
→ Autoscaling en fonction de l’utilisation CPU/mémoire
→ Si un nœud du cluster héberge trop de pods, davantage de serveurs sont créés automatiquement pour augmenter la capacité du cluster et réduire la charge, puis réduits lorsqu’il n’y a plus d’activité
→ Dans le cas de PanelBear, le nombre de réplicas des pods API est automatiquement ajusté de 2 à 8 -
Mise en cache des assets statiques via un CDN
→ CloudFlare est configuré au niveau DNS pour traiter toutes les requêtes et gérer aussi la protection DDoS
→ Pour servir les fichiers statiques, il utilise Whitenoise ( https://github.com/evansd/whitenoise ), ce qui évite d’avoir à envoyer les fichiers vers Nginx/Cloudfront/S3
→ Pour quelques sites web statiques, comme la landing page de PanelBear, il utilise NextJS -
Cache des données applicatives
→ À certains endroits, il utilise le cache LRU en mémoire fourni par Python
→ La plupart des endpoints utilisent Redis dans le cluster -
Rate limiting par endpoint
→ nginx-ingress applique un rate limiting global, mais il faut parfois définir des limites spécifiques par endpoint ou par méthode
→ La bibliothèque Django Ratelimit permet de déclarer des limites par vue Django
→ Redis est utilisé comme backend pour suivre les clients appelant chaque endpoint (hachage basé sur une clé client, et non sur l’IP) -
Administration de l’application
→ Le panneau d’administration de Django prend en charge nativement les fonctions de consultation et d’édition des données
→ Il y a ajouté des fonctions comme le blocage d’accès aux comptes suspects, l’envoi d’e-mails d’annonce ou le traitement des demandes de suppression de compte (suppression logicielle d’abord, puis suppression complète sous 72 heures) -
Exécution des tâches planifiées
→ Dans un SaaS, de nombreuses tâches planifiées s’exécutent : rapports quotidiens pour les clients, calcul des statistiques d’usage toutes les 15 minutes, e-mails de métriques envoyés à l’équipe, etc.
→ Plusieurs workers Celery et le scheduler Celery beat tournent dans le cluster, avec Redis comme file de tâches
→ Il utilise HealthChecks.io pour être averti par SMS/Slack/e-mail lorsque les tâches planifiées ne s’exécutent pas correctement -
Configuration de l’application
→ Toute la configuration passe par des variables d’environnement. C’est ancien, mais portable et bien pris en charge -
Gestion des secrets
→ Utilisation de kubeseal. Il chiffre les secrets avec de la cryptographie asymétrique. Seuls les clusters disposant des droits d’accès à la clé de déchiffrement peuvent les déchiffrer
→ Pour protéger les secrets dans le cluster, il utilise des clés de chiffrement AWS KMS -
Données relationnelles : Postgres
→ Pour les expérimentations, il exécute un conteneur Postgres vanilla dans le cluster et effectue des sauvegardes quotidiennes vers S3 avec un CronJob K8s
→ Quand un projet grandit, la base de données est déplacée du cluster vers RDS, et AWS prend alors en charge les sauvegardes chiffrées, les mises à jour de sécurité, etc.
→ Pour renforcer la sécurité, les bases de données AWS ne sont accessibles que depuis un réseau privé -
Données en colonnes : ClickHouse
→ Il utilise ClickHouse pour stocker efficacement les données analytiques de PanelBear et les interroger en temps réel
→ C’est une excellente base de données columnar, extrêmement rapide et capable d’offrir un fort taux de compression si la structure est bien conçue (moins de stockage = plus de revenus)
→ L’instance ClickHouse est auto-hébergée dans le cluster K8s
→ Un CronJob sauvegarde périodiquement les données columnar vers S3
→ En cas de sinistre, quelques scripts permettent de sauvegarder et restaurer manuellement les données depuis S3 -
Découverte de services basée sur DNS
→ K8s gère automatiquement les enregistrements DNS dans le cluster pour router le trafic vers le bon service
→ Même pendant l’autoscaling, les enregistrements DNS sont synchronisés automatiquement pour rester connectés aux pods sains -
Infrastructure versionnée
→ Docker, Terraform et les manifests K8s sont gérés dans un dépôt unique (infra mono-repo)
→ L’infrastructure peut être créée ou supprimée avec des commandes simples, et le contrôle de version la rend reproductible -
Terraform pour les ressources cloud
→ La plupart des ressources cloud sont gérées avec Terraform
→ Cela permet de documenter et de suivre les ressources et configurations de l’infrastructure -
Manifests K8s pour le déploiement des apps
→ Les manifests K8s sont écrits dans des fichiers YAML du mono-repo d’infrastructure
→ Le dépôt est séparé en deux dossiers :clusteretapps
→clustercontient les réglages liés aux services communs à tout le cluster, comme nginx-ingress, les secrets chiffrés ou les scrapers Prometheus
→appsstocke les informations de chaque projet dans un namespace dédié -
Abonnements et paiements
→ Tous les paiements sont gérés avec Stripe Checkout
→ Il n’a pas besoin de manipuler lui-même les informations de paiement, ce qui lui permet de se concentrer sur le produit
→ Il suffit de créer une session client, de rediriger vers la page Stripe, puis de recevoir le résultat via webhook -
Logging
→ Sans agent de logging, il suffit d’écrire les logs sur stdout pour que k8s les collecte automatiquement et effectue aussi la rotation
→ Il pourrait les envoyer vers Elasticsearch/Kibana via FluentBit, etc., mais ne le fait pas encore pour rester simple
→ Pour inspecter les logs, il utilise l’outil CLI stern -
Monitoring et alertes
→ Au départ, il auto-hébergeait Prometheus / Grafana, mais lorsqu’un problème de cluster survenait, le système d’alerte tombait lui aussi, ce qui posait problème
→ Il est donc passé à New Relic
→ Tous les services disposent d’une intégration Prometheus capable de collecter automatiquement des métriques et de les envoyer à Datadog, New Relic, Grafana Cloud, etc. La migration vers New Relic s’est donc résumée à utiliser l’image Docker Prometheus fournie par eux -
Suivi des erreurs
→ Il utilise Sentry pour collecter les erreurs applicatives
→ Le canal Slack #alerts centralise toutes les alertes : downtime, échecs de cron jobs, alertes de sécurité, régressions de performance, exceptions applicatives, etc. -
Profiling et autres bons outils
→ Lorsqu’une analyse approfondie est nécessaire, il utilise des outils comme cProfile ou snakeviz
→ Sur sa machine locale, il utilise Django Debug Toolbar
11 commentaires
Merci.
Y a-t-il une grande différence de fonctionnalités entre Sentry et New Relic ?
Je pensais qu’ils faisaient des choses similaires, mais je ne les ai encore jamais utilisés.
Oh, notre entreprise étudie aussi l’adoption de k8s, et c’est un article vraiment intéressant, même pour une startup tech qui n’est pas gérée par une seule personne.
Merci pour ce bon article. Je repars inspiré.
C’est un bon article, même pas seulement pour une startup solo.
Une petite coquille,,
→ Avec Sentry, collecter les erreurs de l’application
=> Je pense qu’il s’agit de « collecte »
Merci. C’est corrigé~ !
J’aimerais qu’il y ait aussi davantage de développeurs solo ou de petites équipes en Corée qui gagnent de l’argent avec leur propre service.
J’espère que GeekNews deviendra un espace où ces services pourront se faire connaître et recevoir des retours constructifs.
Bilan de 6 mois d’exploitation d’une startup SaaS solo https://fr.news.hada.io/topic?id=2415
Gérer une startup logicielle avec un minimum d’effort https://fr.news.hada.io/topic?id=1534
Rapport 2021 sur l’état des SaaS indépendants [slides de 63 pages] https://fr.news.hada.io/topic?id=3728
Récit d’un échec après avoir tenté de bâtir une entreprise valant 1 000 milliards de wons https://fr.news.hada.io/topic?id=2
Je vends des oignons sur Internet https://fr.news.hada.io/topic?id=3
Ce qu’un dirigeant de startup passé par Samsung a compris après avoir perdu 1,2 milliard de wons https://fr.news.hada.io/topic?id=3015
Faire tourner une startup avec 6 $ par an https://fr.news.hada.io/topic?id=1621
Merci
Je suis d'accord. Merci :)
👍