web-dev-qa-db-ja.com

xfs、20ディスク、Cephを搭載した「大規模」サーバーでのページ断片化の原因

Linuxの経験が少しある人からの洞察は、IOシステムで役立つでしょう。ここに私の話があります。

最近、Ceph経由でファイルを提供するために6つのDell PowerEdge rx720xdsのクラスタを立ち上げました。これらのマシンは、2つのnumaゾーンと70個の奇数ギガバイトのメモリを備えた2つのソケット上に24コアを備えています。ディスクはそれぞれ1つのディスクの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,noatime,attr2,inode64,noquota 0 0
/dev/sdu1 /var/lib/ceph/osd/ceph-99 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdd1 /var/lib/ceph/osd/ceph-82 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdk1 /var/lib/ceph/osd/ceph-88 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdl1 /var/lib/ceph/osd/ceph-89 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdh1 /var/lib/ceph/osd/ceph-86 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdo1 /var/lib/ceph/osd/ceph-97 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdc1 /var/lib/ceph/osd/ceph-81 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdb1 /var/lib/ceph/osd/ceph-80 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sds1 /var/lib/ceph/osd/ceph-98 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdn1 /var/lib/ceph/osd/ceph-91 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sde1 /var/lib/ceph/osd/ceph-83 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdq1 /var/lib/ceph/osd/ceph-93 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdg1 /var/lib/ceph/osd/ceph-85 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdt1 /var/lib/ceph/osd/ceph-95 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdf1 /var/lib/ceph/osd/ceph-84 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdr1 /var/lib/ceph/osd/ceph-94 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdi1 /var/lib/ceph/osd/ceph-96 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdp1 /var/lib/ceph/osd/ceph-92 xfs rw,noatime,attr2,inode64,noquota 0 0

IOこれらのマシンを通過すると、数百MB /秒でバーストしますが、ほとんどの場合、多くの小さな「突っ込み」でかなりアイドル状態です:

# 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時間後、隣接するページが断片化されるため、4つの割り当て(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 

断片化がかなり悪化すると、システムはカーネル空間で回転し始め、すべてがばらばらになります。この障害時の1つの異常は、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 [023] .... 19509.445609: mm_vmscan_direct_reclaim_end: nr_reclaimed=1

Vmstatの出力も関係しています。システムがこの高負荷状態にある間、コンパクションは屋根を通過します(そしてほとんどが失敗します)。

pgmigrate_success 38760827 pgmigrate_fail 350700119 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

18
pingu

コメントが多いので観察で答えると思いました。

https://Gist.github.com/christian-marie/7bc845d2da7847534104 の出力に基づいて

以下を決定できます。

  1. 試行されたメモリ割り当てのGFP_MASKは、次のことを実行できます。
    • 緊急プールにアクセスできます(Ithinkこれは、ゾーンの最高水準点より下のデータにアクセスすることを意味します)
    • 緊急予備を使用しないでください(Ithinkこれは、最小透かしの下のmemroyへのアクセスを許可しないことを意味します)
    • 通常のゾーンの1つから割り当てます。
    • スペースを確保するために交換できます。
    • スペースを空けるためにキャッシュをドロップできます。

ゾーンの断片化はここにあります:

[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以上である5以上は、高次割り当ての断片化と飢餓を示します。

私は現在、この期間の断片化がスラブキャッシュと関係があることを示唆する確かな程度の証拠を見ていません。結果のメモリ統計では、次のことがわかります

Node 0 = active_anon:9694208kB inactive_anon:1054236kB
Node 1 = active anon:11371988kB inactive_anon:1172444kB

ユーザースペースから割り当てられた巨大なページはないため、ユーザースペースは常に注文0のメモリを要求します。したがって、両方のゾーンで22GiBを超えるデフラグ可能なメモリが存在します。

説明できない行動

高次の割り当てが失敗した場合、高次のメモリ割り当ての領域を実行して成功させるために、メモリの圧縮が常に試行されていると理解しています。なぜこれが起こらないのですか?それが発生した場合、並べ替えに適した22GiBのメモリがあるのに、デフラグするメモリが見つからないのはなぜですか?

私が説明できると思う行動

これを正しく理解するにはさらに調査が必要ですが、ページキャッシュを自動的にスワップ/ドロップする割り当ての機能は、まだ十分に利用できる空きメモリがあるため、おそらくここでは適用されず、再利用は発生しないと思います。高次では十分ではありません。

多くの空きメモリおよび各ゾーンに残っているいくつかの注文4リクエストがある一方で、「各注文の合計空きメモリの合計と実際の空きメモリから差し引く」という問題は、実際の割り当てエラーの原因となる「最低」ウォーターマークの下の「空きメモリ」。

4
Matthew Ife