Mendiagnosis penggunaan CPU yang tinggi pada Docker untuk Mac

20

Bagaimana cara mendiagnosis penyebab Docker pada MacOS, khususnya com.docker.hyperkitmenggunakan 100% CPU?

penggunaan CPU buruh pelabuhan

Statistik buruh pelabuhan

Statistik Docker menunjukkan semua kontainer yang berjalan memiliki CPU, memori, IO bersih dan blok IO yang rendah.

output statistik buruh pelabuhan

iosnoop

iosnoop menunjukkan bahwa com.docker.hyperkitmelakukan sekitar 50 tulis per detik dengan total 500KB per detik ke file Docker.qcow2. Menurut Apa itu Docker.qcow2? , Docker.qcow2adalah file jarang yang merupakan penyimpanan persisten untuk semua wadah Docker.

Dalam kasus saya, file tidak jarang. Ukuran fisik cocok dengan ukuran logis.

docker.qcow ukuran sebenarnya

dtrace (dtruss)

dtruss sudo dtruss -p $DOCKER_PIDmenunjukkan sejumlah besar psynch_cvsignaldan psynch_cvwaitpanggilan.

psynch_cvsignal(0x7F9946002408, 0x4EA701004EA70200, 0x4EA70100)          = 257 0
psynch_mutexdrop(0x7F9946002318, 0x5554700, 0x5554700)           = 0 0
psynch_mutexwait(0x7F9946002318, 0x5554702, 0x5554600)           = 89474819 0
psynch_cvsignal(0x10BF7B470, 0x4C8095004C809600, 0x4C809300)             = 257 0
psynch_cvwait(0x10BF7B470, 0x4C8095014C809600, 0x4C809300)               = 0 0
psynch_cvwait(0x10BF7B470, 0x4C8096014C809700, 0x4C809600)               = -1 Err#316
psynch_cvsignal(0x7F9946002408, 0x4EA702004EA70300, 0x4EA70200)          = 257 0
psynch_cvwait(0x7F9946002408, 0x4EA702014EA70300, 0x4EA70200)            = 0 0
psynch_cvsignal(0x10BF7B470, 0x4C8097004C809800, 0x4C809600)             = 257 0
psynch_cvwait(0x10BF7B470, 0x4C8097014C809800, 0x4C809600)               = 0 0
psynch_cvwait(0x10BF7B470, 0x4C8098014C809900, 0x4C809800)               = -1 Err#316

Perbarui: toppada host Docker

Dari https://stackoverflow.com/a/58293240/30900 :

docker run -it --rm --pid host busybox top

Penggunaan CPU pada host tertanam docker adalah ~ 3%. Penggunaan CPU di MacBook saya adalah ~ 100%. Jadi, host docker tertanam tidak menyebabkan lonjakan penggunaan CPU.

tuan rumah buruh pelabuhan atas

Pembaruan: menjalankan skrip dtrace dari kebanyakan jejak stack yang paling umum

Tumpukan jejak dari skrip dtrace dalam jawaban di bawah ini: https://stackoverflow.com/a/58293035/30900 .

