
Hai! Dalam artikel ini, saya ingin menjelaskan, dalam istilah awam, bagaimana
mencuri muncul di VMs dan memberi tahu Anda tentang beberapa artefak yang kurang jelas yang kami temukan selama penelitian tentang topik yang saya terlibat sebagai CTO dari
Mail. com Platform
Solusi Cloud . Platform ini menjalankan KVM.
Waktu mencuri CPU adalah waktu selama VM tidak menerima sumber daya yang diperlukan untuk beroperasi. Waktu ini hanya dapat dihitung dalam OS tamu di lingkungan virtualisasi. Sangat tidak jelas di mana sumber daya yang dialokasikan hilang, seperti dalam situasi kehidupan nyata. Namun, kami memutuskan untuk mencari tahu, dan kami bahkan melakukan serangkaian tes untuk melakukannya. Itu bukan untuk mengatakan bahwa kami tahu segalanya tentang
mencuri, tetapi ada beberapa hal menarik yang ingin kami bagikan dengan Anda.
1. Apa itu mencuri ?
Steal adalah metrik yang menunjukkan kurangnya waktu CPU untuk proses VM. Seperti yang dijelaskan dalam
patch kernel KVM ,
mencuri adalah waktu yang dihabiskan hypervisor untuk menjalankan proses lain dalam OS host, sementara proses VM dalam antrian run. Dengan kata lain,
mencuri dihitung sebagai perbedaan antara saat ketika suatu proses siap untuk dijalankan dan saat ketika waktu CPU dialokasikan untuk proses tersebut.
Kernel VM mendapatkan metrik
mencuri dari hypervisor. Hypervisor tidak menentukan proses yang sedang berjalan. Itu hanya mengatakan: "Aku sibuk, dan tidak bisa mengalokasikan waktu untukmu." Dalam KVM,
mencuri mencuri didukung dalam
tambalan . Ada dua poin utama mengenai ini:
- Seorang VM belajar tentang mencuri dari hypervisor. Ini berarti bahwa dalam hal kerugian, mencuri adalah pengukuran tidak langsung yang dapat terdistorsi dalam beberapa cara.
- Hypervisor tidak membagikan informasi VM tentang apa yang ditempati. Poin yang paling penting adalah tidak mengalokasikan waktu untuk itu. VM itu sendiri, oleh karena itu, tidak dapat mendeteksi distorsi dalam metrik mencuri , yang dapat diperkirakan oleh sifat dari proses yang bersaing.
2. Apa yang mempengaruhi mencuri ?
2.1. Menghitung mencuri
Pada dasarnya,
mencuri dihitung dengan cara yang kurang lebih sama dengan waktu pemanfaatan CPU. Tidak ada banyak informasi mengenai bagaimana pemanfaatan dihitung. Itu mungkin karena sebagian besar profesional berpikir itu sudah jelas. Namun, ada beberapa jebakan. Prosesnya dijelaskan dalam
sebuah artikel oleh Brendann Gregg . Dia membahas sejumlah nuansa tentang bagaimana menghitung pemanfaatan dan skenario di mana perhitungan akan salah:
- CPU kepanasan dan pelambatan.
- Menghidupkan / mematikan Turbo Boost, menghasilkan perubahan dalam laju jam CPU.
- Perubahan irisan waktu yang terjadi ketika teknologi hemat daya CPU, misalnya SpeedStep, digunakan.
- Masalah yang terkait dengan menghitung rata-rata: mengukur pemanfaatan selama satu menit pada daya 80% dapat menyembunyikan dorongan 100% jangka pendek.
- Spinlock yang menghasilkan skenario di mana prosesor digunakan, tetapi proses pengguna tidak mengalami kemajuan. Akibatnya, utilisasi CPU yang dihitung akan menjadi 100%, tetapi prosesnya tidak akan menghabiskan waktu CPU.
Saya belum menemukan artikel yang menggambarkan perhitungan
mencuri seperti itu (jika Anda tahu ada, silakan bagikan di bagian komentar). Seperti yang Anda lihat dari kode sumber, mekanisme perhitungannya sama dengan pemanfaatan. Satu-satunya perbedaan adalah bahwa penghitung lain ditambahkan secara khusus untuk proses KVM (proses VM), yang menghitung berapa lama proses KVM telah menunggu waktu CPU. Penghitung mengambil data pada CPU dari spesifikasinya dan memeriksa apakah semua kutu sedang digunakan oleh proses VM. Jika semua kutu sedang digunakan, maka CPU hanya sibuk dengan proses VM. Kalau tidak, kita tahu bahwa CPU melakukan sesuatu yang lain dan
mencuri muncul.
Proses dimana
mencuri dihitung tunduk pada masalah yang sama seperti perhitungan reguler pemanfaatan. Masalah-masalah ini tidak begitu umum, tetapi mereka bisa tampak agak membingungkan.
2.2. Jenis virtualisasi KVM
Secara umum, ada tiga jenis virtualisasi, dan semuanya didukung oleh KVM. Mekanisme
pencuri mungkin tergantung pada jenis virtualisasi.
Terjemahan Dalam hal ini, OS VM akan bekerja dengan perangkat hypervisor fisik dengan cara berikut:
- OS tamu mengirim perintah ke perangkat tamunya.
- Driver perangkat tamu menerima perintah, membuat permintaan perangkat BIOS, dan mengirimkan perintah ke hypervisor.
- Proses hypervisor menerjemahkan perintah menjadi perintah perangkat fisik, membuatnya lebih aman, antara lain.
- Driver perangkat fisik menerima perintah yang dimodifikasi dan meneruskannya ke perangkat fisik itu sendiri.
- Hasil eksekusi dari perintah kembali mengikuti jalur yang sama.
Keuntungan dari terjemahan adalah ia memungkinkan kita untuk meniru perangkat apa pun dan tidak memerlukan persiapan khusus dari kernel OS. Tetapi ini datang dengan mengorbankan kinerja.
Virtualisasi perangkat keras. Dalam hal ini, perangkat menerima perintah dari OS pada tingkat perangkat keras. Ini adalah metode terbaik tercepat dan keseluruhan. Sayangnya, tidak semua perangkat fisik, hypervisor, dan OS tamu mendukungnya. Untuk saat ini, perangkat utama yang mendukung virtualisasi perangkat keras adalah CPU.
Paravirtualization. Opsi paling umum untuk virtualisasi perangkat pada KVM dan tipe virtualisasi yang paling luas untuk OS tamu. Fitur utamanya adalah bekerja dengan beberapa subsistem hypervisor (mis. Jaringan atau drive stack) dan mengalokasikan halaman memori menggunakan API hypervisor tanpa menerjemahkan perintah level rendah. Kerugian dari metode virtualisasi ini adalah kebutuhan untuk memodifikasi kernel OS tamu untuk memungkinkan interaksi dengan hypervisor menggunakan API yang sama. Solusi paling umum untuk masalah ini adalah menginstal driver khusus ke dalam OS tamu. Dalam KVM, API ini disebut
API virtio .
Ketika paravirtualization digunakan, jalur ke perangkat fisik jauh lebih pendek daripada dalam kasus ketika terjemahan digunakan, karena perintah dikirim langsung dari VM ke proses hypervisor di host. Ini mempercepat eksekusi semua instruksi dalam VM. Dalam KVM, API virtio bertanggung jawab untuk ini. Ini hanya berfungsi untuk beberapa perangkat seperti adapter jaringan dan drive. Inilah sebabnya mengapa driver virtio diinstal ke VM.
Sisi lain dari akselerasi tersebut adalah tidak semua proses yang dijalankan dalam VM tetap berada dalam VM. Ini menghasilkan sejumlah efek, yang dapat menyebabkan
mencuri . Jika Anda ingin mempelajari lebih lanjut, mulailah dengan
API untuk virtual I / O: virtio .
2.3. Penjadwalan yang adil
VM pada hypervisor, pada kenyataannya, adalah proses reguler, yang tunduk pada hukum penjadwalan (distribusi sumber daya antara proses) di kernel Linux. Mari kita lihat lebih dekat.
Linux menggunakan apa yang disebut CFS, Completely Fair Scheduler, yang menjadi default dengan kernel 2.6.23. Untuk memahami algoritma ini, baca Arsitektur Kernel Linux atau kode sumbernya. Inti dari CFS terletak pada distribusi waktu CPU antar proses, tergantung pada waktu menjalankannya. Semakin banyak waktu CPU yang dibutuhkan suatu proses, semakin sedikit waktu CPU yang didapat. Ini menjamin eksekusi "adil" dari semua proses dan membantu untuk menghindari satu proses mengambil semua prosesor, sepanjang waktu dan memungkinkan proses lain untuk berjalan juga.
Terkadang paradigma ini menghasilkan artefak yang menarik. Pengguna Linux yang sudah lama berdiri pasti akan ingat bagaimana editor teks biasa pada desktop akan membeku ketika menjalankan aplikasi intensif sumber daya seperti kompiler. Ini terjadi karena tugas sumber daya ringan, seperti aplikasi desktop, bersaing dengan tugas yang menggunakan banyak sumber daya, seperti kompiler. CFS menganggap ini tidak adil, sehingga menghentikan editor teks dari waktu ke waktu dan memungkinkan CPU memproses tugas-tugas kompiler. Ini diperbaiki menggunakan mekanisme
sched_autogroup ; Namun, ada banyak keanehan lain dari distribusi waktu CPU. Artikel ini sebenarnya bukan tentang seberapa buruk CFS. Ini lebih merupakan upaya untuk menarik perhatian pada kenyataan bahwa distribusi waktu CPU yang "adil" bukanlah tugas yang paling sepele.
Aspek penting lain dari penjadwal adalah preemption. Ini diperlukan untuk membersihkan CPU dari segala proses yang terlalu dipaksakan dan memungkinkan orang lain untuk bekerja juga. Ini disebut
pengalihan konteks . Seluruh konteks tugas dipertahankan: status tumpukan, register, dan sebagainya, setelah itu proses dibiarkan menunggu dan digantikan oleh proses lain. Ini adalah operasi yang mahal untuk sebuah OS. Ini jarang digunakan, tetapi sebenarnya tidak buruk sama sekali. Pergantian konteks yang sering mungkin menjadi indikator masalah OS tetapi biasanya terjadi terus menerus dan bukan merupakan tanda masalah apa pun secara khusus.
Wacana panjang ini diperlukan untuk menjelaskan satu fakta: dalam penjadwal Linux yang adil, semakin banyak sumber daya CPU yang digunakan proses, semakin cepat akan dihentikan untuk memungkinkan proses lain bekerja. Apakah ini benar atau tidak adalah pertanyaan yang kompleks, dan solusinya berbeda tergantung pada bebannya. Sampai saat ini, Windows scheduler memprioritaskan aplikasi desktop, yang mengakibatkan proses latar belakang lebih lambat. Di Sun Solaris ada lima kelas penjadwal yang berbeda. Ketika virtualisasi diperkenalkan, mereka menambahkan satu lagi,
Penjadwal berbagi yang adil , karena yang lain tidak berjalan dengan baik dengan virtualisasi Solaris Zones. Untuk menggali lebih dalam tentang ini, saya sarankan memulai dengan
Solaris Internal: Solaris 10 dan OpenSolaris Kernel Architecture atau
Memahami Kernel Linux .
2.4. Bagaimana kita bisa memonitor mencuri ?
Sama seperti metrik CPU lainnya, mudah untuk
mencuri di dalam VM. Anda dapat menggunakan alat pengukuran metrik CPU apa pun. Yang utama adalah VM harus ada di Linux. Untuk beberapa alasan, Windows tidak memberikan informasi seperti itu kepada pengguna. :(
Output atas: spesifikasi beban CPU dengan mencuri di kolom kananBanyak hal menjadi rumit ketika mencoba untuk mendapatkan informasi ini dari hypervisor. Anda dapat mencoba meramalkan
mencuri pada mesin host, menggunakan Load Average (LA), misalnya. Ini adalah nilai rata-rata jumlah proses dalam antrian run. Metode perhitungan untuk parameter ini bukan yang sederhana, tetapi secara umum, jika LA yang telah distandarisasi berdasarkan jumlah utas CPU lebih besar dari 1, itu berarti server Linux kelebihan beban.
Jadi, tunggu apa lagi semua proses ini? Jelas, CPU. Namun, jawaban ini tidak terlalu akurat, karena kadang-kadang CPU gratis dan LA terlalu tinggi. Ingatlah
bahwa NFS jatuh dan LA naik pada saat yang sama . Situasi serupa mungkin terjadi dengan drive dan perangkat input / output lainnya. Bahkan, proses mungkin menunggu akhir kunci: fisik (terkait dengan perangkat input / output) atau logis (objek mutex, misalnya). Hal yang sama berlaku untuk kunci tingkat perangkat keras (misalnya, respons disk) atau kunci tingkat logika (disebut "penguncian primitif", yang mencakup sejumlah entitas, mutex adaptif dan putaran, semaphore, variabel kondisi, kunci rw, kunci ipc ...).
Fitur lain dari LA adalah bahwa itu dihitung sebagai nilai rata-rata dalam OS. Misalnya, jika 100 proses bersaing untuk satu file, LA adalah 50. Jumlah besar ini membuatnya tampak seperti ini buruk untuk OS. Namun, untuk kode yang ditulis dengan buruk ini bisa menjadi normal. Hanya kode spesifik yang akan menjadi buruk, dan sisa OS mungkin baik-baik saja.
Karena rata-rata ini (kurang dari satu menit), menentukan apa pun yang menggunakan LA bukanlah ide terbaik, karena dapat menghasilkan hasil yang sangat ambigu dalam beberapa kasus. Jika Anda mencoba mencari tahu lebih lanjut tentang ini, Anda akan menemukan bahwa Wikipedia dan sumber daya lain yang tersedia hanya menggambarkan kasus yang paling sederhana, dan prosesnya tidak dijelaskan secara rinci. Jika Anda tertarik dengan ini, sekali lagi, kunjungi
Brendann Gregg dan ikuti
tautannya .
3. Efek khusus
Sekarang mari kita ke kasus utama
pencurian yang kita temui. Izinkan saya menjelaskan bagaimana hasilnya dari hal di atas dan bagaimana mereka berkorelasi dengan metrik hypervisor.
Pemanfaatan berlebih. Kasus paling sederhana dan paling umum: hypervisor sedang digunakan secara berlebihan. Memang, dengan banyak VM berjalan dan memakan banyak sumber daya CPU, persaingan tinggi, dan pemanfaatan menurut LA lebih besar dari 1 (standar menurut utas CPU). Semuanya tertinggal dalam semua VM.
Mencuri yang dikirim dari hypervisor juga tumbuh. Anda harus mendistribusikan ulang muatan atau mematikan sesuatu. Secara keseluruhan, ini semua logis dan langsung.
Paravirtualization vs instance tunggal. Hanya ada satu VM di hypervisor. VM mengkonsumsi sebagian kecil dari itu, tetapi memberikan beban input / output yang tinggi, misalnya, untuk drive. Tanpa diduga,
mencuri kecil kurang dari 10% muncul (karena beberapa tes yang kami lakukan menunjukkan).
Ini adalah kasus yang aneh. Di sini,
mencuri muncul karena kunci pada tingkat perangkat paravirtualized. Di dalam VM, breakpoint dibuat. Ini diproses oleh pengemudi dan pergi ke hypervisor. Karena pemrosesan breakpoint pada hypervisor, VM melihat ini sebagai permintaan yang dikirim. Sudah siap untuk menjalankan dan menunggu CPU, tetapi tidak menerima waktu CPU. VM berpikir bahwa waktunya telah dicuri.
Ini terjadi ketika buffer dikirim. Ia pergi ke ruang kernel hypervisor dan kami menunggu untuk itu. Dari sudut pandang VM, itu harus segera kembali. Karena itu, menurut algoritma perhitungan
mencuri kami, kali ini dianggap dicuri. Sangat mungkin bahwa mekanisme lain mungkin terlibat dalam hal ini (misalnya pemrosesan
panggilan sistem lain), tetapi mekanisme tersebut tidak boleh berbeda secara signifikan.
Penjadwal vs VM yang sangat dimuat. Ketika satu VM menderita
mencuri lebih dari yang lain, ini terhubung langsung dengan penjadwal. Semakin besar beban yang dilakukan suatu proses pada CPU, semakin cepat penjadwal akan membuangnya, sehingga memungkinkan proses lain bekerja. Jika VM mengonsumsi sedikit, itu akan mengalami hampir tidak
mencuri. Prosesnya baru saja duduk dan menunggu, dan perlu diberi lebih banyak waktu. Jika VM memberikan beban maksimum pada semua core, prosesnya dibuang lebih sering dan VM diberikan lebih sedikit waktu.
Lebih buruk lagi ketika proses dalam VM mencoba untuk mendapatkan lebih banyak CPU, karena mereka tidak dapat memproses data. Maka OS pada hypervisor akan memberikan lebih sedikit waktu CPU karena optimasi yang adil. Ini memproses bola salju, dan
mencuri lonjakan setinggi langit, sementara VM lain mungkin bahkan tidak menyadarinya. Semakin banyak core, semakin buruk bagi VM yang malang. Singkatnya, banyak VM yang dimuat dengan banyak core paling menderita.
Rendah LA tetapi
mencuri ada. Jika LA sekitar 0,7 (artinya hypervisor tampaknya kurang beban), tetapi ada
mencuri di beberapa VM:
- Contoh paravirtualization yang disebutkan di atas berlaku. VM mungkin menerima metrik yang mengindikasikan mencuri , sedangkan hypervisor tidak memiliki masalah. Menurut hasil pengujian kami, mencuri seperti itu cenderung tidak melebihi 10% dan tidak memiliki dampak yang signifikan pada kinerja aplikasi dalam VM.
- Parameter LA telah dihitung secara tidak benar. Lebih tepatnya, itu telah dihitung dengan benar pada saat tertentu, tetapi ketika rata-rata, itu lebih rendah dari yang seharusnya selama satu menit. Misalnya, jika satu VM (sepertiga dari hypervisor) mengkonsumsi semua CPU selama 30 detik, maka LA selama satu menit akan menjadi 0,15. Empat VM seperti itu, yang bekerja pada saat yang sama, akan menghasilkan nilai 0,6. Berdasarkan LA, Anda tidak akan dapat menyimpulkan bahwa selama 30 detik untuk masing-masing, mencuri hampir 25%.
- Sekali lagi, ini terjadi karena penjadwal, yang memutuskan bahwa seseorang "terlalu banyak makan" dan membuat mereka menunggu. Sementara itu, ia akan mengubah konteks, memproses breakpoint, dan menangani masalah sistem penting lainnya. Akibatnya, beberapa VM tidak mengalami masalah, dan yang lain menderita kerugian kinerja yang signifikan.
4. Distorsi lainnya
Ada sejuta alasan yang mungkin untuk distorsi alokasi waktu CPU yang adil pada VM. Sebagai contoh, hyperthreading dan NUMA menambah kompleksitas pada perhitungan. Mereka mempersulit pemilihan inti yang digunakan untuk menjalankan suatu proses karena penjadwal menggunakan koefisien; artinya bobot, yang menyulitkan perhitungan bahkan lebih dari ini ketika mengganti konteks.
Ada distorsi yang muncul dari teknologi seperti Turbo Boost atau kebalikannya, mode hemat daya, yang mungkin secara artifisial meningkatkan atau mengurangi kecepatan inti CPU dan bahkan irisan waktu. Menghidupkan Turbo Boost pada penurunan produktivitas satu utas CPU karena peningkatan kinerja di utas lainnya. Pada saat itu, informasi mengenai kecepatan clock CPU saat ini tidak dikirim ke VM, yang berpikir bahwa seseorang mencuri waktunya (mis. Ia meminta 2 GHz dan mendapat separuh lebih banyak).
Faktanya, ada banyak alasan untuk distorsi. Anda dapat menemukan sesuatu yang lain sepenuhnya dalam sistem apa pun. Saya sarankan mulai dengan buku-buku yang ditautkan di atas dan mendapatkan statistik dari hypervisor menggunakan alat-alat seperti perf, sysdig, systemtap, dan
puluhan lainnya .
5. Kesimpulan
- Beberapa mencuri mungkin muncul karena paravirtualization dan ini dapat dianggap normal. Sumber daring mengatakan bahwa nilai ini bisa 5-10%. Itu tergantung pada aplikasi dalam VM, dan beban yang diletakkan VM pada perangkat fisiknya. Penting untuk memperhatikan bagaimana perasaan aplikasi di dalam VM.
- Korelasi antara beban pada hypervisor dan mencuri di dalam VM tidak selalu pasti. Kedua perhitungan mencuri bisa salah dalam beberapa kasus dan dengan beban yang berbeda.
- Penjadwal tidak menyukai proses yang meminta banyak sumber daya. Ia mencoba memberi lebih sedikit kepada mereka yang meminta lebih. Contoh besar berarti.
- Sedikit mencuri bisa menjadi normal tanpa paravirtualization juga (dengan mempertimbangkan beban dalam VM, kekhasan beban tetangga, distribusi beban antara benang, dan faktor lainnya).
- Jika Anda ingin menghitung mencuri dalam sistem tertentu, teliti berbagai kemungkinan, kumpulkan metrik, analisis secara menyeluruh, dan pikirkan cara mendistribusikan beban secara adil. Apapun, mungkin ada penyimpangan, yang harus diverifikasi menggunakan tes atau melihatnya di debugger kernel.