Docker for Mac에서 높은 CPU 사용량 진단


20

MacOS에서 Docker의 원인, 특히 com.docker.hyperkitCPU를 100 % 사용 하는 원인을 어떻게 진단 합니까?

도커 CPU 사용량

도커 통계

Docker 통계는 실행중인 모든 컨테이너에 CPU, 메모리, net IO 및 블록 IO가 낮음을 보여줍니다.

도커 통계 출력

iosnoop

iosnoop은 com.docker.hyperkit파일에 초당 총 500KB의 초당 약 50 개의 쓰기 를 수행 하는 것을 보여줍니다 Docker.qcow2. 에 따르면 Docker.qcow2 무엇입니까? , Docker.qcow2모든 도커 용기에 대한 영구 저장소의 스파 스 파일입니다.

제 경우에는 파일이 그 스파 스가 아닙니다. 물리적 크기는 논리적 크기와 일치합니다.

docker.qcow 실제 크기

dtrace (dtruss)

dtruss sudo dtruss -p $DOCKER_PID보여 큰 수 psynch_cvsignalpsynch_cvwait통화.

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

업데이트 : topDocker 호스트에서

에서 https://stackoverflow.com/a/58293240/30900 :

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

docker 내장 호스트의 CPU 사용량은 ~ 3 %입니다. MacBook의 CPU 사용량은 ~ 100 %입니다. 따라서 도커 내장 호스트로 인해 CPU 사용량이 급증하지 않습니다.

도커 호스트 상단

업데이트 : 가장 일반적인 스택 추적의 dtrace 스크립트 실행

https://stackoverflow.com/a/58293035/30900 에서 dtrace 스크립트의 추적을 추적 하십시오 .

이 커널 스택 추적은 무해 해 보입니다.

              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

17 초 동안 사용자 공간에서 가장 일반적인 스택 추적은 com.docker.hyperkit과 관련이 있습니다. 17 초 동안 1365 개의 스택 추적이 com.docker.hyperkit생성되어 초당 평균 80 개의 스레드 가 생성됩니다.

              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

관련 문제

Github-docker / for-mac : com.docker.hyperkit 100 % CPU 사용량이 다시 # 3499로 돌아 왔습니다 . 한 의견은 https://www.docker.com/blog/user-guided-caching-in-docker-for-mac/에 설명 된 볼륨 캐싱 추가를 제안 합니다. 나는 이것을 시도하고 CPU 사용량이 ~ 10 % 감소했습니다.


이미지를 만들고 있습니까? 또한 많은 블록 IO를 수행하는 컨테이너에 중점을 둡니다. Kubernetes를 활성화했는지 여부도 중요합니다.
BMitch

1
클러스터가 구축되고 몇 분 동안 실행 된 후 모든 메트릭을 수집했습니다. Kubernetes가 비활성화되었습니다. 그럼에도 불구하고 어떤 시스템도 많은 블록 IO를 수행하지 않습니다. 컨테이너가 아무것도하지 않습니다. CPU 사용량이 컨테이너 수와 대략 상관 관계가있는 것으로 나타났습니다.
Joe

머신에 코어 / CPU가 몇 개 있습니까?
BMitch

또한 컨테이너가 아닌 전체 엔진 및 데스크톱 클라이언트를 도커를 다시 시작해 보셨습니까?
BMitch

4 개의 코어가있는 2018 MBP 2.8 GHz Core i7을 실행하고 있습니다. Docker 엔진의 CPU 코어 수를 조정하려고했습니다. 1, 3, 4 및 6 코어를 시도했습니다. 도커로 제한하면 CPU 사용량이 100 %에서 60 %로 감소했습니다.
Joe

답변:


5

나는 같은 문제를 가지고있다. 모든 볼륨을 제거한 후 CPU %가 정상으로 돌아갔습니다.

docker system prune --volumes

또한 일부 명명 된 볼륨을 수동으로 제거했습니다.

docker volume rm NameOfVolumeHere

Docker for mac에서 볼륨을 사용할 수 없다는 전반적인 문제는 해결되지 않습니다. 지금은 사용중인 볼륨의 양에주의하고 Docker 데스크탑을 사용하지 않을 때 닫는 중입니다.


3

