Bagaimana cara menggunakan cgroup untuk membatasi semua proses kecuali daftar putih ke satu CPU?

26

Ada panduan untuk cgroups dari Red Hat yang mungkin agak membantu (tetapi tidak menjawab pertanyaan ini).

Saya tahu cara membatasi proses tertentu untuk CPU tertentu, selama perintah untuk memulai proses itu, dengan:

Pertama, masukkan * berikut ini di /etc/cgconfig.conf:

mount {
  cpuset =  /cgroup/cpuset;
  cpu =     /cgroup/cpu;
  cpuacct = /cgroup/cpuacct;
  memory =  /cgroup/memory;
  devices = /cgroup/devices;
  freezer = /cgroup/freezer;
  net_cls = /cgroup/net_cls;
  blkio =   /cgroup/blkio;
}

group cpu0only {
  cpuset {
    cpuset.cpus = 0;
    cpuset.mems = 0;
  }
}

Dan kemudian memulai suatu proses dan menugaskannya secara khusus untuk cgroup itu dengan menggunakan:

cgexec -g cpuset:cpu0only myprocessname

Saya dapat membatasi semua contoh nama proses tertentu secara otomatis dengan (saya pikir ini benar) dengan memasukkan yang berikut ini /etc/cgrules.conf:

# user:process  controller  destination
*:myprocessname cpuset      cpu0only

Pertanyaan saya adalah: Bagaimana saya bisa melakukan yang sebaliknya ?

Dengan kata lain, Bagaimana saya bisa menetapkan semua proses kecuali untuk set tertentu proses yang masuk daftar putih dan anak-anak mereka ke cgroup terbatas?


Berdasarkan apa yang telah saya pelajari, tetapi belum diuji, saya percaya bahwa solusi parsial adalah:

Tambahkan grup "tidak dibatasi":

group anycpu {
  cpuset {
    cpuset.cpus = 0-31;
    cpuset.mems = 0;  # Not sure about this param but it seems to be required
  }
}

Tetapkan proses saya secara eksplisit ke grup yang tidak dibatasi, dan yang lainnya untuk grup yang dibatasi:

# user:process  controller  destination
*:myprocessname cpuset      anycpu
*               cpuset      cpu0only

Namun, peringatan tentang ini tampaknya (dari membaca dokumen, bukan dari pengujian, sehingga sebutir garam) bahwa anak-anak myprocessnameakan dipindahkan ke kelompok terbatas cpu0only.

Pendekatan alternatif yang mungkin adalah membuat pengguna untuk menjalankan myprocessnamedan memiliki semua proses pengguna itu tidak dibatasi, dan segala sesuatu yang lain dibatasi. Namun, dalam kasus penggunaan aktual saya, proses perlu dijalankan oleh root, dan ada proses lain yang juga harus dijalankan oleh root yang harus dibatasi.

Bagaimana saya bisa melakukan ini dengan cgroup?


Jika ini tidak mungkin dilakukan dengan cgroup (yang saya duga sekarang adalah masalahnya), apakah ide saya tentang solusi parsial benar dan akankah mereka bekerja seperti yang saya pikirkan?

* Penafian: Ini mungkin bukan contoh kode minimal; Saya tidak mengerti semua bagian jadi saya tidak tahu mana yang tidak perlu.

Wildcard
sumber

Jawaban:

30

UPDATE: Perhatikan bahwa jawaban di bawah ini berlaku untuk RHEL 6. Dalam RHEL 7, sebagian besar cgroup dikelola oleh systemd, dan libcgroup sudah ditinggalkan.


Sejak memposting pertanyaan ini, saya telah mempelajari seluruh panduan yang saya tautkan di atas, serta sebagian besar dokumentasi cgroups.txt dan cpusets.txt . Saya sekarang tahu lebih banyak daripada yang saya harapkan untuk belajar tentang cgroup, jadi saya akan menjawab pertanyaan saya sendiri di sini.

Ada beberapa pendekatan yang bisa Anda ambil. Kontak perusahaan kami di Red Hat (Arsitek Teknis) merekomendasikan agar tidak ada pembatasan menyeluruh dari semua proses yang lebih disukai daripada pendekatan yang lebih bersifat deklaratif — hanya membatasi proses yang secara spesifik kami inginkan dibatasi. Alasan untuk ini, menurut pernyataannya pada subjek, adalah bahwa mungkin untuk panggilan sistem untuk bergantung pada kode ruang pengguna (seperti proses LVM) yang jika dibatasi dapat memperlambat sistem ke bawah — kebalikan dari efek yang dimaksudkan. Jadi saya akhirnya membatasi beberapa proses khusus yang disebut dan meninggalkan yang lain sendirian.

Selain itu, saya ingin menyebutkan beberapa data dasar cgroup yang saya lewatkan ketika saya memposting pertanyaan saya.


Cgroup tidak tergantung pada libcgrouppemasangan. Namun, itu adalah seperangkat alat untuk secara otomatis menangani konfigurasi cgroup dan tugas proses untuk cgroup dan bisa sangat membantu.

Saya menemukan bahwa alat libcgroup juga dapat menyesatkan, karena paket libcgroup dibangun di atas nya sendiri set abstraksi dan asumsi tentang penggunaan cgroups, yang sedikit berbeda dari pelaksanaan level kernel sebenarnya cgroups. (Saya bisa memberi contoh tetapi butuh kerja; komentar jika Anda tertarik.)