Jejak tumpukan kernel ini terlihat tidak berbahaya.

              AppleIntelLpssGspi`AppleIntelLpssGspi::regRead(unsigned int)+0x1f
              AppleIntelLpssGspi`AppleIntelLpssGspi::transferMmioDuplexMulti(void*, void*, unsigned long long, unsigned int)+0x91
              AppleIntelLpssSpiController`AppleIntelLpssSpiController::transferDataMmioDuplexMulti(void*, void*, unsigned int, unsigned int)+0xb2
              AppleIntelLpssSpiController`AppleIntelLpssSpiController::_transferDataSubr(AppleInfoLpssSpiControllerTransferDataRequest*)+0x5bc
              AppleIntelLpssSpiController`AppleIntelLpssSpiController::_transferData(AppleInfoLpssSpiControllerTransferDataRequest*)+0x24f
              kernel`IOCommandGate::runAction(int (*)(OSObject*, void*, void*, void*, void*), void*, void*, void*, void*)+0x138
              AppleIntelLpssSpiController`AppleIntelLpssSpiDevice::transferData(IOMemoryDescriptor*, void*, unsigned long long, unsigned long long, IOMemoryDescriptor*, void*, unsigned long long, unsigned long long, unsigned int, AppleIntelSPICompletion*)+0x151
              AppleHSSPISupport`AppleHSSPIController::transferData(IOMemoryDescriptor*, void*, unsigned long long, unsigned long long, IOMemoryDescriptor*, void*, unsigned long long, unsigned long long, unsigned int, AppleIntelSPICompletion*)+0xcc
              AppleHSSPISupport`AppleHSSPIController::doSPITransfer(bool, AppleHSSPITransferRetryReason*)+0x97
              AppleHSSPISupport`AppleHSSPIController::InterruptOccurred(IOInterruptEventSource*, int)+0xf8
              kernel`IOInterruptEventSource::checkForWork()+0x13c
              kernel`IOWorkLoop::runEventSources()+0x1e2
              kernel`IOWorkLoop::threadMain()+0x2c
              kernel`call_continuation+0x2e
               53

              kernel`waitq_wakeup64_thread+0xa7
              pthread`__psynch_cvsignal+0x495
              pthread`_psynch_cvsignal+0x28
              kernel`psynch_cvsignal+0x38
              kernel`unix_syscall64+0x27d
              kernel`hndl_unix_scall64+0x16
               60

              kernel`hndl_mdep_scall64+0x4
              113

              kernel`ml_set_interrupts_enabled+0x19
              524

              kernel`ml_set_interrupts_enabled+0x19
              kernel`hndl_mdep_scall64+0x10
             5890

              kernel`machine_idle+0x2f8
              kernel`call_continuation+0x2e
            43395

Jejak tumpukan paling umum di ruang pengguna selama 17 detik jelas melibatkan com.docker.hyperkit. Ada 1365 tumpukan jejak dalam 17 detik di mana com.docker.hyperkitdibuat utas yang rata-rata hingga 80 utas per detik.

              com.docker.hyperkit`0x000000010cbd20db+0x19f9
              com.docker.hyperkit`0x000000010cbdb98c+0x157
              com.docker.hyperkit`0x000000010cbf6c2d+0x4bd
              libsystem_pthread.dylib`_pthread_body+0x7e
              libsystem_pthread.dylib`_pthread_start+0x42
              libsystem_pthread.dylib`thread_start+0xd
               19

              Hypervisor`hv_vmx_vcpu_read_vmcs+0x1
              com.docker.hyperkit`0x000000010cbd4c4f+0x2a
              com.docker.hyperkit`0x000000010cbd20db+0x174a
              com.docker.hyperkit`0x000000010cbdb98c+0x157
              com.docker.hyperkit`0x000000010cbf6c2d+0x4bd
              libsystem_pthread.dylib`_pthread_body+0x7e
              libsystem_pthread.dylib`_pthread_start+0x42
              libsystem_pthread.dylib`thread_start+0xd
               22

              Hypervisor`hv_vmx_vcpu_read_vmcs
              com.docker.hyperkit`0x000000010cbdb98c+0x157
              com.docker.hyperkit`0x000000010cbf6c2d+0x4bd
              libsystem_pthread.dylib`_pthread_body+0x7e
              libsystem_pthread.dylib`_pthread_start+0x42
              libsystem_pthread.dylib`thread_start+0xd
               34

              com.docker.hyperkit`0x000000010cbd878d+0x36
              com.docker.hyperkit`0x000000010cbd20db+0x42f
              com.docker.hyperkit`0x000000010cbdb98c+0x157
              com.docker.hyperkit`0x000000010cbf6c2d+0x4bd
              libsystem_pthread.dylib`_pthread_body+0x7e
              libsystem_pthread.dylib`_pthread_start+0x42
              libsystem_pthread.dylib`thread_start+0xd
               47

              Hypervisor`hv_vcpu_run+0xd
              com.docker.hyperkit`0x000000010cbd20db+0x6b6
              com.docker.hyperkit`0x000000010cbdb98c+0x157
              com.docker.hyperkit`0x000000010cbf6c2d+0x4bd
              libsystem_pthread.dylib`_pthread_body+0x7e
              libsystem_pthread.dylib`_pthread_start+0x42
              libsystem_pthread.dylib`thread_start+0xd
              135

