Linux Kernel: cgroup 削除後も残り続ける slab キャッシュ についての調べ物

タイトルの通りで、コンテナの生成と削除が頻繁におこなわれているホストで、 cgroup 削除後も特定の slab キャッシュ ( + sysfs のファイル = kobject ) が残るという現象を調べていました

環境

vagrant@bionic:~$ uname -a
Linux bionic 5.4.1-050401-generic #201911290555 SMP Fri Nov 29 11:03:47 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

再現の方法

  • cgroup v1 + memory コントローラーでグループを作る
  • そのグループ内で適当なファイルを作成する
  • cgroup のグループを削除する

とすれば ok です

#!/bin/bash

set -ex

for i in {1..10};
do
  mkdir /sys/fs/cgroup/memory/hogehoge-$i;
  bash -c "echo \$\$ > /sys/fs/cgroup/memory/hogehoge-$i/tasks; rm -rfv /tmp/$i; mkdir /tmp/$i; ps > /tmp/$i/hoge;"
done

for i in {1..10};
do
  rmdir /sys/fs/cgroup/memory/hogehoge-$i;
done

観察

スクリプトの中で cgroup を削除しているにも関わらず cgroup に属する slab キャッシュが残っており、その様子は /sysfs/kernel/slab/<キャッシュの名前>/cgroup/<キャッシュの名前(コンテナ名)> を通して把握できます

root@bionic:~# find /sys/kernel/ -type d | grep hogehoge
/sys/kernel/slab/radix_tree_node/cgroup/radix_tree_node(987:hogehoge-1)
/sys/kernel/slab/dentry/cgroup/dentry(1029:hogehoge-4)
/sys/kernel/slab/dentry/cgroup/dentry(1027:hogehoge-3)
/sys/kernel/slab/dentry/cgroup/dentry(1025:hogehoge-2)
/sys/kernel/slab/dentry/cgroup/dentry(1039:hogehoge-9)
/sys/kernel/slab/dentry/cgroup/dentry(1023:hogehoge-1)
/sys/kernel/slab/dentry/cgroup/dentry(1037:hogehoge-8)
/sys/kernel/slab/dentry/cgroup/dentry(987:hogehoge-1)
/sys/kernel/slab/dentry/cgroup/dentry(1035:hogehoge-7)
/sys/kernel/slab/dentry/cgroup/dentry(1033:hogehoge-6)
/sys/kernel/slab/dentry/cgroup/dentry(1031:hogehoge-5)
/sys/kernel/slab/dentry/cgroup/dentry(1041:hogehoge-10)
/sys/kernel/slab/proc_inode_cache/cgroup/proc_inode_cache(987:hogehoge-1)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(999:hogehoge-7)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(997:hogehoge-6)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(993:hogehoge-4)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(991:hogehoge-3)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(1029:hogehoge-4)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(1027:hogehoge-3)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(1025:hogehoge-2)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(1023:hogehoge-1)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(1037:hogehoge-8)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(1005:hogehoge-10)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(1035:hogehoge-7)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(1003:hogehoge-9)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(1001:hogehoge-8)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(1031:hogehoge-5)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(989:hogehoge-2)
/sys/kernel/slab/:a-0000104/cgroup/buffer_head(987:hogehoge-1)
/sys/kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(1029:hogehoge-4)
/sys/kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(1027:hogehoge-3)
/sys/kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(1025:hogehoge-2)
/sys/kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(1039:hogehoge-9)
/sys/kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(1023:hogehoge-1)
/sys/kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(1037:hogehoge-8)
/sys/kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(1035:hogehoge-7)
/sys/kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(1041:hogehoge-10)
/sys/kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(1033:hogehoge-6)
/sys/kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(1031:hogehoge-5)

buffer_head, ext4_inode_cache, dentry, radix_tree_node といったファイルシステムに関係してそうな slab が残ります

これらのファイルは sysctl vm.drop_caches=3 で強制的に削除できます. udevadm でその様子をモニターできます

root@bionic:~# udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[9553.936313] remove   /buffer_head(1035:hogehoge-7) (cgroup)
KERNEL[9553.972915] remove   /buffer_head(1029:hogehoge-4) (cgroup)
UDEV  [9553.973513] remove   /buffer_head(1035:hogehoge-7) (cgroup)
UDEV  [9553.975710] remove   /buffer_head(1029:hogehoge-4) (cgroup)
KERNEL[9554.021867] remove   /dentry(1041:hogehoge-10) (cgroup)
KERNEL[9554.029926] remove   /dentry(1035:hogehoge-7) (cgroup)
UDEV  [9554.030095] remove   /dentry(1041:hogehoge-10) (cgroup)
KERNEL[9554.031050] remove   /dentry(1039:hogehoge-9) (cgroup)
UDEV  [9554.031120] remove   /dentry(1035:hogehoge-7) (cgroup)
UDEV  [9554.031872] remove   /dentry(1039:hogehoge-9) (cgroup)
KERNEL[9554.032554] remove   /dentry(1037:hogehoge-8) (cgroup)
KERNEL[9554.032571] remove   /dentry(1033:hogehoge-6) (cgroup)
KERNEL[9554.032580] remove   /dentry(1031:hogehoge-5) (cgroup)
KERNEL[9554.032587] remove   /dentry(1029:hogehoge-4) (cgroup)

...

もう一度 /sys/kernel 以下をみてみると、消えましたね

root@bionic:~# find /sys/kernel/ -type d | grep hogehoge
root@bionic:~# 

( 注: kswapd の background reclaim やタスクの direct reclaim で slab の回収をする際にも削除されると思います. ここでは観察のために vm.drop_caches を呼び出しています )

疑問と推測 ❓

