50 puan yazan xguru 2021-04-12 | 11 yorum | WhatsApp'ta paylaş
  • Stres olmadan, yavaş tempoda SaaS işleten tek kişilik bir geliştiricinin mimarisinin açıklaması

  • Aynı anda birden fazla projeyi çalıştıran bir altyapı kurmuş

  • Açıklamayı yakın zamanda yaptığı PanelBear adlı SaaS'ı temel alarak yapıyor
    → En küçük VPS üzerinde SQLite + Django ile başladı
    → 6 aylık iterasyonun ardından, EKS üzerinde Django monolith + Postgres + ClickHouse (analitik) + Redis (önbellekleme) + Celery (zamanlanmış işler)
    → Çoğu şey otomatik: autoscaling, ingress, TLS sertifikaları, failover, logging, monitoring vb.
    → Bu kurulum birden fazla projede kullanıldığı için maliyeti düşürüyor ve deneyleri gerçekten çok kolay başlatmayı sağlıyor
    → Altyapı yönetimi neredeyse hiç zaman almıyor (ayda 0~2 saat).
    → Zamanın büyük kısmı özellik geliştirme, müşteri desteği ve işi büyütmeye gidiyor

  • AWS'de Kubernetes kullanıyor ama bunun şart olmadığını söylüyor. Yine de buna alışık olduğu için istikrarlı biçimde işletebildiğini düşünüyor.
    → Sabırlı bir ekipte (hatalara birlikte katlanıp engel olan) bu aracı yıllarca kullanarak öğrenmiş
    → "Kubernetes basit şeyleri karmaşıklaştırır ama karmaşık şeyleri de basitleştirebilir"

  • Otomatik DNS, SSL ve load balancing
    → Tüm trafik CloudFlare Proxy'den AWS L4 NLB'ye (Network Load Balancer) iletiliyor
    → Bir request geldiğinde LB bunu k8s cluster düğümlerinden birine forward ediyor
    → Bu düğümler birden fazla AZ'ye (Availability Zone) yayılmış private subnet'lerde bulunuyor
    → k8s'in isteğin hangi servise gideceğini bulmasını ingress-nginx (Nginx cluster) yapıyor
    → nginx, trafiği iletmeden önce Rate Limiting ve traffic shaping kuralları uyguluyor
    → PanelBear örneğinde uygulama container'ı, Uvicorn üzerinde sunulan Django
    → Terraform/K8s arasında birkaç yapılandırma dosyası var ve çoğu proje bunları paylaşıyor
    → Yeni proje deploy ederken yaklaşık 20 satırlık ingress yapılandırması yeterli

  • Otomatik rollout ve rollback
    → Master'a her push'ta GitHub Actions ile CI pipeline çalışıyor
    → Kod tabanı inceleniyor, Docker-Compose ile tam ortam kurularak E-to-E testleri yapılıyor
    → Kontroller geçerse ECR'ye (AWS'nin Docker Registry'si) push edilecek yeni Docker image'ı build ediliyor
    → k8s cluster içindeki flux bileşeni ( https://fluxcd.io/ ) cluster'daki image'ları otomatik olarak senkronize ediyor
    → Flux otomatik olarak incremental rollout gerçekleştiriyor

  • Horizontal Autoscaling
    → CPU/bellek kullanımına göre autoscaling
    → Cluster'da düğüm başına çok fazla Pod varsa, cluster kapasitesini artırmak ve yükü azaltmak için otomatik olarak daha fazla sunucu oluşturuluyor; iş olmadığında küçültülüyor
    → PanelBear örneğinde API Pod'ları için kopya sayısı 2 ile 8 arasında otomatik ayarlanıyor

  • Static asset'leri CDN ile cache'leme
    → CloudFlare DNS'e tanımlanarak tüm istekleri işliyor ve DDoS koruması da sağlıyor
    → Static dosya sunumu için Whitenoise ( https://github.com/evansd/whitenoise ) kullanılıyor; böylece dosyaları NGinx/Cloudfront/S3'e upload etmeye gerek kalmıyor
    → PanelBear'in landing page'i gibi bazı statik web sitelerinde NextJS kullanılıyor

  • Uygulama verisi cache'leme
    → Bazı bölümlerde Python'ın sunduğu in-memory LRU cache kullanılıyor
    → Endpoint'lerin çoğunda cluster içi Redis kullanılıyor

  • Endpoint başına Rate Limiting
    → nginx-ingress global rate limit uygulasa da bazen endpoint/metot bazında özel limitler vermek gerekiyor
    → Django Ratelimit kütüphanesi kullanılarak Django view başına sınır tanımlanabiliyor
    → Redis backend olarak kullanılıyor ve her endpoint'e request atan client'ları izlemek üzere yapılandırılmış (IP yerine client key tabanlı hash)

  • Uygulama yönetimi
    → Django'nun Admin Panel'i varsayılan olarak verileri görüntüleme ve düzenleme işlevlerini destekliyor
    → Şüpheli hesap erişimini engelleme / duyuru e-postası gönderme / hesap silme taleplerini işleme gibi özellikler eklenmiş (önce soft delete, ardından 72 saat içinde kalıcı silme)

  • Zamanlanmış işlerin çalıştırılması
    → SaaS'ta çeşitli zamanlanmış işler çalışıyor: müşterilere günlük raporlar, her 15 dakikada bir kullanım istatistiklerinin hesaplanması, çalışanlara gönderilen metrik e-postaları vb.
    → Cluster içinde birkaç Celery worker ve Celery beat scheduler çalışıyor. Task queue olarak Redis kullanılıyor
    → Zamanlanmış işler düzgün çalışmadığında SMS/Slack/Email ile bildirim almak için HealthChecks.io kullanılıyor

  • Uygulama yapılandırması
    → Tüm ayarlar environment variable'larla yapılıyor. Eski usul ama taşınabilir ve iyi destekleniyor

  • Secret'ları koruma
    → kubeseal kullanılıyor. Asimetrik şifreleme ile Secret'lar şifreleniyor. Yalnızca şifre çözme anahtarına erişim izni olan cluster şifreyi çözebiliyor
    → Cluster içindeki Secret'ları korumak için AWS KMS'nin şifreleme anahtarı kullanılıyor

  • İlişkisel veri: Postgres
    → Deneyler için cluster içinde vanilla Postgres container'ı çalıştırılıyor ve K8s Cronjob ile S3'e günlük yedek alınıyor
    → Proje büyüdüğünde veritabanı cluster içinden RDS'ye taşınıyor ve şifreli yedekler ile güvenlik güncellemelerini AWS üstleniyor
    → Güvenliği artırmak için AWS veritabanına yalnızca Private Network içinden erişilebiliyor

  • Sütun bazlı veri: ClickHouse
    → PanelBear'in analitik verilerini verimli biçimde depolamak ve gerçek zamanlı sorgulamak için ClickHouse kullanılıyor
    → Harika bir columnar veritabanı; çok hızlı ve yapı doğru kurulursa yüksek sıkıştırma oranı sunuyor (daha az depolama = daha fazla gelir)
    → ClickHouse instance'ı K8s cluster içinde self-host ediliyor
    → Columnar verileri periyodik olarak S3'e yedekleyen bir CronJob oluşturulmuş
    → Felaket durumunda veriyi S3'ten manuel yedekleyip geri yüklemek için birkaç script var

  • DNS tabanlı servis keşfi
    → K8s, cluster içindeki DNS kayıtlarını otomatik yöneterek trafiği ilgili servise yönlendiriyor
    → Autoscaling sırasında da sağlıklı pod'lara bağlanılması için DNS kayıtlarını otomatik senkronize ediyor

  • Sürüm kontrollü altyapı
    → Docker, Terraform ve K8s manifest'leri tek bir depoda (Infra Mono-Repo) yönetiliyor
    → Basit komutlarla altyapı oluşturulup silinebiliyor ve sürüm kontrolü sayesinde yeniden üretilebiliyor

  • Cloud resource'ları için Terraform
    → Cloud kaynaklarının çoğu Terraform ile yönetiliyor
    → Bu sayede altyapı kaynakları ve ayarları belgelenebiliyor ve izlenebiliyor

  • Uygulama deploy'u için K8s manifest'leri
    → Altyapı mono repo'sundaki YAML dosyalarında K8s manifest'leri yer alıyor
    cluster ve apps olmak üzere iki klasöre ayrılmış
    cluster içinde nginx-ingress, şifrelenmiş secret'lar, Prometheus scraper gibi cluster geneli servis ayarları bulunuyor
    apps içinde her proje için bir namespace altında bilgiler tutuluyor

  • Abonelik ve ödeme
    → Tüm ödemeler Stripe Checkout ile işleniyor
    → Ödeme bilgisinin kendisiyle uğraşmak gerekmediğinden ürüne odaklanmayı sağlıyor
    → Müşteri oturumu oluşturup Stripe sayfasına yönlendirdikten sonra sonucu WebHook ile almak yeterli

  • Logging
    → Bir logging agent kullanmak yerine stdout'a log yazdırmak yeterli; k8s logları otomatik topluyor ve rotate işlemini de yapıyor
    → FluentBit vb. ile Elasticsearch/Kibana'ya gönderilebilir ama sistemi basit tutmak için henüz yapılmıyor
    → Log incelemek için CLI aracı stern kullanılıyor

  • Monitoring ve uyarılar
    → Başta Prometheus / Grafana self-host ediliyordu ama cluster sorunu yaşandığında uyarı sistemi de birlikte durduğu için kullanışsız olmuş
    → Bu yüzden New Relic'e geçilmiş
    → Tüm servislerde metrikleri otomatik toplayıp Datadog, New Relic, Grafana Cloud vb.'ye gönderebilen bir Prometheus Integration olduğu için, New Relic'e geçiş onların sağladığı Prometheus Docker image'ını kullanmak kadar kolay olmuş

  • Hata takibi
    → Uygulama hatalarını toplamak için Sentry kullanılıyor
    → downtime, cron job failure'ları, güvenlik uyarıları, performans gerilemeleri, uygulama exception'ları gibi tüm alarmları merkezileştirmek için Slack #alerts kanalı kullanılıyor

  • Profiling ve diğer güzel şeyler
    → Derin analiz gerektiğinde cProfile veya snakeviz gibi araçlar kullanılıyor
    → Local makinede Django Debug Toolbar kullanılıyor

11 yorum

 
wellsbabo 2024-08-13

Teşekkür ederim

 
admin2 2021-04-13

Sentry ile New Relic arasında işlev farkı çok mu?

Benzer işlevler sunduklarını düşünmüştüm ama henüz hiç kullanmadım.

 
kbumsik 2021-04-13

Ah, şirketimizde de k8s kullanımını değerlendirmeyi düşünüyoruz; tek kişilik bir startup olmasa bile oldukça iyi bir yazıymış.

 
fortune 2021-04-12

Güzel yazı için teşekkürler. İlham alarak ayrılıyorum.

 
khris 2021-04-12

Tek kişilik bir startup olmak zorunda değil; yine de güzel bir yazı.

 
yshrust 2021-04-12

Küçük bir yazım hatası var,,

  • Hata takibi

→ Sentry kullanarak uygulama hatalarını topla

=> Sanırım "topla" olmalı

 
xguru 2021-04-12

Teşekkürler. Düzelttim~!

 
xguru 2021-04-12

Ülkemizde de kendi hizmetiyle para kazanan tek kişilik geliştiricilerin veya küçük ekiplerin daha fazla ortaya çıkmasını umuyorum.

GeekNews'in de bu tür hizmetlerin kendilerini tanıttığı ve sağlıklı geri bildirim aldığı bir alan olarak büyümesini isterim.

 
wellsbabo 2024-08-13

Teşekkür ederim

 
reedids 2021-04-12

Katılıyorum. Teşekkürler :)

 
e1q88 2021-04-12

👍