Diagnosi dell'utilizzo elevato della CPU su Docker per Mac


20

Come posso diagnosticare la causa di Docker su MacOS, com.docker.hyperkitutilizzando in particolare il 100% della CPU?

utilizzo della CPU docker

Statistiche Docker

Le statistiche Docker mostrano che tutti i container in esecuzione hanno CPU, memoria, IO di rete e IO di blocco bassi.

output delle statistiche della finestra mobile

iosnoop

iosnoop mostra che com.docker.hyperkitesegue circa 50 scritture al secondo per un totale di 500 KB al secondo nel file Docker.qcow2. Secondo Cos'è Docker.qcow2? , Docker.qcow2è un file sparso che è l'archiviazione persistente per tutti i contenitori Docker.

Nel mio caso il file non è così scarso. La dimensione fisica corrisponde alla dimensione logica.

docker.qcow dimensioni effettive

dtrace (dtruss)

dtruss sudo dtruss -p $DOCKER_PIDmostra un gran numero di psynch_cvsignale psynch_cvwaitchiama.

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

Aggiornamento: topsull'host Docker

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

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

L'utilizzo della CPU sull'host incorporato nella finestra mobile è ~ 3%. L'utilizzo della CPU sul mio MacBook è stato ~ 100%. Pertanto, l'host incorporato nella finestra mobile non sta causando il picco di utilizzo della CPU.

Docker host top

Aggiornamento: eseguendo script dtrace delle più comuni tracce di stack

Stack tracce dagli script dtrace nella risposta di seguito: https://stackoverflow.com/a/58293035/30900 .

Queste tracce dello stack del kernel sembrano innocue.

              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

Le tracce dello stack più comuni nello spazio utente in 17 secondi implicano chiaramente com.docker.hyperkit. Ci sono 1365 tracce di stack in 17 secondi in cui sono stati com.docker.hyperkitcreati thread che hanno una media di 80 thread al secondo.

              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

Problemi correlati

Github - docker / for-mac: com.docker.hyperkit L'utilizzo della CPU al 100% è tornato di nuovo # 3499 . Un commento suggerisce di aggiungere la cache del volume descritta qui: https://www.docker.com/blog/user-guided-caching-in-docker-for-mac/ . Ho provato questo e ho ottenuto una piccola riduzione del 10% circa nell'uso della CPU.


Stai costruendo immagini? Mi concentrerei anche su container che eseguono molto blocco IO. Importa anche se hai abilitato Kubernetes.
BMitch

1
Ho raccolto tutte le metriche dopo che il cluster è stato creato e funzionante per alcuni minuti. Kubernetes è disabilitato. Nessuna delle macchine esegue però molti blocchi IO. I contenitori non stanno facendo nulla. Ho notato che l'utilizzo della CPU sembra approssimativamente correlato al numero di container.
Joe,

Quanti core / cpu hai sulla macchina?
BMitch

Inoltre, hai provato a riavviare la finestra mobile, non i contenitori, ma l'intero motore e il client desktop?
BMitch

Sto usando un Core i7 MBP 2.8 GHz 2018 con 4 core. Ho provato a modificare il numero di core della CPU per il motore Docker. Ho provato 1, 3, 4 e 6 core. La limitazione alla finestra mobile ha ridotto l'utilizzo della CPU dal 100% al 60%.
Joe,

Risposte:


5

Ho lo stesso problema. La mia CPU% è tornata alla normalità dopo aver rimosso tutti i miei volumi.

docker system prune --volumes

Ho anche rimosso manualmente alcuni volumi con nome:

docker volume rm NameOfVolumeHere

Ciò non risolve il problema generale di non poter utilizzare i volumi con Docker per mac. In questo momento sto solo attento alla quantità di volumi che utilizzo e alla chiusura del desktop Docker quando non in uso.


3

