Konteks dan cakupan
Sebuah layanan HTTP berjalan dalam sebuah Deployment. Setelah sebuah Pod dihapus, beberapa permintaan masih mencapai instans lama, sementara long polling dan background job terputus. Jelaskan lini masa terminasi di seluruh Kubernetes, Service, load balancer, dan proses, lalu rancang draining, pembatalan, percobaan ulang (retry), dan verifikasi. Keahlian intinya adalah membatasi koneksi dan efek samping selama proses shutdown, sehingga topik ini termasuk dalam backend.
Hal yang dievaluasi pewawancara
Jawaban yang kuat membedakan penghapusan Pod, pembaruan EndpointSlice, propagasi load balancer, preStop, SIGTERM, dan SIGKILL. Menerima SIGTERM bukan berarti lalu lintas telah berhenti. Cakup koneksi berumur panjang, antrean job, retry yang idempoten, hilangnya daya node secara tiba-tiba, dan masa tenggang (grace period) yang tidak memadai.
Pertanyaan klarifikasi di awal
- Apakah layanannya berupa short request, SSE, WebSocket, atau long polling? Bisakah koneksi dimigrasikan?
- Apa yang diperiksa oleh probe readiness, liveness, dan startup, dan apakah aplikasi mengekspos status drain?
- Apakah preStop berupa sleep, HTTP hook, atau endpoint drain aplikasi? Siapa yang melakukan proses keluar (exit) akhir?
- Apakah Pod menjalankan worker, dan bagaimana lease serta pengiriman duplikat ditangani?
- Berapa latensi propagasi dari ingress load balancer, service mesh, dan cloud LB?
Kerangka jawaban 30 detik
“Pertama, tandai aplikasi sebagai not-ready dan berhenti menerima pekerjaan baru, lalu tunggu propagasi endpoint dan load balancer. Masuk ke tahap draining: selesaikan short request, tutup atau migrasikan koneksi berumur panjang, dan hentikan worker agar tidak mengambil job baru sambil melepaskan lease yang tidak dapat mereka selesaikan. preStop hanyalah jendela koordinasi; SIGTERM bertugas melakukan pembersihan (cleanup). Masa tenggang harus mencakup p99 propagasi, draining, dan cleanup, dengan SIGKILL hanya dikirim setelah masa tersebut habis. Uji rilis dengan metrik koneksi dan job untuk membuktikan tidak ada permintaan yang hilang atau efek samping duplikat.”
Solusi langkah demi langkah
Gambarkan lini masanya: controller menghapus Pod, kubelet memulai terminasi, EndpointSlice dan load balancer menghapus endpoint secara asinkron, dan kontainer dapat menjalankan preStop sebelum SIGTERM. Karena propagasi bersifat asinkron, aplikasi harus menolak pekerjaan baru segera setelah mengetahui statusnya sedang draining, bahkan jika lalu lintas masih tiba di alamat lama.
Pisahkan status ready dan draining. Jalur shutdown menyetel status draining, menggagalkan readiness, dan berhenti menerima koneksi baru atau mengembalikan respons yang dapat dicoba ulang (retryable). Short request yang ada diselesaikan. SSE, WebSocket, dan long polling harus menerima sinyal penutupan, cursor, atau token pelanjutan agar klien dapat terhubung kembali dengan aman.
Sleep pada preStop tidak dapat menggantikan logika aplikasi. Hal itu hanya memberi waktu untuk propagasi dan menghabiskan masa tenggang. Lebih disukai endpoint drain aplikasi yang mencatat waktu mulai dan sisa kuota waktu; handler SIGTERM menghentikan pekerjaan baru, menutup listener, menunggu permintaan aktif, dan melepaskan connection pool.
Rancang draining worker secara terpisah dari draining HTTP. Berhenti mengambil pesan baru. Lindungi job aktif dengan lease atau visibility timeout, dan lepaskan job tersebut ketika sisa waktu tidak mencukupi sehingga worker lain dapat mencoba lagi. Penulisan job dan efek samping eksternal memerlukan kunci idempotensi; Pod yang dimatikan paksa tidak boleh menagih biaya atau mengirim barang dua kali.
Pilih terminationGracePeriodSeconds dari nilai p99 yang terukur: propagasi ingress, permintaan terlama yang diizinkan, penutupan koneksi, cleanup worker, dan pembersihan log (log flushing), ditambah margin jitter. Setelah batas waktu berakhir, kubelet dapat memaksa penghentian; permintaan yang belum selesai dan state dalam proses tidak dapat bergantung pada eksekusi finally.
Pemeliharaan node berbeda dari penghapusan Pod. Graceful node shutdown di Kubernetes memberi kubelet dan Pod jendela waktu yang terencana, tetapi kehilangan daya, kernel panic, dan restart host secara paksa tidak memberikannya. Job-job kritis memerlukan checkpoint yang tahan lama, beberapa replika, dan pemulihan berbasis antrean.
Verifikasi rolling release, penghapusan manual, node drain, lambatnya propagasi LB, koneksi berdurasi panjang, dan timeout setelah SIGTERM. Periksa 5xx, pemutusan koneksi, tingkat penyelesaian, penolakan saat draining, retry job, efek duplikat, keterlambatan penghapusan endpoint, dan pematian Pod secara paksa, yang semuanya dikorelasikan dengan versi rilis.
Contoh jawaban berkualitas tinggi
“Saya tidak akan menganggap preStop: sleep 30 sebagai graceful shutdown. Saat menerima sinyal shutdown, aplikasi menandai dirinya sedang draining, menggagalkan readiness, dan berhenti menerima pekerjaan baru. Pembaruan endpoint dan LB merambat secara asinkron, sehingga instans lama tetap menolak permintaan baru. Short request diselesaikan; koneksi SSE dan WebSocket menerima token penutupan atau pelanjutan; worker berhenti mengambil job dan melepaskan lease yang tidak dapat mereka selesaikan.
preStop hanya memberi waktu untuk propagasi. Handler SIGTERM menutup listener, menunggu permintaan aktif, melepaskan pool, dan keluar sebelum batas waktu habis. Saya menentukan masa tenggang berdasarkan p99 propagasi yang terukur, permintaan terlama, cleanup worker, dan log flushing. Pengujian mencakup rolling release, node drain, koneksi lama, crash, dan force kill, dengan memastikan tidak ada permintaan yang hilang, efek samping duplikat, atau job yang tidak pulih.”
Kesalahan umum
- Hanya menunggu SIGTERM → lalu lintas yang terpropagasi masih mencapai Pod lama → gagalkan readiness dan masuk ke tahap draining terlebih dahulu.
- Menggunakan sleep statis alih-alih draining → perubahan propagasi atau durasi permintaan akan merusaknya → kendalikan logika berdasarkan sisa batas waktu.
- Menghentikan Pod tetapi tetap mengambil antrean job → pematian paksa menduplikasi pekerjaan → berhenti mengambil job dan lepaskan lease.
- Memperlakukan koneksi lama seperti permintaan biasa → klien tidak dapat melanjutkan sesi → kirim sinyal penutupan dan cursor.
- Menentukan masa tenggang dari latensi rata-rata → permintaan p99 terkena SIGKILL → ukur tail latency dan propagasi.
- Mengasumsikan
finallyselalu berjalan → force kill dan kehilangan daya melewati proses pembersihan → simpan (persist) state kritis. - Hanya memantau status Pod → melewatkan lambatnya propagasi LB dan pemutusan koneksi → korelasikan endpoint, permintaan, dan metrik rilis.
- Menggagalkan liveness saat draining → memicu badai restart (restart storm) → readiness berarti kelayakan menerima lalu lintas; liveness berarti kesehatan proses.
Pertanyaan lanjutan dan jawabannya
Pertanyaan lanjutan 1: Mengapa permintaan masih bisa datang setelah readiness gagal?
Pembaruan endpoint, service mesh, dan cloud load balancer merambat dengan jeda waktu, dan koneksi yang ada tidak dimigrasikan secara otomatis. Aplikasi yang sedang draining harus menolak pekerjaan baru dan menutup koneksi yang ada dengan aman.
Pertanyaan lanjutan 2: Berapa lama waktu sleep pada preStop?
Jangan menebak. Ukur p99 propagasi endpoint dan LB, gabungkan dengan alokasi waktu permintaan dan cleanup worker, serta perlakukan sleep sebagai jendela koordinasi yang terikat waktu.
Pertanyaan lanjutan 3: Bagaimana cara menutup WebSocket secara graceful?
Berhenti menerima koneksi baru dan kirim kode penutupan (close code) beserta panduan penyambungan kembali. Biarkan klien melanjutkan sesi dengan session ID atau cursor, dan simpan state yang cukup untuk menghindari pengulangan efek samping.
Pertanyaan lanjutan 4: Bagaimana jika Pod mati di tengah-tengah pemrosesan job?
Simpan state job dan lease. Worker baru akan mengambilnya setelah visibility timeout; kunci idempotensi atau kueri status melindungi dari efek samping eksternal. Jangan bergantung pada finally dalam proses.
Pertanyaan lanjutan 5: Bisakah kehilangan daya node berlangsung secara graceful?
Tidak dapat diandalkan secara konsisten. Penanganan shutdown node yang terencana mencakup alur pemeliharaan yang teramati; kehilangan daya dan crash pada kernel memerlukan replika, checkpoint persisten, dan job yang dapat dicoba ulang.
Pertanyaan lanjutan 6: Bagaimana cara menentukan masa tenggang?
Jumlahkan propagasi endpoint, permintaan maksimum, penutupan koneksi lama, pelepasan lease, pembersihan koneksi, dan log flush, lalu validasi dengan nilai p99 terukur serta margin tambahan, bukan menggunakan nilai rata-rata.
Pertanyaan lanjutan 7: Bagaimana cara menghindari restart storm saat draining?
Gagalkan readiness sambil menjaga liveness tetap sehat. Pisahkan tanggung jawab probe agar kondisi “sementara tidak menerima lalu lintas” tidak disalahartikan sebagai proses yang crash.