Bagaimana Kami Membuat Deploy Turun ke Nol Error 502
Setiap kali kami men-deploy backend Mythex, sejumlah kecil permintaan gagal dengan 502 Bad Gateway. Tidak banyak, tetapi 502 selama deploy berarti klik seseorang tidak berbuat apa-apa, atau build yang sedang ditontonnya tersendat sejenak. Kami melacaknya ke dua masalah terpisah: watchdog self-healing yang berkelahi dengan deploy kami, dan celah antara saat server berhenti mendengarkan dan saat load balancer berhenti mengirim lalu lintas kepadanya. Dalam tiga deploy produksi berturut-turut setelah perbaikan, jumlahnya turun dari 10 ke 6 lalu ke 0.
Susunannya
API dan orkestrator kami berjalan sebagai container di sekelompok kecil server di belakang Application Load Balancer (ALB) AWS. Sebuah deploy memperbarui satu server pada satu waktu: ia mengeringkan container lama, menjalankan yang baru, lalu pindah ke server berikutnya. Watchdog di setiap server memeriksa bahwa container berjalan dan me-restart apa pun yang tidak berjalan. Tujuannya agar proses yang crash pukul 3 pagi kembali tanpa ada orang yang harus bangun.
Keduanya masuk akal jika berdiri sendiri. Bersama-sama, tidak.
Masalah 1: watchdog berlomba dengan deploy
Watchdog berjalan sekali setiap menit dan “menyembuhkan” setelah satu health check yang gagal. Deploy sengaja mengeringkan layanan selama hingga 150 detik, dan selama itu health check seharusnya gagal. Jadi watchdog terpicu selama setiap deploy.
Sebagian besar waktu ia kalah dalam perlombaan tanpa membahayakan. Sekali, ia menang: ia menulis ulang compose file (deskripsi container mana yang seharusnya berjalan) di tengah deploy, dan meninggalkan server tanpa container gateway sama sekali, sementara job deploy melaporkan sukses.
Perbaikannya:
- Satu kunci. Deploy sekarang mengambil kunci file yang sama dengan skrip bootstrap server, sehingga watchdog dan deploy tidak pernah berjalan bersamaan.
- Empat kali gagal, bukan sekali. Watchdog butuh empat health check gagal berturut-turut sebelum bertindak. Layanan yang sedang dikeringkan tidak lagi terlihat mati.
- Satu definisi. Compose file sekarang hanya punya satu sumber, yang dipublikasikan ke server, alih-alih salinan yang bisa tidak sinkron.
- Verifikasi, jangan percaya begitu saja. Job deploy tidak lagi lulus hanya karena sebuah perintah mengembalikan hasil. Ia memeriksa API, orkestrator, gateway, dan publish worker di setiap server sebelum bisa dianggap sukses.
Masalah 2: server pergi sebelum lalu lintasnya
Masalah kedua lebih senyap. Saat deploy mengeringkan sebuah server, server itu mulai menjawab endpoint health-nya dengan 503 agar load balancer mengeluarkannya dari rotasi. Server kami melakukan itu selama 5 detik, lalu mati.
Tetapi ALB hanya memeriksa kesehatan sesekali, dan butuh beberapa pemeriksaan gagal berturut-turut sebelum berhenti mengarahkan lalu lintas ke sebuah target, hingga sekitar 60 detik dari awal sampai akhir. Jadi selama sekitar 55 detik, load balancer terus mengirim permintaan sungguhan ke server yang sudah berhenti mendengarkan. Itulah 502 kami.
Perbaikannya adalah membuat kedua linimasa itu selaras:
- Target group sekarang memeriksa setiap 5 detik dan menandai target tidak sehat setelah 2 kegagalan, sekitar 10 detik untuk menyadarinya.
- Proses pengeringan tetap melayani lalu lintas sungguhan selama 15 detik setelah mulai gagal di health check, sehingga selalu ada tumpang-tindih.
- Pengaturan ini tinggal di skrip yang menyediakan infrastruktur, bukan di konsol yang pernah diklik seseorang sekali.
Menjaga angka-angkanya saling cocok
Timeout seperti ini saling bergantung. Pengeringan harus lebih lama daripada waktu yang dibutuhkan balancer untuk menyadari; pengeringan ditambah shutdown harus selesai sebelum container dihentikan paksa. Mudah bagi seseorang untuk mengubah satu angka enam bulan kemudian dan diam-diam memunculkan kembali bug itu.
Jadi kami menuliskan hubungan-hubungan itu sebagai tes: pengeringan harus lebih lama daripada interval health check dikali ambang kegagalan; waktu untuk dianggap sehat kembali harus tetap singkat; seluruh pengeringan harus muat di dalam stop grace period container. Ubah satu angka tanpa yang lain dan CI gagal. Kami juga melakukan mutation test terhadap tes itu sendiri: mengubah setiap angka ke nilai yang salah dan memeriksa apakah sebuah tes menangkapnya.
Mengukur deploy itu mudah salah
Hasil ukur pertama kami mengatakan deploy yang bersih sekitar 3% rusak. Itu tidak benar. Kami menghitung setiap respons non-200, dan 503 dari endpoint health selama pengeringan bukan kegagalan; itu adalah pengeringan yang menjalankan tugasnya, memberi tahu balancer agar tidak memilih server itu sambil tetap melayani permintaan sungguhan.
Yang dirasakan pengguna adalah 502: permintaan tidak mencapai apa pun. Hanya menghitung itu yang memberi gambaran nyata: 10, lalu 6, lalu 0 di tiga deploy produksi.
Yang kami ambil dari ini
- Penyembuhan mandiri perlu tahu tentang downtime yang direncanakan. Watchdog yang tidak bisa membedakan deploy dari crash pada akhirnya akan berkelahi dengan deploy.
- Pengeringan adalah jabat tangan. Server harus terus melayani sampai load balancer terbukti berhenti mengirim lalu lintas, dan waktu itu diatur di balancer, bukan di server.
- Kodekan invarian sebagai tes. Angka operasional akan bergeser. Tes yang menghubungkannya satu sama lain tidak.
- Putuskan apa yang diukur sebelum mengukur. “Error” adalah metrik yang salah; “permintaan yang tidak mencapai apa pun” adalah metrik yang benar.
Jika Anda mempublikasikan aplikasi di Mythex, tidak satu pun dari ini terlihat oleh Anda, dan itulah intinya. Terkait: bagaimana aplikasi yang dipublikasikan tetap online saat Anda mempublikasikannya ulang.