Il mio sospetto è che il problema sia legato all'IO. Con i volumi MacOS, ciò implica osxfs in cui è possibile eseguire alcune ottimizzazioni delle prestazioni. Principalmente, se puoi accettare meno controlli di coerenza, puoi impostare la modalità volume su delegatedper prestazioni più veloci. Vedi i documenti per maggiori dettagli: https://docs.docker.com/docker-for-mac/osxfs-caching/ . Tuttavia, se l'immagine contiene un numero elevato di file di piccole dimensioni, le prestazioni ne risentiranno, soprattutto se si dispone anche di molti livelli di immagine.

È inoltre possibile provare il comando seguente per eseguire il debug di eventuali problemi di processo nella VM integrata utilizzata dalla finestra mobile:

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

(Per uscire, utilizzare <ctrl>-c)


Per rintracciare se è IO, puoi anche provare quanto segue:

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

Ciò verrà eseguito all'interno del container alpine in esecuzione nello spazio dei nomi pid VM, mostrando qualsiasi IO che si verifica da qualsiasi processo, indipendentemente dal fatto che quel processo sia all'interno o meno di un container. Le statistiche sono ogni 5 secondi per un minuto (12 volte) e quindi ti darà una tabella media per processo. È quindi possibile <ctrl>-ddistruggere il contenitore alpino.


Dai commenti e dalle modifiche, queste statistiche possono essere verificate. Un MBP a 4 core ha 8 thread, quindi l'utilizzo completo della CPU dovrebbe essere dell'800% se MacOS riporta lo stesso di altri sistemi basati su Unix. All'interno della VM c'è un carico superiore al 100% mostrato nel comando in alto per la media dell'ultimo minuto (anche se in meno rispetto alle medie 5 e 15) che è più o meno quello che vedi per il processo hyperkit sull'host. L'uso istantaneo è superiore al 12%, non al 3%, poiché è necessario aggiungere le percentuali di sistema e utente. E i numeri di I / O mostrati in pidstat si allineano approssimativamente con ciò che vedi scritto nell'immagine qcow2.


Se il motore docker stesso si sta bloccando (ad es. Riavviare i contenitori o eseguire molti controlli di integrità), è possibile eseguire il debug osservando l'output di:

docker events

Ho modificato tutti i montaggi del volume delegatedma non ci sono stati miglioramenti delle prestazioni. Ho eseguito il topcomando sulla VM incorporata ma l'utilizzo della CPU è rimasto circa il 3% circa.
Joe,

Aggiornato con pidstatper tracciare meglio i problemi di IO.
BMitch

pidstatmostra che le letture per tutti i PID sono 0 kB / s. Per le scritture: logwritescrive 8,5kB / s in media e influxdscrive 0,61kB / s in media. Il resto dei processi sono 0.
Joe,

1

Questo è un piccolo script dTrace che uso per trovare dove il kernel sta trascorrendo il suo tempo (è di Solaris e risale ai primi giorni di Solaris 10):

#!/usr/sbin/dtrace -s

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

Semplicemente campiona le tracce dello stack del kernel e conta ognuna delle quali incontra @hotnell'aggregazione.

Eseguilo come root:

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

Lascialo funzionare per un discreto periodo di tempo mentre riscontri problemi con la CPU, quindi premi CTRL-Cper interrompere lo script. Emetterà tutte le tracce dello stack del kernel incontrate, l'ultima più comune. Se hai bisogno di più (o meno) stack frame di default con

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

Ciò mostrerà uno stack frame di 15 chiamate in profondità.

Le ultime tracce dello stack saranno quelle in cui il kernel trascorre la maggior parte del suo tempo. Ciò può essere o meno informativo.

Questo script farà lo stesso per le tracce dello stack dello spazio utente:

#!/usr/sbin/dtrace -s

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

Eseguilo in modo simile:

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

ustack() è un po 'più lento - per emettere i nomi effettivi delle funzioni, dTrace deve fare molto più lavoro per ottenerli dagli spazi degli indirizzi dei processi appropriati.

La disabilitazione della protezione dell'integrità del sistema potrebbe aiutarti a ottenere migliori tracce dello stack.

Vedi Nozioni di base sulle azioni DTrace per ulteriori dettagli.


Grazie, ho aggiornato la domanda con i risultati degli script. Le tracce dello stack dello spazio utente mostrano com.docker.hyperkit crea molti thread.
Joe,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.