Dua Arah Lalu Lintas, Satu Kotak
Selamat Datang
Sebagian besar diagram arsitektur menunjukkan lalu lintas bergerak ke satu arah: klien di atas, server di bawah, panah menunjuk ke bawah. Kenyataannya, lalu lintas bergerak ke kedua arah.
Ingress: klien eksternal mencapai layanan Anda melalui jalur ini. Reverse proxy di tepi jaringan Anda mengakhiri TLS, merutekan permintaan, & menerapkan kebijakan akses.
Egress: layanan Anda mencapai layanan eksternal melalui jalur ini. Memanggil API pemroses pembayaran, mengambil target webhook, mengirim permintaan ke mitra. Seringkali melalui forward proxy atau NAT gateway dengan daftar izin (allowlist).
Banyak arsitektur dimulai dengan satu kotak yang menangani keduanya. Cara kerjanya, sampai hari di mana ia tidak lagi berfungsi. Mode kegagalannya halus, hanya muncul setelah cukup banyak layanan internal ada, & mengajarkan pelajaran penting tentang pemisahan kepedulian (separation-of-concerns).
Pada akhir pelajaran ini, Anda akan memahami:
- Mengapa ingress & egress mewakili pola lalu lintas yang secara fundamental berbeda dengan sumbu penskalaan yang berbeda & mode kegagalan yang berbeda
- Hairpin NAT & mengapa proxy yang mencoba terhubung ke dirinya sendiri gagal
- Percabangan arsitektur: satu kotak menjadi dua, & apa yang kemudian dimiliki secara eksklusif oleh masing-masing
- Keuntungan isolasi keamanan: setiap sisi dapat mengunci ke mitra yang diizinkan secara nyata
- Cara mengidentifikasi kapan desain satu kotak Anda telah melampaui ambang batas di mana pemisahan diperlukan
Mengapa Arah-Arah Tersebut Membutuhkan Alat yang Berbeda
Dua Beban Kerja Berbeda di Satu Batas Jaringan
Karakteristik trafik masuk (ingress):
- Diinisiasi oleh pihak eksternal (internet secara umum)
- Volume meningkat seiring dengan basis pengguna Anda
- Terminasi TLS, perutean permintaan, pembatasan laju per sumber
- Kekhawatiran pertahanan berlapis: DDoS, penyalahgunaan, scraping
- IP publik harus menerima koneksi dari siapa pun
Karakteristik trafik keluar (egress):
- Diinisiasi oleh layanan Anda sendiri (kumpulan klien yang dikenal dan terbatas)
- Volume meningkat seiring dengan pola panggilan layanan-ke-layanan & API eksternal Anda
- Allowlisting IP sumber di endpoint jarak jauh (Anda memiliki satu IP keluaran tetap yang dipercaya oleh mitra)
- Kekhawatiran pertahanan berlapis: eksfiltrasi data, layanan internal yang terkompromi yang melakukan panggilan keluar
- Seharusnya menolak koneksi dari siapa pun selain layanan Anda sendiri
Asimetri kunci: ingress menerima trafik dari dunia; egress menerima trafik hanya dari layanan Anda sendiri. Menempatkannya di mesin yang sama berarti mesin tersebut harus dapat dijangkau secara bersamaan dari dunia (untuk ingress) & hanya dari layanan Anda (untuk egress). Aturan firewall yang memenuhi salah satu justru bertentangan dengan yang lain.
Jalur pertumbuhan: proyek kecil dapat menyembunyikan keduanya di balik satu IP & satu alat, karena volumenya kecil & daftar izin IP mitra pendek. Seiring proyek berkembang, gesekan antara kedua peran tersebut meningkat, & suatu hari satu mode kegagalan spesifik (hairpin NAT) memaksa pemisahan tersebut.
Bug yang Memaksa Pemisahan
Kisah Gangguan yang Disanitasi
Bayangkan sebuah percabangan arsitektur nyata yang terjadi di armada produksi. Nama-nama di bawah ini telah diubah; bentuknya identik dengan apa yang dihadapi tim di lapangan.
Sebuah organisasi menjalankan satu server proxy di 203.0.113.5. Server ini menangani ingress (port 443 untuk pengguna) & egress (port 1080 SOCKS5 untuk layanan internal yang memanggil keluar). Layanan internal berada di subnet privat & merutekan semua lalu lintas keluar melalui proxy SOCKS5 tersebut di 203.0.113.5:1080.
Salah satu layanan yang dihosting di belakang 203.0.113.5 yang sama adalah api.example.com. DNS publik menyelesaikan api.example.com menjadi 203.0.113.5.
Sekarang, layanan internal yang berbeda perlu memanggil api.example.com. Jalur keluarnya:
1. Layanan internal menyelesaikan api.example.com → 203.0.113.5
2. Layanan internal mengirim permintaan melalui proxy egress SOCKS5 di 203.0.113.5:1080
3. Proxy mencoba membuka koneksi dari dirinya sendiri ke 203.0.113.5:443
4. Koneksi ditolak. Paket harus keluar & masuk kembali ke NAT yang sama, yang ditolak oleh sebagian besar stack jaringan. Proxy tidak dapat terhubung ke dirinya sendiri melalui IP publiknya sendiri.
Ini adalah hairpin NAT: paket yang keluar dari NAT & perlu masuk kembali ke NAT yang sama untuk mencapai tujuannya. Tanpa dukungan hairpin khusus di lapisan routing, paket akan terbuang.
Mengapa Masalah Ini Muncul Terlambat
Di awal proyek, setiap layanan internal berkomunikasi dengan layanan internal lainnya menggunakan nama host privat (internal-api.local) atau tidak memanggil kembali layanan publik organisasi mereka sendiri. Jalur hairpin tersebut sama sekali tidak ada.
Kemudian, fitur baru mengharuskan layanan A untuk memanggil api.example.com (nama host publik). Jalur hairpin tersebut teraktivasi. Koneksi ditolak. Gangguan terjadi.
Perbaikan tersebut hanya menambal gejalanya (memaksa resolver untuk memberikan IP privat api.example.com alih-alih IP publik). Akar masalahnya: satu mesin melakukan terlalu banyak tugas.
Cabang Arsitektural
Satu Kotak Menjadi Dua
Solusi yang bersih: pisahkan proxy menjadi dua mesin.
Server Ingress (IP publik 203.0.113.5):
- Caddy / reverse proxy pada port 80, 443
- Catatan DNS publik menunjuk ke sini
- Menjaminkan api.example.com, app.example.com, dll.
Server Egress (IP publik yang berbeda 203.0.113.99):
- SOCKS5 / forward proxy pada port 1080
- Firewall membatasi koneksi masuk hanya ke IP subnet internal
- Layanan internal merutekan semua keluaran melalui alamat ini
Apa yang didapat:
1. Hairpin terpecahkan. Layanan internal yang memanggil api.example.com merutekan keluaran melalui 203.0.113.99 (egress), yang kemudian terhubung secara normal ke 203.0.113.5 (ingress, IP yang berbeda). Loop NAT hilang karena kedua IP tersebut berada di mesin yang berbeda.
2. Isolasi keamanan. Firewall server egress dapat dikunci ke set kecil IP internal. Firewall server ingress tetap terbuka ke dunia luar. Dua set aturan terpisah, masing-masing mengekspresikan satu peran dengan jelas.
3. Skala independen. Bandwidth ingress berskala dengan pengguna; bandwidth egress berskala dengan aktivitas layanan internal. Tingkatkan salah satu tanpa menyentuh yang lain.
4. Isolasi kegagalan. Egress yang salah konfigurasi tidak lagi merusak situs publik. DDoS terhadap situs publik tidak lagi menguras bandwidth egress.
5. Model mental yang lebih jelas. Setiap mesin memiliki satu tugas. Insinyur beralasan tentang masalah ingress tanpa memikirkan egress, & sebaliknya.
Dua Sumbu, Dua Keputusan Penyesuaian Ukuran
Skalabilitas Independen
Sebelum pemisahan, pertumbuhan ke arah mana pun membebani mesin yang sama. Setelah pemisahan, setiap arah memiliki provisioning-nya sendiri.
Penentuan ukuran Ingress: berskala sesuai jumlah pengguna. Keputusan kapasitas berada di lapisan yang menghadap publik (lebih banyak replika reverse proxy, VM yang lebih besar, CDN di depan). Anggaran bandwidth dihitung berdasarkan lalu lintas pengguna pada saat puncak.
Penentuan ukuran Egress: berskala sesuai volume panggilan dari layanan internal ke API eksternal. Sering kali didominasi oleh pengiriman webhook, panggilan ke pemroses pembayaran, atau pengambilan data pihak ketiga. Anggaran bandwidth dihitung berdasarkan pola panggilan internal.
Isolasi kegagalan: DDoS terhadap ingress publik tidak lagi menghabiskan bandwidth egress (panggilan ke pemroses pembayaran tetap berjalan). Keruntuhan proxy egress tidak lagi menjatuhkan situs publik (pengguna tetap dapat mengakses situs; hanya panggilan keluar internal yang gagal).
SLO yang Berbeda: ketersediaan ingress penting bagi pengguna (gangguan situs yang terlihat); ketersediaan egress penting bagi operator (kegagalan latar belakang yang mungkin membutuhkan waktu lebih lama untuk terdeteksi). Masing-masing sisi dapat memiliki SLO-nya sendiri.
Beberapa Server Egress
Setelah peran egress menjadi mesin tersendiri, langkah selanjutnya yang jelas adalah menjalankan beberapa mesin egress di belakang load balancer untuk HA. Setiap layanan internal baru menunjuk ke hostname egress (yang teresolusi ke pool yang di-load-balance) alih-alih ke satu IP tunggal.
Prinsipnya sama dengan sistem terdistribusi lainnya: begitu sebuah tier menjadi stateless & memiliki perannya sendiri, ia dapat diperbanyak dengan biaya yang murah.
Integrasi Mitra Baru
Organisasi Anda menjalankan pemisahan ingress / egress sesuai desain. Server egress memiliki IP publik tetap (203.0.113.99) yang telah Anda daftarkan dalam allowlist untuk tiga API mitra yang ada (pemroses pembayaran, gerbang SMS, dan penyedia email).
Tim produk ingin menambahkan integrasi keempat: sistem pengiriman webhook yang memanggil kembali ke endpoint pelanggan di seluruh dunia. Perkiraan volume: 10.000 panggilan per menit, dengan lonjakan hingga 30.000.
Merancang Batas Jaringan untuk Layanan yang Bertumbuh
Sintesis
Anda telah mempelajari mengapa ingress & egress membutuhkan alat yang berbeda, kegagalan hairpin NAT yang memaksa pemisahan di armada nyata, & bagaimana skalabilitas independen, isolasi keamanan, & isolasi kegagalan tercapai setelah pemisahan tersebut diterapkan.
Terapkan keempatnya.
Perusahaan SaaS menengah menjalankan tiga subdomain produk (app, api, admin) untuk pengguna mereka, ditambah empat integrasi outbound (Stripe, Twilio, SendGrid, sistem webhook pelanggan). Saat ini, semuanya berada di belakang satu mesin proxy dengan satu IP publik. Mereka mulai menerima laporan tentang kegagalan hairpin yang tidak konsisten ketika layanan internal mencoba memanggil api.example.com. Mereka ingin merancang perbaikan permanen.
Ke Mana Kursus Ini Berlanjut
Ke Mana Kursus Ini Berlanjut
Anda baru saja melihat salah satu refactoring pemisahan-prihatin (separation-of-concerns) yang paling bersih dalam sistem terdistribusi: satu kotak menjadi dua, masing-masing dengan peran yang jelas, & sistem mewarisi manfaat penskalaan, keamanan, & isolasi kegagalan di sepanjang jalan.
Pelajaran berikutnya (cs_distsys_failure_modes_and_blast_radius) memperluas penalaran isolasi kegagalan. Anda akan membaca postmortem DNS-SERVFAIL yang telah disanitasi, mengidentifikasi pola kegagalan berantai, & menulis item tindakan tanpa menyalahkan yang menargetkan sistem, bukan orang.
Pelajaran pendamping: geometry_of_ingress_egress_separation membingkai ulang pemisahan tersebut sebagai graf bipartit & mengeksplorasi simpang pemotong, partisi jaringan, & apa yang diajarkan teori graf tentang batas jaringan.
Bagus. Lanjutkan.