문제는 IO와 관련이 있다는 것입니다. MacOS 볼륨의 경우 여기에는 수행 할 수있는 성능 조정이있는 osxfs가 포함됩니다. 기본적으로 일관성 검사를 적게받을 수있는 경우 delegated성능을 높이기 위해 볼륨 모드를 설정할 수 있습니다 . 자세한 내용은 문서를 참조하십시오 : https://docs.docker.com/docker-for-mac/osxfs-caching/ . 그러나 이미지에 많은 수의 작은 파일이 포함 된 경우 특히 이미지 레이어가 많은 경우 성능이 저하됩니다.

도 커가 사용하는 내장 VM 내에서 프로세스 문제를 디버깅하기 위해 다음 명령을 시도 할 수도 있습니다.

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

(종료하려면을 사용하십시오 <ctrl>-c)


IO인지 추적하려면 다음을 시도하십시오.

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

이는 VM pid 네임 스페이스에서 실행중인 알파인 컨테이너 내에서 실행되며 해당 프로세스가 컨테이너 내부에 있는지 여부에 관계없이 모든 프로세스에서 발생하는 IO를 표시합니다. 통계는 1 분 (12 회) 동안 5 초마다이며 프로세스 당 평균 테이블을 제공합니다. 그런 다음 <ctrl>-d알파인 컨테이너를 파괴 할 수 있습니다 .


의견 및 수정 사항에서 이러한 통계를 확인할 수 있습니다. 4 코어 MBP에는 8 개의 스레드가 있으므로 MacOS가 다른 Unix 기반 시스템과 동일하게보고하는 경우 전체 CPU 사용률은 800 % 여야합니다. VM 내부에는 지난 분 평균 (5 및 15 평균보다 적음)의 최상위 명령에 100 % 이상의로드가 표시되어 호스트의 하이퍼 킷 프로세스에 대해 대략적으로 볼 수 있습니다. 시스템 및 사용자 백분율을 추가해야하므로 즉각적인 사용량은 3 %가 아니라 12 % 이상입니다. 그리고 pidstat에 표시된 IO 번호는 qcow2 이미지에 기록 된 것과 대략 일치합니다.


도커 엔진 자체가 스 래싱하는 경우 (예 : 컨테이너 다시 시작 또는 많은 상태 확인 실행) 다음의 출력을보고이를 디버깅 할 수 있습니다.

docker events

모든 볼륨 마운트를로 변경 delegated했지만 성능이 향상되지 않았습니다. top임베디드 VM 에서 명령을 실행 했지만 CPU 사용량이 ~ 3 % 정도였습니다.
Joe

pidstatIO 문제를 더 잘 추적하도록 업데이트되었습니다 .
BMitch

pidstat모든 PID의 판독 값이 0kB / s임을 나타냅니다. 쓰기의 경우 : logwrite평균 influxd8.5kB / s를 쓰고 평균 0.61kB / s를 씁니다. 나머지 프로세스는 0입니다.
Joe

1

이것은 커널이 시간을 보내는 곳을 찾는 데 사용하는 작은 dTrace 스크립트입니다 (Solaris에서 왔으며 Solaris 10의 초기 시절로 거슬러 올라갑니다).

#!/usr/sbin/dtrace -s

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

단순히 커널 스택 추적을 샘플링하고 @hot집계 에서 발생하는 각 추적을 계산합니다 .

루트로 실행하십시오.

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

CPU 문제가있는 동안 적절한 시간 동안 실행 한 다음 CTRL-C스크립트를 중단하십시오. 가장 일반적으로 발생한 모든 커널 스택 추적을 내 보냅니다. 기본에서 스택 프레임이 더 많거나 적은 경우

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

스택 프레임 15 호출 깊이를 보여줍니다.

마지막 몇 스택 추적은 커널이 대부분의 시간을 소비하는 곳입니다. 유익한 정보 일 수도 있고 아닐 수도 있습니다.

이 스크립트는 사용자 공간 스택 추적에 대해 동일한 작업을 수행합니다.

#!/usr/sbin/dtrace -s

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

비슷하게 실행하십시오.

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

ustack() dTrace는 실제 함수 이름을 내보내려면 적절한 프로세스의 주소 공간에서 더 많은 작업을 수행해야합니다.

시스템 무결성 보호를 비활성화 하면 더 나은 스택 추적을 얻는 데 도움이 될 수 있습니다.

자세한 내용은 DTrace Action Basics 를 참조하십시오.


감사합니다. 스크립트 결과로 질문을 업데이트했습니다. 사용자 공간 스택 추적은 com.docker.hyperkit이 많은 스레드를 작성 함을 보여줍니다.
Joe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.