【问题标题】:Diagnosing high CPU usage on Docker for Mac诊断 Docker for Mac 上的高 CPU 使用率
【发布时间】:2020-02-05 05:39:17
【问题描述】:

如何在 MacOS 上诊断 Docker 的原因,特别是 com.docker.hyperkit 使用 100% 的 CPU?

Docker 统计数据

Docker stats 显示所有正在运行的容器的 CPU、内存、网络 IO 和块 IO 都很低。

iosnoop

iosnoop 显示com.docker.hyperkit 每秒对文件Docker.qcow2 执行大约50 次写入,总计每秒500KB。根据What is Docker.qcow2?Docker.qcow2 是一个稀疏文件,是所有 Docker 容器的持久存储。

在我的情况下,文件不是那么稀疏。物理大小与逻辑大小匹配。

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

更新:Docker 主机上的top

来自https://stackoverflow.com/a/58293240/30900

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

docker 嵌入式主机的 CPU 使用率约为 3%。我的 MacBook 上的 CPU 使用率约为 100%。因此,docker 嵌入式主机不会导致 CPU 使用率飙升。

更新:运行最常见堆栈跟踪的 dtrace 脚本

来自以下答案中的 dtrace 脚本的堆栈跟踪:https://stackoverflow.com/a/58293035/30900

这些内核堆栈跟踪看起来无害。

              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 usage is back again #3499 。一条评论建议添加此处描述的卷缓存:https://www.docker.com/blog/user-guided-caching-in-docker-for-mac/。我试过了,CPU 使用率降低了约 10%。

【问题讨论】:

  • 您在构建图像吗?我还将专注于执行大量块 IO 的容器。是否启用 Kubernetes 也很重要。
  • 我在集群构建并运行几分钟后收集了所有指标。 Kubernetes 已禁用。但是,没有一台机器执行大量的块 IO。容器没有做任何事情。我注意到 CPU 使用率似乎与容器数量大致相关。
  • 你的机器有多少个内核/cpu?
  • 另外,您是否尝试过重启 docker,而不是容器,而是整个引擎和桌面客户端?
  • 我运行的是 2018 MBP 2.8 GHz Core i7,有 4 个内核。我尝试调整 Docker 引擎的 CPU 内核数量。我尝试了 1、3、4 和 6 核。限制为 docker 将 CPU 使用率从 100% 降低到 60%。

标签: macos docker profiling dtrace


【解决方案1】:

我找到的解决方案是增加分配给 Docker 的资源。我将内存从 2GB 增加到 8GB,将交换从 1GB 增加到 2GB,磁盘映像大小增加到 160GB。彻底解决了我的问题,读者可以轻松尝试。

