Kegagalan memulai OpenVPN sering datang sebagai keluhan sumber daya plus saran bermaksud baik untuk menaikkan sebuah batas, dan saran itu hanya berhasil sekitar separuh kasus. Di balik kegagalan itu ada dua penghitung yang tidak saling terkait. Yang satu adalah batas kernel pada jumlah tugas yang dimiliki sebuah ID pengguna nyata, dan batas itu diwarisi saat proses dijalankan. Yang lain adalah anggaran cgroup yang diterapkan manajer layanan pada satu unit dan semua yang di-fork-nya. Membaca nilai efektif masing-masing, untuk unit yang benar-benar berjalan, lebih murah daripada menebak.

Dua penghitung, dua pertanyaan

LimitNPROC adalah RLIMIT_NPROC di bawah nama systemd, dan satuan akuntansinya adalah ID pengguna nyata. Setiap proses milik pengguna itu dihitung terhadap total yang sama, termasuk pekerjaan yang dimulai unit lain, sesi login, atau tugas penjadwal. Karena itu batas ini bukan plafon per layanan meskipun disetel di dalam unit layanan, dan layanan yang mem-fork pembantu untuk tiap klien bersaing dengan semua hal lain yang berjalan di bawah akun tersebut. Tugas cron yang sibuk di bawah pengguna yang sama dapat mendorong unit VPN melewati garis yang tidak pernah ia lewati sendiri.

TasksMax punya pemilik lain: pengendali pids pada cgroup unit, yang menghitung tugas alih-alih proses. Thread adalah tugas, jadi daemon yang tampak satu-thread tetapi punya kumpulan pekerja dapat menghabiskan anggaran yang sekilas tampak jauh lebih besar daripada jumlah prosesnya. EffectiveTasksMax melaporkan apa yang sebenarnya diizinkan hierarki cgroup setelah slice induk angkat bicara.

Mengapa pengecualian root mengubah jawabannya

Kernel tidak menerapkan RLIMIT_NPROC pada proses yang membawa CAP_SYS_RESOURCE atau CAP_SYS_ADMIN, karena itu unit yang berjalan sebagai root tanpa melepaskan hak istimewa praktis tidak dibatasi oleh setelan tersebut. Pengecualian tunggal ini menjelaskan nasihat berlawanan yang saling dipertukarkan orang: menaikkan LimitNPROC memperbaiki penerapan yang melepas hak istimewa dan tidak melakukan apa pun bagi yang tetap berhak istimewa. Periksa User= dan apakah daemon mengganti identitas setelah start sebelum menyalahkan atau memuji setelan itu. Unit berhak istimewa yang kemudian beralih ke akun tanpa hak istimewa kembali jatuh di bawah batas pada saat peralihan, yang membuat garis waktu kegagalan juga layak dibaca.

Tahap kegagalan mempersempitnya lebih jauh. Penolakan saat persiapan eksekusi, kesalahan fork yang dilaporkan daemon sendiri, dan pembuatan tugas yang ditolak di dalam cgroup menghasilkan baris journal berbeda, dan hanya satu di antaranya dijawab oleh anggaran yang lebih besar.

Baca nilai efektif, bukan nilai shell

ulimit -u pada shell interaktif menjelaskan shell itu. Ia tidak menjelaskan apa yang diteruskan manajer layanan ke daemon, dan tidak mengatakan apa pun tentang akuntansi cgroup. Tanyakan unitnya saja, memakai nama instans yang ada di host dan bukan contoh dari panduan.

systemctl show [email protected] -p User -p LimitNPROC -p TasksCurrent -p TasksMax -p EffectiveTasksMax
cat /proc/$(systemctl show -p MainPID --value [email protected])/limits | grep -i processes

Di dalam kontainer jawabannya butuh dua pembacaan lagi, karena nilai internal infinity hanya menjelaskan pandangan tamu. Mintalah plafon pids milik kontainer kepada pemilik host, dan pastikan apakah manajer layanan internal dapat mendelegasikan pengendali itu sama sekali. Unit bersarang tidak dapat memegang anggaran yang tidak pernah diberikan cgroup induknya.

Ukur perbaikan dan buktikan di bawah beban

Ambil angka dari beban kerja, bukan dari teks kesalahan. Hitung proses yang dijalankan daemon per klien terhubung atau per pemanggilan pembantu, kalikan dengan konkurensi yang diperkirakan ditanggung penerapan, tambahkan margin untuk sesi administratif, lalu bandingkan angka itu dengan dua nilai efektif. Penimpaan drop-in lokal menjaga perubahan tetap dapat ditinjau dan bertahan melewati peningkatan paket, sedangkan menyunting berkas unit yang dikirim menyembunyikan perubahan sampai pembaruan berikutnya menggantikannya. Tuliskan aritmetikanya di samping penimpaan, karena orang berikutnya yang menaikkan atau menurunkannya membutuhkan asumsinya, bukan angka akhirnya.

Perubahan anggaran diterapkan saat eksekusi, jadi memuat ulang saja tidak mengubah ukuran proses yang sudah berjalan. Mulai ulang unit lewat daur hidup normalnya, terima gangguan sesi, lalu baca penghitungnya lagi pada instans baru.

sudo systemctl daemon-reload
sudo systemctl restart [email protected]
systemctl show [email protected] -p TasksCurrent -p EffectiveTasksMax
sudo journalctl -u [email protected] -b --no-pager | tail -n 20

Yang membuktikan perbaikan adalah unit yang dimulai ulang dengan jumlah tugas di bawah kedua plafon sambil memikul beban yang dimaksud, ditambah journal yang tidak lagi melaporkan kehabisan tugas atau fork pada tahap yang sama. Simpan angka sebelum dan sesudah bersama perubahan agar penyelidikan berikutnya mulai dari pengukuran, bukan dari nasihat yang sama. Jika jumlahnya masih mencapai plafon, aritmetikanya yang salah, bukan batasnya kebetulan terlalu kecil, dan perbedaan itu layak diketahui sebelum mulai ulang berikutnya.

Artikel terkait