50 pontos por xguru 2021-04-12 | 11 comentários | Compartilhar no WhatsApp
  • Explicação da arquitetura de um desenvolvedor solo que opera um SaaS de forma tranquila, sem estresse

  • Montou uma infraestrutura para operar vários projetos ao mesmo tempo

  • Explica com base no PanelBear, um SaaS que criou recentemente
    → começou no menor VPS possível com SQLite + Django
    → após 6 meses de iteração, evoluiu para Django monolítico sobre EKS + Postgres + ClickHouse (análises) + Redis (cache) + Celery (tarefas agendadas)
    → quase tudo automatizado: autoscaling, ingress, certificados TLS, failover, logging, monitoramento etc.
    → como usa essa configuração em vários projetos, consegue reduzir custos e iniciar experimentos com muita facilidade
    → quase não gasta tempo com gestão de infraestrutura (0 a 2 horas por mês)
    → usa a maior parte do tempo para desenvolver funcionalidades, dar suporte aos clientes e fazer o negócio crescer

  • Usa Kubernetes na AWS, mas isso não é necessariamente obrigatório. Ainda assim, acredita que consegue operar com estabilidade por já estar familiarizado com a ferramenta.
    → aprendeu usando essa ferramenta por vários anos em uma equipe paciente (que aguentava e resolvia os erros junto)
    → "Kubernetes torna o simples complicado, mas também pode tornar o complicado simples"

  • DNS, SSL e balanceamento de carga automáticos
    → todo o tráfego é encaminhado do CloudFlare Proxy para o AWS L4 NLB (Network Load Balancer)
    → quando uma request chega, o LB a encaminha para um dos nós do cluster k8s
    → esses nós ficam em sub-redes privadas distribuídas por várias AZs (Availability Zones)
    → quem descobre para qual serviço o k8s deve enviar a requisição é o ingress-nginx (cluster Nginx)
    → antes de encaminhar o tráfego, o nginx aplica regras de rate limiting e traffic shaping
    → no caso do PanelBear, o container da aplicação é Django servido pelo Uvicorn
    → existem alguns arquivos de configuração entre Terraform/K8s que são compartilhados pela maioria dos projetos
    → ao implantar um novo projeto, cerca de 20 linhas de configuração de ingress bastam

  • Rollout e rollback automáticos
    → toda vez que há push para a branch master, um pipeline de CI é executado com GitHub Actions
    → inspeciona a codebase e monta um ambiente completo com Docker-Compose para testes end-to-end
    → se passar nas verificações, gera uma nova imagem Docker e faz push para o ECR (registro Docker da AWS)
    → o componente flux no cluster k8s ( https://fluxcd.io/ ) sincroniza automaticamente as imagens no cluster
    → o Flux executa rollout incremental automaticamente

  • Horizontal Autoscaling
    → autoscaling com base no uso de CPU/memória
    → se houver Pods demais por nó no cluster, cria automaticamente mais servidores para aumentar a capacidade do cluster e reduzir a carga; quando não há trabalho, reduz novamente
    → no caso do PanelBear, ajusta automaticamente as réplicas do Pod da API de 2 até 8

  • Cache de static assets com CDN
    → configura o CloudFlare no DNS para processar todas as requisições e ainda mitigar DDoS
    → para servir arquivos estáticos usa Whitenoise ( https://github.com/evansd/whitenoise ), então não precisa fazer upload dos arquivos para NGinx/Cloudfront/S3
    → em alguns sites estáticos, como a landing page do Panelbear, usa NextJS

  • Cache de dados da aplicação
    → em algumas partes usa o cache LRU em memória oferecido pelo Python
    → a maioria dos endpoints usa Redis dentro do cluster

  • Rate limiting por endpoint
    → faz rate limiting global no nginx-ingress, mas às vezes é preciso aplicar limites específicos por endpoint/método
    → usa a biblioteca Django Ratelimit para declarar limites por view do Django
    → configurado para usar Redis como backend e rastrear clientes que acessam cada endpoint (hash com base em chave do cliente, não em IP)

  • Administração do app
    → o Admin Panel do Django já oferece, por padrão, recursos para visualizar e editar dados
    → adicionou funções como bloquear acesso a contas suspeitas / enviar emails de aviso / processar solicitações de exclusão de conta (primeiro com soft delete, depois exclusão completa em até 72 horas)

  • Execução de tarefas agendadas
    → em um SaaS, várias tarefas agendadas rodam: relatórios diários para clientes, cálculo de estatísticas de uso a cada 15 minutos, emails de métricas para a equipe etc.
    → mantém alguns workers do Celery e o scheduler Celery beat rodando dentro do cluster. Usa Redis como fila de tarefas
    → usa o HealthChecks.io para ser avisado por SMS/Slack/Email quando tarefas agendadas não são executadas corretamente

  • Configuração do app
    → toda a configuração usa variáveis de ambiente. É antigo, mas portátil e bem suportado

  • Protegendo segredos
    → usa kubeseal. Ele criptografa os Secrets com criptografia assimétrica. Só clusters com permissão de acesso à chave de descriptografia conseguem descriptografar
    → usa chaves de criptografia do AWS KMS para proteger os Secrets dentro do cluster

  • Dados relacionais: Postgres
    → para experimentos, roda um container Postgres vanilla dentro do cluster e faz backup diário para o S3 com um K8s Cronjob
    → quando o projeto cresce, move o banco de dados do cluster para o RDS, deixando a AWS cuidar de backups criptografados, updates de segurança etc.
    → para reforçar a segurança, o banco de dados na AWS só pode ser acessado pela rede privada

  • Dados colunares: ClickHouse
    → usa ClickHouse para armazenar com eficiência e consultar em tempo real os dados analíticos do PanelBear
    → é um excelente banco de dados colunar, muito rápido e, com a modelagem certa, oferece alta compressão (menos storage = mais lucro)
    → hospeda a instância do ClickHouse por conta própria dentro do cluster K8s
    → criou um CronJob que faz backup periódico dos dados colunares para o S3
    → tem alguns scripts para backup e restauração manual dos dados a partir do S3 em caso de desastre

  • Descoberta de serviços baseada em DNS
    → o K8s gerencia automaticamente os registros DNS dentro do cluster e roteia o tráfego para o serviço correspondente
    → mesmo durante o autoscaling, sincroniza automaticamente os registros DNS para conectar aos Pods saudáveis

  • Infraestrutura com versionamento
    → gerencia Docker, Terraform e manifests do K8s em um único repositório (Infra Mono-Repo)
    → é possível criar e remover infraestrutura com comandos simples, e o versionamento permite reprodutibilidade

  • Terraform para recursos de cloud
    → a maior parte dos recursos de cloud é gerenciada com Terraform
    → isso permite documentar e rastrear recursos e configurações de infraestrutura

  • Manifests de K8s para deploy do app
    → os manifests de K8s estão escritos em arquivos YAML no mono-repo de infraestrutura
    → dividido em duas pastas: cluster e apps
    cluster inclui configurações relacionadas a serviços do cluster como nginx-ingress, secrets criptografados e scrapers do Prometheus
    apps armazena as informações de um namespace por projeto

  • Assinaturas e pagamentos
    → usa Stripe Checkout para processar todos os pagamentos
    → como não precisa lidar diretamente com os dados de pagamento, consegue focar no produto
    → basta criar a sessão do cliente, redirecionar para a página da Stripe e receber o resultado por WebHook

  • Logging
    → sem usar agente de logging: basta enviar logs para o stdout que o k8s coleta automaticamente e também faz rotação
    → seria possível enviar para Elasticsearch/Kibana via FluentBit etc., mas ainda não faz isso para manter a simplicidade
    → para inspecionar logs, usa a ferramenta de CLI stern

  • Monitoramento e alertas
    → no início hospedava Prometheus / Grafana por conta própria, mas quando havia problema no cluster, o sistema de alertas também caía, o que era inconveniente
    → por isso, migrou para o New Relic
    → todos os serviços têm integração com Prometheus para coletar métricas automaticamente e enviar para Datadog, New Relic, Grafana Cloud etc.; assim, a migração para o New Relic foi possível apenas usando a imagem Docker do Prometheus fornecida por eles

  • Rastreamento de erros
    → usa Sentry para coletar erros da aplicação
    → centraliza todos os alertas no canal Slack #alerts: downtime, falhas de cron job, alertas de segurança, regressões de performance, exceções da aplicação etc.

  • Profiling e outras coisas úteis
    → quando precisa de análise profunda, usa ferramentas como cProfile ou snakeviz
    → na máquina local, usa Django Debug Toolbar

11 comentários

 
wellsbabo 2024-08-13

Obrigado.

 
admin2 2021-04-13

Há muita diferença de funcionalidade entre o Sentry e o New Relic?

Eu achava que eles faziam coisas parecidas, mas ainda não usei nenhum dos dois.

 
kbumsik 2021-04-13

Ah, nossa empresa também está avaliando adotar k8s, e este é um texto bastante bom mesmo para startups que não são de uma pessoa só.

 
fortune 2021-04-12

Obrigado pelo ótimo texto. Saio daqui inspirado.

 
khris 2021-04-12

É um bom texto, mesmo que não seja necessariamente sobre uma startup de uma pessoa só

 
yshrust 2021-04-12

Tem um pequeno erro de digitação,,

  • Rastreamento de erros

→ usar o Sentry para coletar erros da aplicação

=> acho que o correto é “coletar”

 
xguru 2021-04-12

Obrigado. Corrigi~!

 
xguru 2021-04-12

Eu espero que surjam mais desenvolvedores solo ou pequenas equipes no país que ganhem dinheiro com seus próprios serviços.

Espero que o GeekNews cresça como um espaço onde esses serviços possam se apresentar e receber feedback saudável.

 
wellsbabo 2024-08-13

Obrigado.

 
reedids 2021-04-12

Concordo. Obrigado :)

 
e1q88 2021-04-12

👍