Oleh karena itu, sebelum menggunakan alat libcgroup (seperti /etc/cgconfig.conf, /etc/cgrules.conf, cgexec, cgcreate, cgclassify, dll) saya sangat merekomendasikan mendapatkan sangat akrab dengan /cgroupfilesystem virtual itu sendiri, dan secara manual menciptakan cgroups, hirarki cgroup (termasuk hirarki dengan beberapa subsistem terpasang, yang libcgroup diam-diam dan abstrak leakily pergi), menugaskan kembali proses untuk cgroup yang berbeda dengan menjalankan echo $the_pid > /cgroup/some_cgroup_hierarchy/a_cgroup_within_that_hierarchy/tasks, dan tugas-tugas lain yang tampaknya ajaib yang libcgroupmelakukan di bawah tenda.


Konsep dasar lain saya yang hilang adalah bahwa jika /cgroupfilesystem virtual terpasang pada sistem Anda sama sekali (atau lebih tepatnya, jika salah satu subsistem cgroup alias "controller" yang dipasang sama sekali), maka setiap proses pada seluruh sistem Anda adalah di sebuah cgroup. Tidak ada yang namanya "beberapa proses dalam cgroup dan beberapa tidak".

Ada apa yang disebut root cgroup untuk hierarki yang diberikan, yang memiliki semua sumber daya sistem untuk subsistem yang dilampirkan. Misalnya hierarki cgroup yang memiliki subsistem cpuset dan blkio terpasang, akan memiliki cgroup root yang akan memiliki semua cpus pada sistem dan semua blkio pada sistem, dan dapat berbagi beberapa sumber daya dengan cgroup anak . Anda tidak dapat membatasi cgroup root karena ia memiliki semua sumber daya sistem Anda, jadi membatasi itu bahkan tidak masuk akal.


Beberapa data sederhana lain yang saya lewatkan tentang libcgroup:

Jika Anda menggunakan /etc/cgconfig.conf, Anda harus memastikan bahwa chkconfig --list cgconfigacara yang cgconfigdiatur untuk dijalankan saat boot sistem.

Jika Anda berubah /etc/cgconfig.conf, Anda harus menjalankan service cgconfig restartuntuk memuat perubahan. (Dan masalah dengan menghentikan layanan atau menjalankan cgclearsangat umum ketika bermain-main pengujian. Untuk debugging saya sarankan, misalnya lsof /cgroup/cpuset, jika cpusetadalah nama hierarki cgroup yang Anda gunakan.)

Jika Anda ingin menggunakan /etc/cgrules.conf, Anda perlu memastikan "daemon mesin cgroup rules" ( cgrulesengd) berjalan: service cgred startdan chkconfig cgred on. (Dan Anda harus mengetahui kondisi ras yang mungkin tetapi tidak mungkin mengenai layanan ini, seperti yang dijelaskan dalam Panduan Manajemen Sumber Daya Red Hat di bagian 2.8.1 di bagian bawah halaman.)

Jika Anda ingin bermain-main secara manual dan mengatur cgroup Anda menggunakan sistem file virtual (yang saya sarankan untuk penggunaan pertama), Anda dapat melakukannya dan kemudian membuat cgconfig.conffile untuk mencerminkan pengaturan Anda dengan menggunakan cgsnapshotberbagai opsi.


Dan akhirnya, informasi penting yang saya lewatkan ketika saya menulis yang berikut ini:

Namun, peringatan tentang ini tampaknya ... bahwa anak-anak dari myprocessname akan dipindahkan ke cpu group hanya cpu0on.

Saya benar, tetapi ada opsi yang tidak saya sadari.

cgexec adalah perintah untuk memulai proses / menjalankan perintah dan menugaskannya ke cgroup.

cgclassify adalah perintah untuk menetapkan proses yang sudah berjalan ke cgroup.

Kedua hal ini juga akan mencegah cgred( cgrulesengd) mengalihkan proses yang ditentukan ke cgroup yang berbeda berdasarkan /etc/cgrules.conf.

Keduanya cgexecdan cgclassifymendukung --stickybendera, yang juga mencegah cgredpenugasan kembali proses anak berdasarkan /etc/cgrules.conf.


Jadi, jawaban atas pertanyaan ketika saya menulisnya (meskipun bukan pengaturan yang akhirnya saya terapkan, karena saran dari Arsitek Teknis Red Hat kami yang disebutkan di atas) adalah:

Buat cpu0onlydan anycpucgroup seperti yang dijelaskan dalam pertanyaan saya. (Pastikan cgconfigdiatur untuk dijalankan saat boot.)

Buat * cpuset cpu0onlyaturan seperti yang dijelaskan dalam pertanyaan saya. (Dan pastikan cgreddiatur untuk dijalankan saat boot.)

Mulai setiap proses saya ingin tidak dibatasi dengan: cgexec -g cpuset:anycpu --sticky myprocessname.

Proses-proses itu akan tidak dibatasi, dan semua proses anak-anak mereka juga tidak akan dibatasi. Segala sesuatu yang lain pada sistem akan dibatasi untuk CPU 0 (setelah Anda reboot, karena cgredcgrules tidak berlaku untuk proses yang sudah berjalan kecuali mereka mengubah EUID mereka). Ini tidak sepenuhnya disarankan, tapi itulah yang awalnya saya minta dan bisa dilakukan dengan cgroup.

Wildcard
sumber
Wow. keren. bagaimana ini memiliki 0 suara?
mikeserv
@ mikeserv, terima kasih. :) Jawab pertanyaan Anda: periksa tanggalnya; Saya baru saja menulis jawaban ini kemarin.
Wildcard
1
saya melihat bahwa. tapi 24 jam yang lalu. mungkin itu penyebabnya panjang. hal-hal baik terkadang bisa diabaikan begitu saja. dan lagi pula, jawaban dengan banyak suara segera sangat jarang yang bagus - informasi tidak bisa berguna jika begitu banyak orang sudah tahu itu. ini adalah salah satu yang bagus. cgroup sangat misterius.
mikeserv