cgroup を削除して プロセスと cgroup からの参照が無くなったにも関わらず slab が残ってしまうのかが謎でした。

推測で、cgroup 内で作られた dirty な inode やページキャッシュがある場合に slab が残るのかな? とアタリをつけました

が、結局わからないので LKML を調べました

ソースを調べる

LKML のパッチや投稿を探しているうちに、私が遭遇したのと内容が合致していそうな投稿を見つけます

lkml.org

どうも cgroup 内で作られた dirty な inode に対して wb = struct bdi_writeback が参照をもっていて、冒頭に書いた現象が起きるようです. なるほど〜

投稿されたパッチ

work_struct で定期的に起床するカーネルスレッドに 回収処理を任せるという実装を提案していますが、その後のレビューを見るに mainline には取り込まれていないようです

現状はなんともしようがないんですかねぇ

与太話

Facebookカーネルエンジニアさんらしいので、FB のユースケースでの問題を解決したいパッチ投稿みたいですね。

まとめ

  • コンテナの生成と削除が頻繁に行われる環境 (例: k8s )で、暗黙的に slab キャッシュが溜まるという現象で遭遇しそうです
  • slab の回収処理が走れば削除されるはずなので、気がついてないというケースもありそうです

関連のエントリ

hiboma.hatenadiary.jp

Linux Kernel: cgroup, sysfs, kobject, uevent についての調べ物 - (3) slub_memcg_sysfs ブートパラメータについて

以下のエントリの続きです

hiboma.hatenadiary.jp

hiboma.hatenadiary.jp

cgroup 内で生成される slab キャッシュに対応する sysfs のファイルが /sys/kernel/slab/<キャッシュの名前>/cgroup/... 以下に生成されることを追っていました。

kernel のブートパラメータに slub_memcg_sysfs=0 を足すことで sysfs のファイル作成を抑制できるのを確認したのを記したエントリです

続きを読む

Linux Kernel: cgroup, sysfs, kobject, uevent についての調べ物 - (2) 実験編

前回のエントリの続きです

hiboma.hatenadiary.jp

実験用のカーネルモジュールを作り、cgroup v1 のメモリコントローラーで制限をかけた状態で sysfs の kobject (slab) が生成されるかどうかを確かめます

実験用のカーネルモジュール

適当な名前の slab キャッシュを生成/破棄するカーネルモジュールを作りました

github.com

これを使って実験をします

続きを読む

Linux Kernel: cgroup, sysfs, kobject, uevent についての調べ物

cgroup v1 + memory コントローラーで制限を課した際に、sysfs のファイル = kboject が生成/削除されるタイミングやその仕組みを調べていました

例えば下記のような sysfs のファイルです

/sys/kernel/slab/dentry/cgroup/dentry(979:@hogehoge)/objects
/sys/kernel/slab/kmalloc-4k/cgroup/kmalloc-4k(979:@hogehoge)/objects
/sys/kernel/slab/kmalloc-32/cgroup/kmalloc-32(979:@hogehoge)/objects
/sys/kernel/slab/kmalloc-2k/cgroup/kmalloc-2k(979:@hogehoge)/objects
/sys/kernel/slab/kmalloc-1k/cgroup/kmalloc-1k(979:@hogehoge)/objects

ぱっと見、cgroup 内の slab が sysfs のファイルとして扱えることは分かっていたのですが、もうちょい調べました

sysfs と kboject について

続きを読む

Linux Kernel: PSI - Pressure Stall Information /proc/pressure/memory で メモリのストールを観察する

下記の続きエントリです

hiboma.hatenadiary.jp

今回は PSI - Pressure Stall Information の /proc/pressure/memory についてのエントリ

PSI を使うと CPU, メモリ, IO で stall した時間(割合) を計測できるってなことですが、どういった実装で「memory stall = メモリのストール」を起こしているタスクを計測しているのかかが疑問で調べていました

続きを読む

cgroup v1 の kmem.limit_in_bytes は deprecated and will be removed

5.4-rc7 で cgroup v1 の memory.kmem.limit_in_bytes を触っていたら下記のメッセージに遭遇した

[ 5627.054183] kmem.limit_in_bytes is deprecated and will be removed. Please report your usecase to linux-mm@kvack.org if you depend on this functionality.

kmem.limit_in_bytes is deprecated and will be removed. !

ソース / コミット

下記のコミットで deprecated になってたのでした

github.com

Cgroup v1 memcg controller has exposed a dedicated kmem limit to users which turned out to be really a bad idea because there are paths which cannot shrink the kernel memory usage enough to get below the limit (e.g. because the accounted memory is not reclaimable).

... 略

5.4-rc1 の頃

kmem.limit_in_bytes で制限をかけた際に、カーネルのメモリを shrink できないパスがあるからとか意図しないエラーを招くからてな理由らしい. 詳細はコミットログを読んでくださいな


つい最近に「 kmem.limit_in_bytes を制限して slab_out_of_memory を起こすのを観察する」というエントリを書いたのだが これも同様のケースかと思う

hiboma.hatenadiary.jp

slab_out_of_memory を起こすと制限をかけた cgroup 内のプロセスが自力でリカバリできない状態にハマるので使いにくいなと思っていたが、 deprecated になるものをあえて使う理由も無かろう

松本〜安曇野〜木崎湖〜白馬 🚴‍♂️

11/2(土) 〜11/4(月) 二泊三日の松本旅行の2日目

松本から安曇野木崎湖〜白馬まで走った. 後半は天気が崩れてしまった

ちょいと消化不良だったので、来年またリベンジだな

f:id:hiboma:20191116205521p:plain

走行距離 79km 獲得標高 977m

続きを読む