Pertanyaan
Sebuah layanan Go berjalan di dalam Pod Kubernetes pada node dengan 64 CPU logis, sedangkan Pod tersebut memiliki batas CPU sebesar 2.5. Setelah melakukan pembaruan ke Go 1.25, jelaskan nilai default GOMAXPROCS, hubungannya dengan permintaan (requests) CPU, apakah perubahan cgroup diikuti, dan bagaimana Anda memvalidasi latensi ekor (tail latency), throughput, serta perilaku GC. Sebutkan apa yang dinonaktifkan oleh pengaturan manual GOMAXPROCS atau GODEBUG.
Apa yang sedang diuji oleh pewawancara
Hal ini menguji konkurensi runtime, semantik sumber daya kontainer, dan diagnosis performa. Bedakan antara CPU logis, batas CPU, permintaan CPU, afinitas proses, dan GOMAXPROCS. Go 1.25 membaca batas throughput rata-rata CPU cgroup Linux dan memperbarui nilai default secara berkala, tetapi penimpaan manual menonaktifkan perilaku tersebut. Jawaban "Atur ke 2" tanpa kuota pecahan, latensi lonjakan (burst latency), dan rollback dianggap tidak lengkap.
Pertanyaan klarifikasi
- Versi Go, versi Linux cgroup, dan container runtime apa yang digunakan?
- Apakah Pod menetapkan batas CPU, permintaan CPU, atau keduanya, dan bisakah batas tersebut berubah?
- Apakah sasarannya throughput, latensi P99, jeda GC, atau biaya, dan apakah lonjakan beban diperkirakan terjadi?
- Apakah
GOMAXPROCSsudah diatur oleh variabel lingkungan, startup flag, atau kode?
Kerangka kerja 30 detik
Nilai default diturunkan dari nilai minimum antara CPU logis, afinitas CPU, dan batas throughput rata-rata CPU cgroup; batas pecahan dibulatkan ke atas, dan runtime umumnya tidak akan memilih nilai di bawah 2 kecuali mesin atau afinitas memiliki kurang dari 2 CPU. Permintaan (requests) tidak digunakan. Kemudian bahas urutan prioritas penimpaan, pembaruan, observabilitas, dan rollback.
Desain langkah demi langkah
1. Pahami nilai default
Tanpa nilai lingkungan GOMAXPROCS atau pemanggilan runtime.GOMAXPROCS, Go 1.25 di Linux membaca kuota/periode cgroup CPU sebagai batas throughput rata-rata. Runtime ini juga mempertimbangkan CPU logis dan afinitas proses serta biasanya memilih nilai minimum. Batas CPU 2.5 dibulatkan ke atas menjadi 3. Permintaan (request) adalah jaminan penjadwalan, bukan batas throughput yang kaku, sehingga tidak digunakan untuk nilai default ini.
2. Pembaruan dan prioritas penimpaan
Runtime secara berkala memeriksa jumlah CPU logis, afinitas, dan perubahan kuota cgroup, biasanya tidak lebih dari sekali per detik. Menyetel variabel lingkungan GOMAXPROCS atau memanggil runtime.GOMAXPROCS menonaktifkan pembaruan otomatis; runtime.SetDefaultGOMAXPROCS() memulihkan nilai default runtime. GODEBUG=containermaxprocs=0 mengabaikan batas cgroup, sedangkan updatemaxprocs=0 menonaktifkan pembaruan.
3. Kaitkan dengan penjadwalan dan pembatasan (throttling)
GOMAXPROCS membatasi eksekusi simultan kode pengguna Go; ini bukan batas maksimum CPU kontainer dan tidak membatasi thread yang terblokir dalam system call. Nilai yang jauh di atas batas CPU dapat memicu throttling kernel dan lonjakan latensi ekor. Nilai yang terlalu rendah dapat mengurangi throughput dan paralelisme GC. Analisis hal ini dengan batas, permintaan, dan overcommit node Kubernetes.
4. Lakukan instrumentasi dan verifikasi
Catat runtime.GOMAXPROCS(0), runtime.NumCPU(), afinitas, kuota/periode cgroup, dan GODEBUG saat startup. Hubungkan /sched/gomaxprocs:threads, CPU throttling, run queue, P99, fraksi CPU GC, throughput, dan eror. Setelah mengubah batas, verifikasi bahwa GOMAXPROCS mengikutinya alih-alih hanya mengandalkan satu log startup.
5. Jalankan eksperimen beban kerja
Pada versi Go dan data yang sama, bandingkan nilai default, nilai eksplisit, dan versi Go sebelumnya di bawah beban CPU-heavy, I/O-waiting, dan lonjakan permintaan singkat (bursty short-request). Ukur steady state dan lonjakan beban. Panduan Go mencatat bahwa GOMAXPROCS yang lebih rendah dapat mengurangi throttling, sementara beban kerja yang fluktuatif mungkin mengalami latensi lebih tinggi ketika paralelisme dibatasi. Putuskan dengan mempertimbangkan P95/P99 serta biaya.
6. Lakukan peluncuran (roll out) dan rollback
Lakukan canary Go 1.25 dengan batas tetap dan kriteria rilis yang eksplisit. Jika throttling, P99, atau GC mengalami regresi, kembalikan image (roll back) atau gunakan nilai eksplisit yang terjustifikasi secara eksperimental, dengan mendokumentasikan bahwa ini menonaktifkan pembaruan otomatis. Menghapus penimpaan dan memanggil SetDefaultGOMAXPROCS akan memulihkan perhitungan default; verifikasi kembali setelah perubahan kuota.
7. Nyatakan failure mode dan batasan
Jangan memperlakukan permintaan sebagai batas, runtime.NumCPU() sebagai paralelisme yang tersedia, atau cgroup sebagai hal yang universal. Sistem non-Linux, kuota yang tidak ada, pengaturan manual, dan versi Go yang lebih lama memiliki perilaku berbeda. Catat versi Go, GODEBUG, spesifikasi sumber daya, dan pemilik rollback dalam checklist rilis.
Contoh jawaban yang kuat
"Tanpa penimpaan eksplisit, Go 1.25 di Linux membaca kuota/periode cgroup dan mengambil nilai minimum dari batas throughput tersebut, CPU logis, dan afinitas; 2.5 CPU dibulatkan menjadi 3, dan permintaan tidak digunakan. Runtime memeriksa perubahan kuota secara berkala, tetapi nilai lingkungan, runtime.GOMAXPROCS, atau GODEBUG=containermaxprocs=0/updatemaxprocs=0 mengubah perilaku ini. Saya akan mencatat GOMAXPROCS, data cgroup, /sched/gomaxprocs, throttling, P99, throughput, dan GC, kemudian membandingkan nilai default, nilai eksplisit, dan versi lama di bawah beban CPU-heavy dan lonjakan beban. Canary yang melanggar batas metrik akan di-rollback, dan runbook mencatat hilangnya pembaruan otomatis saat melakukan penimpaan."
Failure mode yang umum terjadi
- Mengklaim bahwa Go menggunakan permintaan CPU secara langsung.
- Membulatkan batas tanpa menjelaskan kuota pecahan dan aturan nilai minimum.
- Lupa bahwa nilai lingkungan, pemanggilan kode, dan GODEBUG menonaktifkan pembaruan otomatis.
- Mengukur throughput sambil mengabaikan throttling, P99, GC, dan latensi lonjakan.
- Memperlakukan GOMAXPROCS sebagai batas CPU kontainer atau batas thread system-call.
Arah tindak lanjut
Mengapa 2.5 CPU bisa menjadi 3?
GOMAXPROCS adalah bilangan bulat positif, sehingga runtime membulatkan batas throughput pecahan ke atas untuk memanfaatkan kuota secara penuh.
Mengapa permintaan CPU tidak diikutsertakan?
Permintaan adalah jaminan penjadwalan lunak (soft guarantee) yang dapat dilampaui ketika kapasitas sedang menganggur; ini bukan batas throughput atas yang kaku dan stabil.
Bagaimana Anda memverifikasi pembaruan otomatis?
Ubah kuota cgroup dan pantau log serta /sched/gomaxprocs:threads, sambil memeriksa nilai lingkungan dan pengaturan GODEBUG.
Kapan Anda akan mengaturnya secara manual?
Atur secara manual saat eksperimen menunjukkan bahwa paralelisme tetap diperlukan oleh beban kerja, platform, atau target latensi, dan pertahankan konfigurasi rollback yang eksplisit.
Bagaimana dengan Go 1.24?
Gunakan nilai eksplisit atau pendekatan kompatibilitas yang sadar-cgroup (cgroup-aware) sebagai jembatan, lalu uji kembali batas, afinitas, dan throttling setelah memperbarui ke Go 1.25.
Referensi
Go 1.25 "Release Notes", the Go Blog "Container-aware GOMAXPROCS", dan pkg.go.dev "runtime".