美文网首页容器及linux内核技术
docker容器的内存问题排查(“内存丢失”)

docker容器的内存问题排查(“内存丢失”)

作者: zhangzhifei | 来源:发表于2019-12-20 16:50 被阅读0次

    场景描述

    容器内可用内存远没有达到cgroup限制,就已经OOM(Out Of Memory Killer)。容器套餐4c8g,top看占内存最多的进程大约17m左右,总共100个,总内存也不到2g,但是memory.usage_in_bytes已经达到8g(free看也是一样),cache也只有几百兆,久而久之,cache所占内存也被耗尽,容器内进程oom,实际可用内存不到1g。在这记录下问题排查过程。

    排查问题容器环境

    由于达到oom的现场已经不在,现在使用下面的场景进行演示:
    容器套餐4c8g,working_set内存6.8g(容器内一般用working_set来评内存使用情况,working_set=rss+活跃的cache),rss600m,cache1.7g,业务进程使用2g。目前working_set远小于rss+cache。

    排查过程

    1. 进容器看看业务进程消耗资源
      docker exec进到容器top后输入M(大写M),查看消耗内存最多的进程
    top - 15:12:57 up 7 days,  1:00,  1 user,  load average: 0.24, 0.08, 0.02
    Tasks: 145 total,   1 running, 144 sleeping,   0 stopped,   0 zombie
    Cpu(s):  1.0%us,  0.0%sy,  0.0%ni, 99.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
    Mem:   8192000k total,  7724968k used,   467032k free,        0k buffers
    Swap:        0k total,        0k used,        0k free,  1745040k cached
    
      PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                   204 root      20   0 2527m  19m 3140 S  0.0  0.2   0:43.40 docker-qalarm                                            
    35382 nobody    20   0  306m  17m 9.8m S  0.0  0.2   0:20.51 php-fpm                                                  
    35373 nobody    20   0  306m  17m 9984 S  0.0  0.2   0:20.88 php-fpm                                                  
    35444 nobody    20   0  306m  17m 9964 S  0.0  0.2   0:20.55 php-fpm                                                  
    35350 nobody    20   0  306m  17m 9936 S  0.0  0.2   0:20.44 php-fpm                                                  
    35407 nobody    20   0  306m  17m 9976 S  0.0  0.2   0:20.22 php-fpm                                                  
    35392 nobody    20   0  306m  17m 9924 S  0.0  0.2   0:20.33 php-fpm                                                  
    35368 nobody    20   0  306m  17m 9916 S  0.0  0.2   0:20.22 php-fpm                                                  
    35398 nobody    20   0  306m  17m 9908 S  0.0  0.2   0:20.27 php-fpm                                                  
    35357 nobody    20   0  306m  17m 9912 S  0.3  0.2   0:20.94 php-fpm                                                  
    35463 nobody    20   0  306m  17m 9912 S  0.0  0.2   0:20.22 php-fpm                                                  
    35437 nobody    20   0  306m  17m 9900 S  0.0  0.2   0:21.09 php-fpm                                                  
    35464 nobody    20   0  306m  17m 9896 S  0.0  0.2   0:20.46 php-fpm                                                  
    35384 nobody    20   0  306m  17m 9888 S  0.3  0.2   0:19.90 php-fpm                                                  
    35348 nobody    20   0  306m  17m 9876 S  0.0  0.2   0:20.53 php-fpm                                                  
    35365 nobody    20   0  306m  17m 9880 S  0.0  0.2   0:20.71 php-fpm                                                  
    35358 nobody    20   0  306m  17m 9868 S  0.0  0.2   0:20.42 php-fpm                                                  
    35420 nobody    20   0  306m  17m 9892 S  0.0  0.2   0:19.88 php-fpm                                                  
    35424 nobody    20   0  306m  17m 9864 S  0.0  0.2   0:20.52 php-fpm                                                  
    35389 nobody    20   0  306m  17m 9872 S  0.0  0.2   0:20.18 php-fpm                                                  
    35335 nobody    20   0  306m  17m 9908 S  0.0  0.2   0:20.84 php-fpm                                                  
    35468 nobody    20   0  306m  17m 9912 S  0.3  0.2   0:20.58 php-fpm
    
    [root@robot-speaker-e862e0-7c84fb65cd-whv5d /home/q/system/speaker-robot]# ps -ef | grep php-fpm|grep -v grep|wc -l
    129
    

    发现使用内存最多的php-fpm 进程用了17M,129个进程,一共使用内存2.1g。内存使用了7.4g、未使用450M、cache1.7g(我们使用了lxcfs做容器视图隔离,所以内存显示的是容器的真实情况),还有5g左右内存去哪了
    2、进到内存容器cgroup

    7af95a9ac99dd32c8bc51aa4531f75a836d1b5e6c29]# ls
    cgroup.clone_children           memory.kmem.tcp.max_usage_in_bytes  memory.oom_control
    cgroup.event_control            memory.kmem.tcp.usage_in_bytes      memory.pressure_level
    cgroup.procs                    memory.kmem.usage_in_bytes          memory.soft_limit_in_bytes
    memory.failcnt                  memory.limit_in_bytes               memory.stat
    memory.force_empty              memory.max_usage_in_bytes           memory.swappiness
    memory.kmem.failcnt             memory.memsw.failcnt                memory.usage_in_bytes
    memory.kmem.limit_in_bytes      memory.memsw.limit_in_bytes         memory.use_hierarchy
    memory.kmem.max_usage_in_bytes  memory.memsw.max_usage_in_bytes     notify_on_release
    memory.kmem.slabinfo            memory.memsw.usage_in_bytes         tasks
    memory.kmem.tcp.failcnt         memory.move_charge_at_immigrate
    memory.kmem.tcp.limit_in_bytes  memory.numa_stat
    [root@docker123 /sys/fs/cgroup/memory/kubepods/burstable/pod6e726ccc-1d6f-11ea-851f-fa163e9a7739/45bb864dfe68379c6d2f07af95a9ac99dd32c8bc51aa4531f75a836d1b5e6c29]#
    
    • 查看 memory.usage_in_bytes
    7af95a9ac99dd32c8bc51aa4531f75a836d1b5e6c29]# cat  memory.usage_in_bytes
    7934582784
    

    确实是7g多

    • 查看内存使用情况memory.stat
    7af95a9ac99dd32c8bc51aa4531f75a836d1b5e6c29]# cat memory.stat
    cache 1806925824
    rss 622092288
    rss_huge 287309824
    mapped_file 20508672
    swap 0
    pgpgin 17583007
    pgpgout 17135620
    pgfault 48558141
    pgmajfault 1180
    inactive_anon 17465344
    active_anon 628965376
    inactive_file 1058193408
    active_file 724385792
    unevictable 0
    hierarchical_memory_limit 8388608000
    hierarchical_memsw_limit 16777216000
    total_cache 1806925824
    total_rss 622092288
    total_rss_huge 287309824
    total_mapped_file 20508672
    total_swap 0
    total_pgpgin 17583007
    total_pgpgout 17135620
    total_pgfault 48558141
    total_pgmajfault 1180
    total_inactive_anon 17465344
    total_active_anon 628965376
    total_inactive_file 1058193408
    total_active_file 724385792
    total_unevictable 0
    

    没有占用内存特别大的项,也就是远没达到top所见。另外忘记说,上边单位都是字节

    • 查看容器的内核内存使用量memory.kmem.usage_in_bytes
    7af95a9ac99dd32c8bc51aa4531f75a836d1b5e6c29]# cat memory.kmem.usage_in_bytes
    5513891840
    

    果然是5g

    • 现在看下容器使用内核slab情况memory.kmem.slabinfo
    7af95a9ac99dd32c8bc51aa4531f75a836d1b5e6c29]# cat memory.kmem.slabinfo
    slabinfo - version: 2.1
    ...
    taskstats           1960   1960    328   49    4 : tunables    0    0    0 : slabdata     40     40      0
    xfs_ili           3945336 3945336    168   48    2 : tunables    0    0    0 : slabdata  82195  82195      0
    xfs_btree_cur       1560   1560    208   39    2 : tunables    0    0    0 : slabdata     40     40      0
    posix_timers_cache  16071  16071    248   33    2 : tunables    0    0    0 : slabdata    487    487      0
    scsi_cmd_cache      1440   1440    448   36    4 : tunables    0    0    0 : slabdata     40     40      0
    xfs_log_ticket      1760   1760    184   44    2 : tunables    0    0    0 : slabdata     40     40      0
    cfq_queue           1400   1400    232   35    2 : tunables    0    0    0 : slabdata     40     40      0
    inode_cache         2200   2200    592   55    8 : tunables    0    0    0 : slabdata     40     40      0
    radix_tree_node    35635  39984    584   28    4 : tunables    0    0    0 : slabdata   1428   1428      0
    bio-2               2040   2040    320   51    4 : tunables    0    0    0 : slabdata     40     40      0
    fanotify_event_info   2920   2920     56   73    1 : tunables    0    0    0 : slabdata     40     40      0
    blkdev_ioc          1560   1560    104   39    1 : tunables    0    0    0 : slabdata     40     40      0
    xfs_inode         3959772 3959772    960   34    8 : tunables    0    0    0 : slabdata 116478 116478      0
    Acpi-ParseExt       2240   2240     72   56    1 : tunables    0    0    0 : slabdata     40     40      0
    ...
    

    可以看出关于文件元数据缓存就占了4g多,上图第三列是对象数量,第四列是对象大小,所以xfs_inode占用内存=3959772 * 960 /1024/1024/1024,约等于3.5g,xfs_ili 0.7g,这已经4g多了。所以基本可以断定是业务进程操作文件多过导致

    • 查看容器内是否有大量小文件
    [root@robot-speaker-e862e0-7c84fb65cd-whv5d /data/php/session]# ls -lR | grep "^-"| wc -l
    3941117
    

    可见session文件数与slab中的xfs_inode基本相当,所以可以断定罪魁祸首在此

    • 随着session文件越来越多,xfs_inode占用slab内存越来越多,不可回收SUnreclaim也会越来越大,所以最终会导致可用内存越来越少

    验证结果

    经过与业务沟通,他们清理的大量session文件后,slab内存明显降下来了。


    image.png

    结论

    1. 业务应尽可能的避免这种上百万级别的小文件
    2. 更优雅的方式是限制容器内可用内核缓存的比例(还在尝试)

    参考文档

    https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/6/html/resource_management_guide/sec-memory
    https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/memory.html
    https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html

    相关文章

      网友评论

        本文标题:docker容器的内存问题排查(“内存丢失”)

        本文链接:https://www.haomeiwen.com/subject/dfgbnctx.html