Topik wawancara representatif

Wawancara Desain Sistem: Menangani Cache Controller Kubernetes yang Usang

Desain sistemSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Controller Kubernetes dapat bertindak berdasarkan data cache yang usang setelah mengalami kelebihan beban (overload) atau restart. Rancang deteksi, perilaku skip-and-requeue, dan observabilitas tanpa memblokir keseluruhan controller.

Petunjuk dan konteks

Sebuah controller Kubernetes membaca objek dari cache Informer dan menulis state yang diinginkan ke API server. Di bawah beban tinggi, keterlambatan watch, atau restart, cache dapat tertinggal di belakang API server; controller dapat mengulangi penulisan, melakukan penskalaan yang salah, atau menganggap Lease lama telah kedaluwarsa. Rancang deteksi keusangan (staleness) dan mitigasi yang hanya memblokir objek yang terpengaruh.

Hal ini relevan untuk peran platform engineering, SRE, dan pengembang cloud-native controller. Kubernetes v1.36 dan KEP 5647 menjelaskan AtomicFIFO, LastStoreSyncResourceVersion(), pelacakan resource version dari operasi tulis, melewati dan memasukkan kembali kunci yang usang ke antrean (skipping and re-queuing), serta integrasi controller DaemonSet, StatefulSet, ReplicaSet, dan Job. Ini adalah latihan desain sumber terbuka, bukan klaim tentang bank soal wawancara perusahaan mana pun.

Apa yang dievaluasi oleh pewawancara

Pewawancara ingin melihat apakah Anda memahami batasan cache yang berprinsip konsistensi akhir (eventually consistent) dan dapat mengubah konsep "cukup baru" menjadi kondisi resource-version yang dapat diuji. Jawaban yang kuat mencakup sinkronisasi cache, read-after-write, antrean per-kunci, backoff, restart, pemantauan, dan feature gates. Jawaban yang lemah membuat setiap panggilan rekonsiliasi membaca langsung ke API server serta mengabaikan beban dan biaya konsistensi.

Pertanyaan klarifikasi

  • Keputusan mana yang bersifat destruktif: menghapus Pod, menurunkan skala (scale down), pergantian leader, atau pembaruan status biasa?
  • Berapa batas jendela keusangan yang dapat diterima, dan bisakah operasi penting melakukan satu kali pembacaan ke API server?
  • Apakah kita memerlukan read-after-write untuk satu objek atau urutan kausal (causal ordering) di beberapa objek?
  • Setelah restart, penyambungan ulang watch, atau kegagalan API server, haruskah controller menunggu secara konservatif atau mengizinkan penurunan performa yang terbatas (bounded degradation)?

Jawaban 30 detik

“Saya akan mempertahankan cache Informer sebagai jalur baca default dan menggunakan AtomicFIFO beserta resource version teramati terbaru untuk mengukur progres. Setelah menulis objek penting, controller mencatat versi targetnya; hingga cache mengejar ketertinggalan, controller hanya melewati kunci tersebut dan memasukkannya kembali ke antrean dengan exponential backoff. Tindakan destruktif menambahkan pembacaan langsung yang dibatasi atau circuit breaker. Metrik mengekspos latensi cache, rekonsiliasi yang dilewati, dan usia antrean. Saat restart, pertahankan proteksi, selesaikan sinkronisasi cache, lalu lanjutkan.”

Solusi langkah demi langkah

Definisikan keusangan terlebih dahulu. Store Informer diisi oleh event watch yang dapat tertunda, mengalami perubahan urutan, atau tidak lengkap untuk sementara waktu saat cache dibangun ulang. AtomicFIFO pada Kubernetes v1.36 membuat batch daftar awal bersifat atomik terhadap event inkremental, menghindari inkonsistensi cache akibat tumpang tindih proses. LastStoreSyncResourceVersion() mengekspos versi terbaru yang diamati oleh Store.

Untuk setiap penulisan penting, pertahankan objectKey -> resourceVersion. Saat DaemonSet memperbarui Pod, catat versi yang dikembalikan oleh API server. Setiap event pod informer memajukan versi tertinggi yang diamati. DaemonSet hanya dapat menjalankan rekonsiliasi berikutnya yang bergantung pada state baru ketika versi yang diamati telah mencapai penulisan terakhir. Jika tidak, masukkan kembali kunci tersebut ke antrean dengan exponential backoff normal; jangan pernah menghentikan seluruh worker pool.

Penulisan dan pemeriksaan harus bersifat idempoten. Gunakan percobaan ulang saat konflik resource-version, dan pastikan rekonsiliasi yang berulang tidak menimbulkan efek samping tambahan. Restart menyebabkan pemetaan dalam memori hilang, sehingga proses startup menunggu sinkronisasi cache informer sebelum membangun kembali state yang dilindungi dari status objek atau event antrean. Jika pemetaan belum lengkap, tunda pekerjaan destruktif daripada berasumsi data sudah baru.