Masalah terkait

Github - docker / for-mac: com.docker.hyperkit 100% penggunaan CPU kembali lagi # 3499 . Satu komentar menyarankan menambahkan caching volume yang dijelaskan di sini: https://www.docker.com/blog/user-guided-caching-in-docker-for-mac/ . Saya mencoba ini dan mendapat pengurangan kecil ~ 10% dalam penggunaan CPU.

Joe
sumber
Apakah Anda membuat gambar? Saya juga fokus pada wadah yang melakukan banyak blok IO. Itu juga penting apakah Anda telah mengaktifkan Kubernetes.
BMitch
1
Saya mengumpulkan semua metrik setelah cluster dibangun dan dijalankan selama beberapa menit. Kubernet dinonaktifkan. Tidak ada mesin yang melakukan banyak blok IO. Wadah tidak melakukan apa pun. Saya perhatikan penggunaan CPU tampaknya secara kasar berkorelasi dengan jumlah kontainer.
Joe
Berapa core / cpu yang Anda miliki di mesin?
BMitch
Juga, sudahkah Anda mencoba me-restart buruh pelabuhan, bukan wadah, tetapi seluruh mesin dan klien desktop?
BMitch
Saya menjalankan 2018 MBP 2,8 GHz Core i7 dengan 4 core. Saya mencoba mengutak-atik jumlah core CPU untuk mesin Docker. Saya mencoba 1, 3, 4, dan 6 core. Membatasi penggunaan buruh pelabuhan mengurangi penggunaan CPU dari 100% menjadi 60%.
Joe

Jawaban:

5

Saya memiliki masalah yang sama. CPU% saya kembali normal setelah saya menghapus semua volume saya.

docker system prune --volumes

Saya juga secara manual menghapus beberapa volume bernama:

docker volume rm NameOfVolumeHere

Itu tidak menyelesaikan masalah keseluruhan karena tidak dapat menggunakan volume dengan Docker untuk mac. Saat ini saya hanya berhati-hati tentang jumlah volume yang saya gunakan dan menutup desktop Docker saat tidak digunakan.

Chris Adams
sumber
3

Kecurigaan saya adalah bahwa masalahnya terkait IO. Dengan volume MacOS, ini melibatkan osxfs di mana ada beberapa penyesuaian kinerja yang dapat Anda lakukan. Terutama, jika Anda dapat menerima lebih sedikit pemeriksaan konsistensi, Anda dapat mengatur mode volume delegateduntuk kinerja yang lebih cepat. Lihat dokumen untuk detail lebih lanjut: https://docs.docker.com/docker-for-mac/osxfs-caching/ . Namun, jika gambar Anda mengandung banyak file kecil, kinerjanya akan berkurang, terutama jika Anda juga memiliki banyak layer gambar.

Anda juga dapat mencoba perintah berikut untuk men-debug setiap masalah proses dalam VM tertanam yang digunakan buruh pelabuhan:

docker run -it --rm --pid host busybox top

(Untuk keluar, gunakan <ctrl>-c)


Untuk melacak apakah itu IO, Anda juga dapat mencoba yang berikut ini:

$ docker run -it --rm --pid host alpine /bin/sh
$ apk add sysstat
$ pidstat -d 5 12

Itu akan berjalan di dalam wadah alpine yang berjalan di namespace VM VM, menunjukkan setiap IO terjadi dari proses apa pun, apakah proses itu ada di dalam wadah atau tidak. Statistik setiap 5 detik selama satu menit (12 kali) dan kemudian akan memberi Anda tabel rata-rata per proses. Anda kemudian <ctrl>-ddapat menghancurkan wadah alpine.


