• k8s 最佳实践:处理内存碎片化


    k8s 最佳实践:处理内存碎片化

    内存碎片化造成的危害

    节点的内存碎片化严重,导致docker运行容器时,无法分到大的内存块,导致start docker失败。最终导致服务更新时,状态一直都是启动中

    在长时间运行的Linux操作系统中,系统日志有时会出现无法分配高阶内存的报错信息:

    Aug  4 22:58:15 server1 kernel: : [69229257.683658] xenwatch: page allocation failure. order:4, mode:0xd0
    Aug  4 22:58:15 server1 kernel: : [69229257.683665] Pid: 168, comm: xenwatch Tainted: GF          ---------------    2.6.32-358.23.2.el5.x86_64 #1
    Aug  4 22:58:15 server1 kernel: : [69229257.683672] Call Trace:
    Aug  4 22:58:15 server1 kernel: : [69229257.683688]  [<ffffffff8112723a>] ? __alloc_pages_nodemask+0x67a/0x8c0
    Aug  4 22:58:15 server1 kernel: : [69229257.683697]  [<ffffffff8126082f>] ? number+0x2ff/0x330
    Aug  4 22:58:15 server1 kernel: : [69229257.683706]  [<ffffffff81162260>] ? kmem_getpages+0x60/0x150
    

    此时使用cat /proc/buddyinfo观察内存order分配情况,可以看到内存碎片化严重(大量的低阶内存页,但是几乎没有高阶内存页)

    #cat /proc/buddyinfo
    Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
    Node 0, zone    DMA32  32995   4377    762    211    157    108     68     23      3      0      0
    Node 0, zone   Normal 127146  68215   1614      0      0      0      0      0      0      0      1
    

    处理的方法主要采用drop_caches(抛弃缓存),然后使用compact_memory合并低阶内存页来创造出足够的高阶内存页。

    方案1:drop_caches

    Linux Kernel 2.6.16之后的内核提供了一个设置内核抛弃 页缓存 和/或 目录(dentry)和索引节点(inode)缓存,这样可以释放出大量内存。

    • 释放页缓存
    echo 1 > /proc/sys/vm/drop_caches
    
    • 释放目录和索引节点缓存(inode and dentry cache)
    echo 2 > /proc/sys/vm/drop_caches
    
    • 同时释放 页、目录、索引节点缓存:
    echo 3 > /proc/sys/vm/drop_caches
    

    上述操作是无害的操作,并且智慧释放完全没有使用的内存对象。脏对象(dirty objects)将继续被使用直到它们被写入到磁盘中,所以内存脏对象不会被释放。不过,如果在执行drop_caches之前执行sync指令,则会将脏对象刷新到磁盘中,这样drop_caches操作会释放出更多内存。

    注意:drop_caches需要花费一些时间(在终端中可以看到大约几十秒时间),此时再次使用cat /proc/buddyinfo可以看到立即出现了大量高阶内存页。

    但是drop_caches这个触发动作是一次性的,也就是说,并不因为cat /proc/sys/vm/drop_caches时显示输出内容是3就表示系统不缓存内容。相反,一旦完成drop_caches,系统立即自动对后续内存对象进行缓存。所以要再次触发缓存清理,需要再次执行 echo 3 > /proc/sys/vm/drop_caches

    如果重复echo 3 > /proc/sys/vm/drop_caches不能再次释放缓存,可以先尝试echo 0 > /proc/sys/vm/drop_caches然后再执行echo 3 > /proc/sys/vm/drop_caches

    方案2:compact_memory 内存整理

    当内核编译参数设置了CONFIG_COMPACTION,就会在/proc/sys/vm/compact_memory有入口文件。将1写入到这个文件,则所有的zones就会进行压缩,以便能够尽可能地提供连续内存块。对于需要分配大页的时候这个功能非常重要,不过,进程会在需要时直接进行内存压缩(compact memory)。

    必要时候进行内存整理,开销会比较大,会造成业务卡住一段时间(慎用):

    echo 1 > /proc/sys/vm/compact_memory
    

    实践案例

    • 检查系统缺乏高阶内存
    #cat /proc/buddyinfo
    Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
    Node 0, zone    DMA32  32995   4377    762    211    157    108     68     23      3      0      0
    Node 0, zone   Normal 127146  68215   1614      0      0      0      0      0      0      0      1
    
    • 执行缓存释放
    #echo 3 > /proc/sys/vm/drop_caches
    
    • 完成后检查内存页
    #cat /proc/buddyinfo
    Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
    Node 0, zone    DMA32  76826  65298  43784  20780   5272    616     90     32      4      0      0
    Node 0, zone   Normal 524538 365499 176074  45644   4338    140      6      0      0      0      1
    
    • 然后执行内存压缩
    #echo 1 > /proc/sys/vm/compact_memory
    
    • 然后再次检查内存页分布,可以看到逐渐出现更多的高阶内存页
    #cat /proc/buddyinfo
    Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
    Node 0, zone    DMA32  18217  13464   8621   4666   2654   2087   1609   1040    517    130      3
    Node 0, zone   Normal 145048 131183  76864  38454  20405  11854   5149   1143     96      3      1
    
  • 相关阅读:
    简单跟跟spring源码
    java.lang.UnsupportedOperationException mybatis
    通过自定义注解校验后台接口请求参数
    java的修饰符 public --> protected -->default --> private
    Ubuntu安装google-chrome
    git设置core.autocrlf
    时钟时间,系统cpu时间,用户cpu时间
    推荐-Everything搜索工具
    Ubuntu no such file or directory
    centos安装docker
  • 原文地址:https://www.cnblogs.com/yinbiao/p/16277209.html
Copyright © 2020-2023  润新知