最近推出了六个Dell PowerEdge rx720xds集群,通过Ceph提供文件服务.这些机器有24个核心,两个插座,两个numa区域和70奇数千兆字节的内存.磁盘被格式化为每个磁盘的raid(我们无法看到直接暴露它们的方式).网络由mellanox infiniband IP over IB提供(IP数据包在内核域而不是硬件中转换为IB).
我们安装了每个SAS驱动器,如下所示:
# cat /proc/mounts | grep osd /dev/sdm1 /var/lib/ceph/osd/ceph-90 xfs rw,noatime,attr2,inode64,noquota 0 0 /dev/sdj1 /var/lib/ceph/osd/ceph-87 xfs rw,noquota 0 0 /dev/sdu1 /var/lib/ceph/osd/ceph-99 xfs rw,noquota 0 0 /dev/sdd1 /var/lib/ceph/osd/ceph-82 xfs rw,noquota 0 0 /dev/sdk1 /var/lib/ceph/osd/ceph-88 xfs rw,noquota 0 0 /dev/sdl1 /var/lib/ceph/osd/ceph-89 xfs rw,noquota 0 0 /dev/sdh1 /var/lib/ceph/osd/ceph-86 xfs rw,noquota 0 0 /dev/sdo1 /var/lib/ceph/osd/ceph-97 xfs rw,noquota 0 0 /dev/sdc1 /var/lib/ceph/osd/ceph-81 xfs rw,noquota 0 0 /dev/sdb1 /var/lib/ceph/osd/ceph-80 xfs rw,noquota 0 0 /dev/sds1 /var/lib/ceph/osd/ceph-98 xfs rw,noquota 0 0 /dev/sdn1 /var/lib/ceph/osd/ceph-91 xfs rw,noquota 0 0 /dev/sde1 /var/lib/ceph/osd/ceph-83 xfs rw,noquota 0 0 /dev/sdq1 /var/lib/ceph/osd/ceph-93 xfs rw,noquota 0 0 /dev/sdg1 /var/lib/ceph/osd/ceph-85 xfs rw,noquota 0 0 /dev/sdt1 /var/lib/ceph/osd/ceph-95 xfs rw,noquota 0 0 /dev/sdf1 /var/lib/ceph/osd/ceph-84 xfs rw,noquota 0 0 /dev/sdr1 /var/lib/ceph/osd/ceph-94 xfs rw,noquota 0 0 /dev/sdi1 /var/lib/ceph/osd/ceph-96 xfs rw,noquota 0 0 /dev/sdp1 /var/lib/ceph/osd/ceph-92 xfs rw,noquota 0 0
通过这些机器的IO以几百MB / s的速度突发,但大部分时间都很闲置,有很多小“捅”:
# iostat -x -m Linux 3.10.0-123.el7.x86_64 (xxx) 07/11/14 _x86_64_ (24 cpu) avg-cpu: %user %nice %system %iowait %steal %idle 1.82 0.00 1.05 0.11 0.00 97.02 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sda 0.00 0.11 0.25 0.23 0.00 0.00 27.00 0.00 2.07 3.84 0.12 0.61 0.03 sdb 0.02 0.57 3.49 2.28 0.08 0.14 77.18 0.01 2.27 2.99 1.18 1.75 1.01 sdd 0.03 0.65 3.93 3.39 0.10 0.16 70.39 0.01 1.97 2.99 0.79 1.57 1.15 sdc 0.03 0.60 3.76 2.86 0.09 0.13 65.57 0.01 2.10 3.02 0.88 1.68 1.11 sdf 0.03 0.63 4.19 2.96 0.10 0.15 73.51 0.02 2.16 3.03 0.94 1.73 1.24 sdg 0.03 0.62 3.93 3.01 0.09 0.15 70.44 0.01 2.06 3.01 0.81 1.66 1.15 sde 0.03 0.56 4.35 2.61 0.10 0.14 69.53 0.02 2.26 3.00 1.02 1.82 1.26 sdj 0.02 0.73 3.67 4.74 0.10 0.37 116.06 0.02 1.84 3.01 0.93 1.31 1.10 sdh 0.03 0.62 4.31 3.04 0.10 0.15 67.83 0.02 2.15 3.04 0.89 1.75 1.29 sdi 0.02 0.59 3.82 2.47 0.09 0.13 74.35 0.01 2.20 2.96 1.03 1.76 1.10 sdl 0.03 0.59 4.75 2.46 0.11 0.14 70.19 0.02 2.33 3.02 1.00 1.93 1.39 sdk 0.02 0.57 3.66 2.41 0.09 0.13 73.57 0.01 2.20 3.00 0.97 1.76 1.07 sdm 0.03 0.66 4.03 3.17 0.09 0.14 66.13 0.01 2.02 3.00 0.78 1.64 1.18 sdn 0.03 0.62 4.70 3.00 0.11 0.16 71.63 0.02 2.25 3.01 1.05 1.79 1.38 sdo 0.02 0.62 3.75 2.48 0.10 0.13 76.01 0.01 2.16 2.94 0.99 1.70 1.06 sdp 0.03 0.62 5.03 2.50 0.11 0.15 68.65 0.02 2.39 3.08 0.99 1.99 1.50 sdq 0.03 0.53 4.46 2.08 0.09 0.12 67.74 0.02 2.42 3.04 1.09 2.01 1.32 sdr 0.03 0.57 4.21 2.31 0.09 0.14 72.05 0.02 2.35 3.00 1.16 1.89 1.23 sdt 0.03 0.66 4.78 5.13 0.10 0.20 61.78 0.02 1.90 3.10 0.79 1.49 1.47 sdu 0.03 0.55 3.93 2.42 0.09 0.13 70.77 0.01 2.17 2.97 0.85 1.79 1.14 sds 0.03 0.60 4.11 2.70 0.10 0.15 74.77 0.02 2.25 3.01 1.10 1.76 1.20 sdw 1.53 0.00 0.23 38.90 0.00 1.66 87.01 0.01 0.22 0.11 0.22 0.05 0.20 sdv 0.88 0.00 0.16 28.75 0.00 1.19 84.55 0.01 0.24 0.10 0.24 0.05 0.14 dm-0 0.00 0.00 0.00 0.00 0.00 0.00 8.00 0.00 1.84 1.84 0.00 1.15 0.00 dm-1 0.00 0.00 0.23 0.29 0.00 0.00 23.78 0.00 1.87 4.06 0.12 0.55 0.03 dm-2 0.00 0.00 0.01 0.00 0.00 0.00 8.00 0.00 0.47 0.47 0.00 0.45 0.00
问题:
大约48小时后,连续页面碎片化,以至于四个(16页,65536字节)分配开始失败,我们开始丢弃数据包(由于在生成SLAB时kalloc失败).
这是一个相对“健康”的服务器看起来像:
# cat /sys/kernel/debug/extfrag/unusable_index Node 0,zone DMA 0.000 0.000 0.000 0.001 0.003 0.007 0.015 0.031 0.031 0.096 0.225 Node 0,zone DMA32 0.000 0.009 0.015 0.296 0.733 0.996 0.997 0.998 0.998 1.000 1.000 Node 0,zone Normal 0.000 0.000 0.019 0.212 0.454 0.667 0.804 0.903 0.986 1.000 1.000 Node 1,zone Normal 0.000 0.027 0.040 0.044 0.071 0.270 0.506 0.772 1.000 1.000 1.000
当碎片变得更糟时,系统似乎开始在内核空间中旋转,一切都崩溃了.在这次失败期间,一个异常现象是xfsaild似乎使用了大量的cpu并陷入了不间断的睡眠状态.但是,我不想在整个系统故障期间以奇怪的方式得出任何结论.
迄今为止的解决方法.
为了确保这些分配不会失败,即使在碎片化的情况下,我设置:
vm.min_free_kbytes = 16777216
在SLAB缓存中看到数百万个blkdev_requests之后,我尝试通过以下方式减少脏页:
vm.dirty_ratio = 1 vm.dirty_background_ratio = 1 vm.min_slab_ratio = 1 vm.zone_reclaim_mode = 3
可能会同时更改太多变量,但是为了防止inode和dentries导致碎片化,我决定将它们保持在最低限度:
vm.vfs_cache_pressure = 10000
这似乎有所帮助.碎片仍然很高,减少的inode和dentry问题意味着我注意到一些奇怪的东西导致我……
我的问题:
为什么我有这么多blkdev_requests(活动不少),当我丢弃缓存时它会消失?
这就是我的意思:
# slabtop -o -s c | head -20 Active / Total Objects (% used) : 19362505 / 19431176 (99.6%) Active / Total Slabs (% used) : 452161 / 452161 (100.0%) Active / Total Caches (% used) : 72 / 100 (72.0%) Active / Total Size (% used) : 5897855.81K / 5925572.61K (99.5%) Minimum / Average / Maximum Object : 0.01K / 0.30K / 15.69K OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME 2565024 2565017 99% 1.00K 80157 32 2565024K xfs_inode 3295194 3295194 100% 0.38K 78457 42 1255312K blkdev_requests 3428838 3399527 99% 0.19K 81639 42 653112K dentry 5681088 5680492 99% 0.06K 88767 64 355068K kmalloc-64 2901366 2897861 99% 0.10K 74394 39 297576K buffer_head 34148 34111 99% 8.00K 8537 4 273184K kmalloc-8192 334768 334711 99% 0.57K 11956 28 191296K radix_tree_node 614959 614959 100% 0.15K 11603 53 92824K xfs_ili 21263 19538 91% 2.84K 1933 11 61856K task_struct 18720 18636 99% 2.00K 1170 16 37440K kmalloc-2048 32032 25326 79% 1.00K 1001 32 32032K kmalloc-1024 10234 9202 89% 1.88K 602 17 19264K TCP 22152 19765 89% 0.81K 568 39 18176K task_xstate # echo 2 > /proc/sys/vm/drop_caches :( # slabtop -o -s c | head -20 Active / Total Objects (% used) : 965742 / 2593182 (37.2%) Active / Total Slabs (% used) : 69451 / 69451 (100.0%) Active / Total Caches (% used) : 72 / 100 (72.0%) Active / Total Size (% used) : 551271.96K / 855029.41K (64.5%) Minimum / Average / Maximum Object : 0.01K / 0.33K / 15.69K OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME 34140 34115 99% 8.00K 8535 4 273120K kmalloc-8192 143444 20166 14% 0.57K 5123 28 81968K radix_tree_node 768729 224574 29% 0.10K 19711 39 78844K buffer_head 73280 8287 11% 1.00K 2290 32 73280K xfs_inode 21263 19529 91% 2.84K 1933 11 61856K task_struct 686848 97798 14% 0.06K 10732 64 42928K kmalloc-64 223902 41010 18% 0.19K 5331 42 42648K dentry 32032 23282 72% 1.00K 1001 32 32032K kmalloc-1024 10234 9211 90% 1.88K 602 17 19264K TCP 22152 19924 89% 0.81K 568 39 18176K task_xstate 69216 59714 86% 0.25K 2163 32 17304K kmalloc-256 98421 23541 23% 0.15K 1857 53 14856K xfs_ili 5600 2915 52% 2.00K 350 16 11200K kmalloc-2048
这告诉我blkdev_request构建实际上并不与脏页有关,而且活动对象实际上并不活跃?如果这些对象实际上没有被使用,它们如何被释放?这里发生了什么?
对于某些背景,这是drop_caches正在做的事情:
http://lxr.free-electrons.com/source/fs/drop_caches.c
更新:
确定他们可能不是blkdev_requests,但可能是xfs_buf条目显示在该’标题’下?不知道这是如何工作的:
/sys/kernel/slab # ls -l blkdev_requests( lrwxrwxrwx 1 root root 0 Nov 7 23:18 blkdev_requests -> :t-0000384/ /sys/kernel/slab # ls -l | grep 384 lrwxrwxrwx 1 root root 0 Nov 7 23:18 blkdev_requests -> :t-0000384/ lrwxrwxrwx 1 root root 0 Nov 7 23:19 ip6_dst_cache -> :t-0000384/ drwxr-xr-x 2 root root 0 Nov 7 23:18 :t-0000384/ lrwxrwxrwx 1 root root 0 Nov 7 23:19 xfs_buf -> :t-0000384/
我仍然不知道为什么这些被’drop_slabs’清除,或者如何解决造成这种碎片的原因.
奖金问题:什么是更好的方法来获得这种碎片的来源?
如果你读到这里,感谢你的关注!
额外要求的信息:
内存和xfs信息:
https://gist.github.com/christian-marie/f417cc3134544544a8d1
页面分配失败:
https://gist.github.com/christian-marie/7bc845d2da7847534104
跟进:执行信息和压缩相关的事情
http://ponies.io/raw/compaction.png
压缩代码似乎有点低效了吧?我把一些代码拼凑在一起试图复制失败的压缩:https://gist.github.com/christian-marie/cde7e80c5edb889da541
这似乎重现了这个问题.
我还要注意事件跟踪告诉我,有很多失败的回收,一遍又一遍:
< ...> -322 ……. 19509.445609:mm_vmscan_direct_reclaim_end:nr_reclaimed = 1
Vmstat输出也有关系.虽然系统处于这种高负载状态,但压缩通过屋顶(并且主要是失败):
pgmigrate_success 38760827
pgmigrate_fail 35https://gist.github.com/christian-marie/f417cc3134544544a8d119
compact_migrate_scanned 301784730
compact_free_scanned 204838172846
compact_isolated 18711615
compact_stall 270115
compact_fail 244488
compact_success 25212
回收/压实确实存在一些问题.
目前,我正在寻求通过在我们的ipoib设置中添加SG支持来减少高阶分配.真正的问题似乎与vmscan有关.
这很有趣,并引用了这个问题:http://marc.info/?l=linux-mm&m=141607142529562&w=2
解决方法
基于您在https://gist.github.com/christian-marie/7bc845d2da7847534104的输出
我们可以确定以下内容:
>尝试进行内存分配的GFP_MASK允许执行以下操作.
>可以访问紧急池(我认为这意味着访问区域的高水位线以下的数据)
>不要使用紧急储备(我认为这意味着不允许在最小水印下方访问memroy)
>从其中一个正常区域分配.
>可以交换以腾出空间.
>可以放下缓存以腾出空间.
区域碎片位于此处:
[3443189.780792] Node 0 Normal: 3300*4kB (UEM) 8396*8kB (UEM) 4218*16kB (UEM) 76*32kB (UEM) 12*64kB (M) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 151056kB [3443189.780801] Node 1 Normal: 26667*4kB (UEM) 6084*8kB (UEM) 2040*16kB (UEM) 96*32kB (UEM) 22*64kB (UEM) 4*128kB (U) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 192972kB
当时的内存利用率如下:
[3443189.780759] Node 0 Normal free:149520kB min:40952kB low:51188kB high:61428kB active_anon:9694208kB inactive_anon:1054236kB active_file:7065912kB inactive_file:7172412kB unevictable:0kB isolated(anon):5452kB isolated(file):3616kB present:30408704kB managed:29881160kB mlocked:0kB dirty:0kB writeback:0kB mapped:25440kB shmem:743788kB slab_reclaimable:1362240kB slab_unreclaimable:783096kB kernel_stack:29488kB pagetables:43748kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no [3443189.780766] Node 1 Normal free:191444kB min:45264kB low:56580kB high:67896kB active_anon:11371988kB inactive_anon:1172444kB active_file:8084140kB inactive_file:8556980kB unevictable:0kB isolated(anon):4388kB isolated(file):4676kB present:33554432kB managed:33026648kB mlocked:0kB dirty:0kB writeback:0kB mapped:45400kB shmem:2263296kB slab_reclaimable:1606604kB slab_unreclaimable:438220kB kernel_stack:55936kB pagetables:44944kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
页面分配失败输出中每个区域的碎片都很糟糕.有很多免费订单0页,更少订单页面更少.一个“好”的结果将是每个订单上的丰富的免费页面,随着您的订单越高,尺寸逐渐变小.具有0个高阶页面5及以上表示高阶分配的碎片和饥饿.
我目前没有看到令人信服的证据表明这一时期的碎片与板坯缓存有任何关系.在生成的内存统计信息中,我们可以看到以下内容
Node 0 = active_anon:9694208kB inactive_anon:1054236kB Node 1 = active anon:11371988kB inactive_anon:1172444kB
用户空间没有分配大页面,因此用户空间将始终声明订单0内存.因此,在两个区域中总共存在超过22GiB的可碎片化存储器.
行为我无法解释
当高阶分配失败时,我的理解是总是尝试进行内存压缩,以便允许高阶内存分配区域发生并成功.为什么这不会发生?如果它确实发生了,为什么当22GiB的重新排序成熟时,它没有找到任何内存进行碎片整理?
行为我认为我可以解释
这需要更多的研究才能正确理解,但我相信分配能够自动交换/删除一些页面缓存才能成功,这可能不适用于此,因为仍有大量可用内存,因此不会发生回收.高阶订单还不够.
虽然每个区域都有大量的空闲内存和一些订单4请求,但“每个订单的所有可用内存总量和从真实可用内存中扣除”问题会导致“最小”水印下方的“空闲内存”导致实际分配失败的原因.