Untuk keputusan yang sensitif terhadap waktu, tambahkan circuit breaker. Gunakan cache untuk jalur cepat; ketika versi target tidak diketahui atau jeda melebihi ambang batas, lakukan satu pembacaan langsung yang dibatasi dari API server. Jika gagal, jeda hanya kunci tersebut dan catat alasannya. Menjadikan pembacaan langsung sebagai default akan melipatgandakan QPS API server, latensi, dan radius dampak kegagalan.

Ekspos resource version informer, target versi tulis, durasi keterlambatan, jumlah rekonsiliasi yang dilewati, usia antrean, tingkat keberhasilan pembacaan langsung, dan jumlah circuit breaker per controller. Log mencakup kunci objek, versi, dan tindakan, tanpa pernah mencantumkan nilai Secret. Peringatan membedakan kelambatan API server, watch yang terputus, kunci yang sering diakses (hot key), dan pemrosesan controller yang lambat.

Rilis di balik feature gate dan uji coba canary. Aktifkan untuk satu controller dengan tingkat kontensi tinggi dan kumpulan node kecil, lalu verifikasi konvergensi setelah proses lewati (skip), pemulihan restart, dan tidak adanya kelaparan antrean (queue starvation). Perluas peluncuran hanya setelah beban API server dapat diterima. Lakukan rollback dengan menonaktifkan jalur konsistensi baru sambil mempertahankan metrik dan status objek; jangan menghapus pemetaan proteksi secara massal.

Contoh jawaban

Saya akan menerapkan empat lapisan: pembacaan mengutamakan cache, gerbang resource-version, antrean ulang per-kunci, dan circuit breaker untuk tindakan penting. AtomicFIFO menjaga pemrosesan daftar awal tetap konsisten dengan event inkremental, dan Store melaporkan resource version teramati terbaru. Setelah operasi tulis, controller mencatat versi target; controller hanya memproses kunci tersebut setelah cache mencapainya, jika tidak, kunci akan dimasukkan kembali ke antrean dengan backoff.

Penghapusan, penurunan skala, dan keputusan Lease menggunakan pembacaan langsung yang dibatasi ketika kebaruan cache tidak diketahui atau berada di atas ambang batas; kegagalan akan menjeda kunci tersebut. Metrik mencakup keterlambatan versi, pekerjaan yang dilewati, usia antrean, dan rasio pembacaan langsung. Restart menunggu sinkronisasi cache sebelum memulihkan pemetaan. Penerapan canary memvalidasi konvergensi, pemulihan, dan beban API server; status proteksi tidak pernah dihapus secara global.

Kesalahan umum

  • Kesalahan → melakukan pembacaan langsung ke API server pada setiap rekonsiliasi; Alasan gagal → QPS dan latensi meningkat serta cache kehilangan tujuannya; Solusi → lakukan pembacaan langsung hanya untuk tindakan penting atau versi yang tidak diketahui.
  • Kesalahan → menjeda seluruh worker ketika satu objek usang; Alasan gagal → satu kunci yang bermasalah menyebabkan gangguan global; Solusi → lewati dan masukkan kembali ke antrean berdasarkan kunci objek.
  • Kesalahan → hanya membandingkan timestamp lokal; Alasan gagal → pergeseran waktu (clock drift) tidak dapat membuktikan kausalitas watch; Solusi → bandingkan resource version API.
  • Kesalahan → menghapus semua proteksi setelah restart; Alasan gagal → keputusan dapat dijalankan saat cache sedang dibangun kembali; Solusi → tunggu sinkronisasi dan pulihkan state dengan pemeriksaan versi.

Pertanyaan lanjutan

Mengapa resource version lebih aman daripada timestamp lokal?

Resource version berasal dari urutan perubahan objek pada API server dan dapat membuktikan bahwa cache telah mengamati penulisan tertentu. Waktu lokal dipengaruhi oleh clock drift, keterlambatan jaringan, dan jeda proses. Resource version bukan merupakan urutan transaksi lintas objek, sehingga konsistensi multi-objek tetap memerlukan desain eksplisit.

Bagaimana cara menghindari starvation ketika satu kunci terus-menerus usang?

Batasi exponential backoff dan berikan peringatan pada batas waktu tunggu maksimum sambil membiarkan kunci lain tetap berjalan. Setelah ambang batas terlampaui, beralihlah ke pemeriksaan berfrekuensi rendah atau satu kali pembacaan langsung. Hitung jumlah lewati berurutan agar percobaan ulang yang cepat tidak membebani API server.

Kapan suatu operasi harus ditolak?

Untuk keputusan penghapusan, penurunan skala, failover, atau kedaluwarsa Lease, jeda kunci dan pertahankan proteksi saat kebaruan data tidak diketahui dan pembacaan langsung gagal. Pelaporan status biasa dapat berlanjut dalam jendela keusangan yang ditentukan secara eksplisit, tetapi harus menandai status terdegradasi pada status dan metrik.

Sumber publik

Pertanyaan terkait

Alat wawancara terkait

Gunakan Jawab untuk jawaban desain sistem

Perjelas persyaratan terlebih dahulu, lalu lanjutkan dengan skala, arsitektur, pilihan komponen, dan trade-off.

Lihat alat