50 poin oleh xguru 2021-04-12 | 11 komentar | Bagikan ke WhatsApp
  • Penjelasan arsitektur dari seorang developer solo yang menjalankan SaaS dengan santai dan tanpa stres

  • Ia membangun infrastruktur untuk menjalankan beberapa proyek secara bersamaan

  • Penjelasan didasarkan pada SaaS terbarunya, PanelBear
    → mulai dari VPS paling kecil dengan SQLite + Django
    → setelah iterasi selama 6 bulan, menjadi Django monolith + Postgres + ClickHouse (analitik) + Redis (caching) + Celery (pekerjaan terjadwal) di atas EKS
    → sebagian besar sudah diotomatisasi: autoscaling, ingress, sertifikat TLS, failover, logging, monitoring, dan lain-lain
    → karena konfigurasi ini dipakai di beberapa proyek, biaya bisa ditekan dan eksperimen baru bisa dimulai dengan sangat mudah
    → hampir tidak ada waktu yang dihabiskan untuk mengelola infrastruktur (0~2 jam per bulan)
    → sebagian besar waktu dipakai untuk pengembangan fitur, dukungan pelanggan, dan menumbuhkan bisnis

  • Menggunakan Kubernetes di AWS, tetapi ini bukan berarti wajib. Hanya saja, karena sudah terbiasa, ia merasa bisa mengoperasikannya dengan stabil.
    → dipelajari selama beberapa tahun dengan menggunakan alat ini di tim yang sabar (yang mau ikut menanggung dan memperbaiki error bersama)
    → "Kubernetes membuat hal sederhana menjadi rumit, tetapi juga bisa membuat hal rumit menjadi sederhana"

  • DNS otomatis, SSL, dan load balancing
    → semua trafik diteruskan dari CloudFlare Proxy ke AWS L4 NLB (Network Load Balancer)
    → ketika request masuk, LB meneruskannya ke salah satu node di klaster k8s
    → node-node ini berada di subnet privat yang tersebar di beberapa AZ (Availability Zone)
    → ingress-nginx (klaster Nginx) yang menentukan layanan mana di k8s yang harus menerima request
    → sebelum meneruskan trafik, nginx menerapkan aturan rate limiting dan traffic shaping
    → untuk PanelBear, container aplikasi menjalankan Django yang disajikan oleh Uvicorn
    → ada beberapa file konfigurasi antara Terraform/K8s dan sebagian besar proyek berbagi file yang sama
    → saat men-deploy proyek baru, cukup dengan sekitar 20 baris konfigurasi ingress

  • Rollout dan rollback otomatis
    → setiap kali push ke master, pipeline CI dijalankan lewat GitHub Actions
    → memeriksa codebase dan membuat environment lengkap dengan Docker-Compose untuk pengujian end-to-end
    → jika lolos pemeriksaan, akan dibangun image Docker baru yang di-push ke ECR (Docker Registry milik AWS)
    → komponen flux di klaster k8s ( https://fluxcd.io/ ) otomatis menyinkronkan image di dalam klaster
    → Flux otomatis menjalankan incremental rollout

  • Horizontal Autoscaling
    → autoscaling berdasarkan penggunaan CPU/memori
    → jika jumlah Pod per node di klaster terlalu banyak, sistem otomatis membuat lebih banyak server untuk menambah kapasitas klaster dan mengurangi beban. Saat tidak ada pekerjaan, kapasitas diperkecil kembali
    → untuk PanelBear, replika API Pod disesuaikan otomatis dari 2 sampai 8

  • Caching static asset dengan CDN
    → CloudFlare diatur di DNS untuk menangani semua request sekaligus perlindungan DDoS
    → untuk menyajikan file statis digunakan Whitenoise ( https://github.com/evansd/whitenoise ) sehingga tidak perlu mengunggah file ke NGinx/Cloudfront/S3
    → untuk beberapa situs web statis seperti landing page PanelBear digunakan NextJS

  • Caching data aplikasi
    → pada beberapa bagian digunakan in-memory LRU caching bawaan Python
    → sebagian besar endpoint menggunakan Redis di dalam klaster

  • Rate Limiting per Endpoint
    → nginx-ingress melakukan rate limit global, tetapi kadang perlu memberi limit khusus per endpoint/metode
    → dengan library Django Ratelimit, batasan bisa dideklarasikan per Django view
    → dikonfigurasi agar menggunakan Redis sebagai backend untuk melacak klien yang mengakses tiap endpoint (hash berbasis client key, bukan IP)

  • Administrasi aplikasi
    → Admin Panel milik Django secara default sudah mendukung fungsi untuk melihat dan mengedit data
    → menambahkan fungsi seperti memblokir akses akun mencurigakan / mengirim email pengumuman / menangani permintaan penghapusan akun (awalnya soft delete, lalu dihapus permanen dalam 72 jam)

  • Menjalankan pekerjaan terjadwal
    → dalam SaaS ada berbagai pekerjaan terjadwal: laporan harian untuk pelanggan, perhitungan statistik penggunaan setiap 15 menit, email metrik untuk staf, dan sebagainya
    → beberapa worker Celery dan scheduler Celery beat dijalankan di dalam klaster. Redis dipakai sebagai task queue
    → agar menerima notifikasi lewat SMS/Slack/Email saat pekerjaan terjadwal tidak berjalan semestinya, digunakan HealthChecks.io

  • Konfigurasi aplikasi
    → semua konfigurasi menggunakan environment variable. Cara lama, tetapi portabel dan didukung dengan baik

  • Menjaga secret
    → menggunakan kubeseal. Secret dienkripsi dengan kriptografi asimetris. Hanya klaster yang memiliki hak akses ke kunci dekripsi yang bisa mendekripsinya
    → untuk melindungi secret di dalam klaster digunakan kunci enkripsi AWS KMS

  • Data relasional: Postgres
    → untuk eksperimen dijalankan container Postgres vanilla di dalam klaster, lalu backup harian ke S3 dilakukan dengan K8s Cronjob
    → ketika proyek bertumbuh, database dipindahkan dari dalam klaster ke RDS agar AWS menangani backup terenkripsi dan pembaruan keamanan
    → demi memperkuat keamanan, DB di AWS hanya bisa diakses dari Private Network

  • Data kolumnar: ClickHouse
    → untuk menyimpan dan melakukan query data analitik PanelBear secara efisien dan real-time digunakan ClickHouse
    → ini adalah database columnar yang sangat bagus, sangat cepat, dan jika strukturnya dirancang dengan baik bisa memberikan rasio kompresi tinggi (pengurangan storage = peningkatan keuntungan)
    → instance ClickHouse di-self-host di dalam klaster K8s
    → membuat CronJob untuk backup data kolumnar ke S3 secara berkala
    → saat terjadi bencana, ada beberapa skrip untuk membackup dan memulihkan data secara manual dari S3

  • Service discovery berbasis DNS
    → K8s otomatis mengelola record DNS di dalam klaster untuk merutekan trafik ke layanan yang sesuai
    → bahkan saat autoscaling, record DNS otomatis disinkronkan agar tetap terhubung ke pod yang sehat

  • Infrastructure yang dikelola dengan version control
    → Docker, Terraform, dan manifest K8s dikelola dalam satu repositori tunggal (Infra Mono-Repo)
    → infrastruktur bisa dibuat dan dihapus dengan perintah sederhana, serta dapat direproduksi lewat version control

  • Terraform untuk cloud resource
    → sebagian besar resource cloud dikelola dengan Terraform
    → ini memungkinkan resource dan konfigurasi infrastruktur terdokumentasi serta dapat dilacak

  • Manifest K8s untuk deploy aplikasi
    → manifest K8s ditulis di file YAML dalam infra mono repo
    → dibagi ke dalam dua folder: cluster dan apps
    → folder cluster berisi konfigurasi terkait layanan seluruh klaster seperti nginx-ingress, secret terenkripsi, dan scraper Prometheus
    → folder apps menyimpan informasi dalam satu namespace per proyek

  • Langganan dan pembayaran
    → semua pembayaran diproses dengan Stripe Checkout
    → karena tidak perlu terlibat langsung dengan informasi pembayaran, fokus bisa tetap pada produk
    → cukup membuat sesi pelanggan, mengarahkan ke halaman Stripe, lalu menerima hasilnya melalui WebHook

  • Logging
    → tanpa memakai logging agent, cukup keluarkan log ke stdout maka k8s akan otomatis mengumpulkan log dan melakukan rotasi
    → log memang bisa dikirim ke Elasticsearch/Kibana lewat FluentBit dan sejenisnya, tetapi belum dilakukan agar tetap sederhana
    → untuk memeriksa log digunakan tool CLI bernama stern

  • Monitoring dan alert
    → awalnya Prometheus / Grafana di-self-host, tetapi saat terjadi masalah pada klaster, sistem peringatannya ikut berhenti sehingga merepotkan
    → karena itu kemudian pindah ke New Relic
    → semua layanan memiliki integrasi Prometheus yang secara otomatis mengumpulkan metrik dan bisa mengirimkannya ke Datadog, New Relic, Grafana Cloud, dan lainnya, jadi migrasi ke New Relic cukup dengan memakai image Docker Prometheus yang mereka sediakan

  • Pelacakan error
    → menggunakan Sentry untuk mengumpulkan error aplikasi
    → semua peringatan dipusatkan di channel Slack #alerts, termasuk downtime, kegagalan cron job, alert keamanan, regresi performa, dan exception aplikasi

  • Profiling dan hal-hal bagus lainnya
    → ketika perlu analisis mendalam, digunakan tool seperti cProfile atau snakeviz
    → di mesin lokal digunakan Django Debug Toolbar

11 komentar

 
wellsbabo 2024-08-13

Terima kasih

 
admin2 2021-04-13

Apakah perbedaan fitur antara Sentry dan New Relic cukup besar?

Saya tadinya mengira keduanya punya fungsi yang mirip, tetapi saya belum pernah mencobanya.

 
kbumsik 2021-04-13

Oh, di perusahaan kami juga sedang mempertimbangkan adopsi k8s, dan ini artikel yang sangat bagus meskipun bukan hanya untuk startup satu orang.

 
fortune 2021-04-12

Terima kasih untuk tulisan yang bagus. Saya jadi terinspirasi.

 
khris 2021-04-12

Ini tulisan yang bagus, meskipun tidak harus untuk startup satu orang.

 
yshrust 2021-04-12

Ada salah ketik kecil,,

  • Pelacakan error

→ Menggunakan Sentry untuk me... error aplikasi

=> Sepertinya maksudnya "mengumpulkan"

 
xguru 2021-04-12

Terima kasih. Sudah saya perbaiki~!

 
xguru 2021-04-12

Saya berharap akan semakin banyak pengembang solo atau tim kecil di dalam negeri yang menghasilkan uang dari layanan mereka sendiri.

Saya juga berharap GeekNews bisa berkembang menjadi tempat bagi layanan-layanan seperti itu untuk memperkenalkan diri dan menerima masukan yang sehat.

 
wellsbabo 2024-08-13

Terima kasih

 
reedids 2021-04-12

Saya setuju. Terima kasih :)

 
e1q88 2021-04-12

👍