【讨论】:

    【解决方案2】:

    这是一个小的 dTrace 脚本,我用它来查找内核在哪里花费时间(它来自 Solaris,并且可以追溯到 Solaris 10 的早期):

    #!/usr/sbin/dtrace -s
    
    profile:::profile-1001hz
    /arg0/
    {
        @[ stack() ] = count();
    }
    

    它只是对内核堆栈跟踪进行采样,并对在@ 聚合中遇到的每个跟踪进行计数。

    以root身份运行:

    ... # ./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 必须做更多的工作才能从相应进程的地址空间中获取它们。

    Disabling System Integrity Protection 可能会帮助您获得更好的堆栈跟踪。

    有关更多详细信息,请参阅DTrace Action Basics

    【讨论】:

    • 谢谢,我用脚本的结果更新了问题。用户空间堆栈跟踪显示 com.docker.hyperkit 创建了很多线程。
    【解决方案3】:

    禁用use gRPC FUSE for file sharing 可能不是一个好主意。我从 docker 社区提出的另一个问题中找到了反馈。见下文:

    
    So we'll look into that. However, 
    osxfs will not be supported long term. 
    We can't maintain two solutions.
    

    hier to docker issue thread

    【讨论】:

      【解决方案4】:

      编辑:几周后,我的 cpu 问题又回来了 - 所以下面的解决方案可能不值得

      我的 CPU 一直在疯狂地运行,而不是 I/O,正如使用 docker stats 确定的那样

      我做了很多事情,但在执行以下操作后,它突然降低到合理的水平并保持这种状态超过一周:

      • 确保您拥有正确的 CPU 集数量 - 不是您拥有的数量,而是该数量的一半。我的超过了一半,我觉得这是真正的问题,在Preferences | Resources
      • 尽可能减少文件共享的数量 - Preferences | Resources、/private、/tmp/、/var/folders
      • 禁用use gRPC FUSE for file sharing - Preferences | Resources

      【讨论】:

      • 禁用 gRPC 保险丝安装对我有用。 CPU 从 120% 提高到 25%
      • +1。没有什么对我有用,但你的第 2 点有效,删除了一些份额,然后从 200% 减少到 18%
      【解决方案5】:

      更改卷以使用委派配置对我有用,并导致 CPU 使用率急剧下降。 见文档:https://docs.docker.com/docker-for-mac/osxfs-caching/#delegated

      如何在我的 docker-compose.yml 中设置:

      version: "3"
      services: 
        my_service:
          image: python3.6
          ports:
            - "80:10000"
          volumes:
            - ./code:/www/code:cached
      

      对我来说,macOS 10.15.5、Docker Desktop 2.3.0 有效

      【讨论】:

        【解决方案6】:

        我也有同样的问题。删除所有卷后,我的 CPU % 恢复正常。

        docker system prune --volumes
        

        我还手动删除了一些命名卷:

        docker volume rm NameOfVolumeHere
        

        这并不能解决无法将卷与 Docker for mac 一起使用的整体问题。现在我只是小心我使用的卷数量并在不使用时关闭 Docker 桌面。

        【讨论】:

        • 救了我的培根。做得好。 macos bigsur
        【解决方案7】:

        我怀疑这个问题与 IO 有关。对于 MacOS 卷,这涉及到 osxfs,您可以在其中执行一些性能调整。主要是,如果你能接受更少的一致性检查,你可以将音量模式设置为delegated以获得更快的性能。有关详细信息,请参阅文档:https://docs.docker.com/docker-for-mac/osxfs-caching/。但是,如果您的图像包含大量小文件,性能就会受到影响,尤其是如果您还有很多图像层。

        您还可以尝试以下命令来调试 docker 使用的嵌入式 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 命名空间中的 alpine 容器内运行,显示任何进程发生的任何 IO,无论该进程是否在容器内。统计信息是每 5 秒一分钟(12 次),然后它将为您提供每个进程的平均表。然后您可以<ctrl>-d 销毁 alpine 容器。


        从 cmets 和编辑中,这些统计数据可能会检查出来。一个 4 核 MBP 有 8 个线程,因此如果 MacOS 报告的与其他基于 Unix 的系统相同,则 CPU 利用率应为 800%。在虚拟机内部,top 命令显示过去一分钟的平均负载超过 100%(尽管比 5 和 15 的平均值要少),这与您在主机上的 hyperkit 进程中看到的大致相同。由于您需要添加系统和用户百分比,因此瞬时使用率从顶部开始超过 12%,而不是 3%。 pidstat 中显示的 IO 编号与您看到的写入 qcow2 映像的内容大致一致。


        如果 docker 引擎本身正在抖动(例如,重新启动容器或运行大量健康检查),那么您可以通过查看以下输出进行调试:

        docker events
        

        【讨论】:

        • 我将所有卷挂载都更改为delegated,但没有性能提升。我在嵌入式 VM 上运行了 top 命令,但 CPU 使用率徘徊在 ~3% 左右。
        • 更新为pidstat 以更好地跟踪 IO 问题。
        • pidstat 显示所有 PID 的读取速度均为 0 kB/s。对于写入:logwrite 平均写入 8.5kB/s,influxd 平均写入 0.61kB/s。其余进程为0。
        • 提供的文档链接似乎没有在任何地方提到delegated(或者至少页面中的 cmd+F 似乎没有找到它)。是否有相关文档的更新链接?
        • @AdamParkin Docker 自发布此答案以来至少重新设计了一次文件系统层,因此看起来 osxfs 已从文档中删除。 delegated 选项在当前版本中可能会被忽略,所以我会跳过它并查看其他性能调试步骤。
        猜你喜欢
        • 2010-12-06
        • 2011-05-10
        • 2020-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多