Dari komentar dan pengeditan, statistik ini dapat memeriksa. MBP 4 inti memiliki 8 utas, jadi utilisasi CPU penuh harus 800% jika MacOS melaporkan sama dengan sistem berbasis Unix lainnya. Di dalam VM ada lebih dari 100% beban yang ditunjukkan pada perintah teratas untuk rata-rata di menit terakhir (meskipun kurang dari rata-rata 5 dan 15) yang kira-kira seperti yang Anda lihat untuk proses hyperkit di host. Penggunaan instan adalah lebih dari 12% dari atas, bukan 3%, karena Anda perlu menambahkan sistem dan persentase pengguna. Dan angka-angka IO yang ditunjukkan pada pidstat sejajar dengan apa yang Anda lihat tertulis pada gambar qcow2.


Jika mesin buruh pelabuhan itu sendiri meronta-ronta (misalnya memulai kembali wadah, atau menjalankan banyak pemeriksaan kesehatan), maka Anda dapat men-debug itu dengan menonton output dari:

docker events
BMitch
sumber
Saya mengubah semua volume mount delegatedtetapi tidak ada peningkatan kinerja. Saya menjalankan topperintah pada VM tertanam tetapi penggunaan CPU melayang sekitar ~ 3%.
Joe
Diperbarui dengan pidstatuntuk melacak masalah IO dengan lebih baik.
BMitch
pidstatmenunjukkan bacaan untuk semua PID adalah 0 kB / s. Untuk menulis: logwritemenulis rata-rata influxd8.5kB / s dan rata-rata menulis 0.61kB / s. Sisa prosesnya adalah 0.
Joe
1

Ini adalah skrip dTrace kecil yang saya gunakan untuk menemukan di mana kernel menghabiskan waktunya (itu dari Solaris, dan tanggal kembali ke hari-hari awal Solaris 10):

#!/usr/sbin/dtrace -s

profile:::profile-1001hz
/arg0/
{
    @[ stack() ] = count();
}

Ini hanya sampel jejak tumpukan kernel dan menghitung masing-masing yang ditemui dalam @hotagregasi.

Jalankan sebagai root:

... # ./kernelhotspots.d > /tmp/kernel_hot_spots.txt

Biarkan berjalan untuk jumlah waktu yang layak saat Anda mengalami masalah CPU, lalu tekan CTRL-Cuntuk memecahkan skrip. Ini akan memancarkan semua jejak tumpukan kernel yang ditemui, yang terakhir paling umum. Jika Anda membutuhkan lebih banyak (atau kurang) tumpukan frame dari default dengan

    @[ stack( 15 ) ] = count();

Itu akan menampilkan 15 frame stack panggilan mendalam.

Beberapa jejak stack terakhir adalah tempat kernel Anda menghabiskan sebagian besar waktunya. Itu mungkin atau mungkin tidak informatif.

Skrip ini akan melakukan hal yang sama untuk jejak tumpukan ruang pengguna:

#!/usr/sbin/dtrace -s

profile:::profile-1001hz
/arg1/
{
    @[ ustack() ] = count();
}

Jalankan dengan cara yang sama:

... # ./userspacehotspots.d > /tmp/userspace_hot_spots.txt

ustack() sedikit lebih lambat - untuk memancarkan nama fungsi sebenarnya, dTrace harus melakukan lebih banyak pekerjaan untuk mendapatkannya dari ruang alamat dari proses yang sesuai.

Menonaktifkan Perlindungan Integritas Sistem mungkin membantu Anda mendapatkan jejak tumpukan yang lebih baik.

Lihat Dasar - dasar Tindakan DTrace untuk beberapa perincian lebih lanjut.

Andrew Henle
sumber
Terima kasih, saya memperbarui pertanyaan dengan hasil skrip. Jejak tumpukan userspace menunjukkan com.docker.hyperkit membuat banyak utas.
Joe