第12回 コンテナ技術の情報交換会@オンラインにて 「cgroup と sysfs ファイル - トラブルシューティングから cgroup を深追いする」を発表しました

第12回 コンテナ技術の情報交換会@オンラインに発表しました!

ct-study.connpass.com

スライド

発表のスライドは下記で公開しております

speakerdeck.com

speakerdeck でフォントがしゃばしゃばになるのを解決できていないので、PDF でも公開しています ...

github.com

スライドの概要

弊社 GMO ペパボの ロリポップ!マネージドクラウドでのトラブルシューティング事例を契機として cgroup の sysfs ( スラブキャッシュ ) 周りを追いかけた内容を発表しています。

発表内容は、過去のエントリを勉強会向けにまとめ直した内容です。モデル図などを加筆しています。

hiboma.hatenadiary.jp

トラブルの詳細については、ブログでは過去にも公開していなかった内容で、今回の発表でのみ閲覧できます。当時、実際に記録したコマンドやメトリクス図なども掲載しています。

配信動画

こちらで閲覧できます

www.youtube.com

私の発表パートは下記から閲覧できます

youtu.be

twitter #lxcjp

穏やかな感じで twitter タイムラインでした。みなさんの発表に対して「よかった」とフィードバックをいただけて嬉しいですね ☺️

twitter.com

謝辞

@ten_forward ( id:defiant ) さん、 windhole ( id:windholep )さん、@masami256( id:masami256 ) さん 運営の準備ありがとうございました!! 当時の発表お疲れ様でした!! この場を借りて謝辞を述べさせていただきます。

また何か発表かのネタになるような事例に遭ったら よろしくお願いします! ( でもトラブルは無い方がね ...

【続 Vol. 2】 Linux Kernel: cgroup 削除後も残り続ける slab キャッシュ についての調べ物 - upsteam は修正パッチが入って解決済み

どんどんタイトルが長くなっていますが... 先のエントリで書いた問題の補足記事エントリです。

hiboma.hatenadiary.jp

5.9-rc1 以降、slub_memcg_sysfs は何も機能しない

slub_memcg_sysfs は、cgroup に関連する sysfs ファイル ( /sys/kernel/cgroup ... ) の作成を制御する カーネルのブートオプション(パラメータ) です。

        slub_memcg_sysfs=       [MM, SLUB]
                        Determines whether to enable sysfs directories for
                        memory cgroup sub-caches. 1 to enable, 0 to disable.
                        The default is determined by CONFIG_SLUB_MEMCG_SYSFS_ON.
                        Enabling this can lead to a very high number of debug
                        directories and files being created under
                        /sys/kernel/slub.

詳細は下記のエントリに記しています

hiboma.hatenadiary.jp


ところが、下記のコミットで slub_memcg_sysfs に変更が入り特に何も機能しないコードになってしまいました。

github.com

実際にコードを見てみましょう

オプションを処理する setup_slub_memcg_sysfs() をみてみる

カーネルのブート時に slub_memcg_sysfs を指定していると setup_slub_memcg_sysfs() でオプションの値を扱います。

#ifdef CONFIG_MEMCG
static bool memcg_sysfs_enabled = IS_ENABLED(CONFIG_SLUB_MEMCG_SYSFS_ON); 👈

static int __init setup_slub_memcg_sysfs(char *str)
{
    int v;

    if (get_option(&str, &v) > 0)
        memcg_sysfs_enabled = v; 👈

    return 1;
}

__setup("slub_memcg_sysfs=", setup_slub_memcg_sysfs);
#endif

slub_memcg_sysfs={0|1} を指定して起動すると、変数 memcg_sysfs_enabled が指定した値にりますが、

しかし、この変数が参照される箇所は二箇所しかありません (ソースは 5.9-rc7 )

 $ global -rsx memcg_sysfs_enabled
memcg_sysfs_enabled 4885 mm/slub.c        static bool memcg_sysfs_enabled = IS_ENABLED(CONFIG_SLUB_MEMCG_SYSFS_ON);
memcg_sysfs_enabled 4892 mm/slub.c              memcg_sysfs_enabled = v;

変数の参照元が、先の setup_slub_memcg_sysfs だけということになります。

したがって 5.9-rc1 以降は特に何にも機能しないオプションになっているようです。


感想

  • 該当のバージョン以降で検証をする機会にハマらないように、あるいは過去の関連するエントリへのポインタへなるよう本エントリの内容が役に立つと幸いです。
  • 何にも機能しないなら消したらいいのかな? と思いつつ、後方互換として残しているのでしょうか? ML のディスカッションを追ってないので詳細はわかりません

【続】 Linux Kernel: cgroup 削除後も残り続ける slab キャッシュ についての調べ物 - upsteam は修正パッチが入って解決済み

以前に下記のエントリを書きました。勉強会に登壇するネタとして調べ直したところ 新しい Linux カーネルでは問題が解決されていました。

hiboma.hatenadiary.jp

hiboma.hatenadiary.jp

hiboma.hatenadiary.jp

hiboma.hatenadiary.jp

どんな問題ですか?

「cgroup を削除した後も sysfs の slab キャッシュ が残る」「slab キャッシュ が reclaim されるタイミングで必要のない uevent が送出される」 という二つの問題でした。

問題 と書いていますが、対象の slab キャッシュは inode っキャッシュや dentry キャッシュ であり、reclaimable な slab キャッシュです。 reclaimable な slab キャッシュは、カーネルにメモリプレッシャーがかかると自然に回収されため、大抵は問題として顕在化せずに気がつかないかと思います。送出される uevent も slab キャッシュの数が多くなければシステムへの負荷として観測されるほどにはなりません。

ところが、私が仕事で扱ってるサーバでは、以下のように問題を踏みました。

そもそも、このネタを調べていたのは「とある大量のコンテナを扱う production 環境」で、sysfs ファイル削除のタイミングで uevent が大量に送出され、それを処理するカーネルスレッドが競合を起こし TASK_UNINTERRUPTIBLE でブロックされ、ロードアベレージ上昇のアラートを招いていたのが発端でした。

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

問題の回避・解決方法は?

1. slub_memcg_sysfs を指定する

ワークアラウンドとして、ブートオプションに slub_memcg_sysfs=0 を指定すると、cgroup によって sysfs のファイルが作成されなくなり slab っキャッシュも溜まらなくなり、「問題」を回避することができます。

2. 新しいカーネルにする

本エントリの本題になります。上記の新しいカーネルではパッチがあたり、問題が解決されています

パッチその1

cgroup 削除後も slab キャッシュが残ってしまうコードは下記で解決されたようです。5.9-rc1 で取り込まれているパッチです。

github.com

コミットログを見るに、memcg で使う kmem_cache を一つに統一する、という内容のようですがボリュームのでかいパッチで詳細まではちょっとわかりません

本エントリに関係するのは、diff で言うと下記のあたり。

@@ -5760,16 +5628,6 @@ static int sysfs_slab_add(struct kmem_cache *s)
    if (err)
        goto out_del_kobj;
 
-#ifdef CONFIG_MEMCG
-  if (is_root_cache(s) && memcg_sysfs_enabled) {
-      s->memcg_kset = kset_create_and_add("cgroup", NULL, &s->kobj);
-      if (!s->memcg_kset) {
-          err = -ENOMEM;
-          goto out_del_kobj;
-      }
-  }
-#endif
-
    if (!unmergeable) {
        /* Setup first alias */
        sysfs_slab_alias(s, s->name);

https://github.com/torvalds/linux/commit/10befea91b61c4e2c2d1df06a2e978d182fcf792#diff-4f86c03fe66c75bd50afc8e320349281L5763-L5772

パッチその2

cgroup が作る sysfs ファイルが udev イベントを飛ばしていたコードは下記のコミットで削除されました。5.8-rc1 で取り込まれています

github.com

「必要ないから消したよ」というコミットログですね。

I came across some unnecessary uevents once again which reminded me this. The patch seems to be lost in the leaves of the original discussion [1], so resending.


kmem_cache ( slub キャッシュ ) はカーネル内部の構造体なのに、ユーザ空間に通知を出すのは変だし、使ってるのみたことないというコメント

Kmem caches are internal kernel structures so it is strange that userspace notifiers would be needed. And I am not aware of any use of these notifiers.

https://lore.kernel.org/linux-mm/20200423115721.19821-1-mkoutny@suse.com/

先のエントリを書いた時に「 cgroup の sysfs が uevent を出して何に使うんだろう?」という疑問を抱いていたのですが、カーネルコミッタも同様に思っていたようですね。よかった 😀


These notifiers may just exist because in the initial slub release the sysfs code was copied from another subsystem.

さらに、「別のサブシステムからコピペして作った」という旨も書かれています ワハハ


イベントの宣伝

第12回 コンテナ技術の情報交換会@オンライン では、これらの話をまとめ直した内容を喋るつもりでいます

ct-study.connpass.com

TenForward id:defiant さん、こんな感じです!

八方ヶ原大間々台 🚴‍♂️

9/22 栃木県矢板市の八方ヶ原大間々台へヒルクライム。コロナのせいで遠方に出かけるのを控えていたので、ようやく今年初の山。

f:id:hiboma:20200928113242p:plain

f:id:hiboma:20200922161549j:plain

走行距離 61km, 獲得標高 1143m。在宅の合間で、ランニングやサイクルトレーナーでトレーニングしてものの、すっかり足が衰えていてしんどかった。

続きを読む

会社のテックブログに記事を書きました: ペパボ トラブルシュート伝 - TCP: out of memory -- consider tuning tcp_mem の dmesg から辿る 詳解 Linux net.ipv4.tcp_mem

以下の記事です。

tech.pepabo.com

  • TCP our of memory
  • memory pressure モード
  • net.ipv4.tcp_mem

以上の三つの詳細を扱ったエントリです。TCP で大規模なトラフィックを扱っているサーバを扱われている場合、問題がないかどうかを確かめてみるとよいかと思います。

本文長いです。何に気をつけたらいいんでしょう?

ラクティカルな話だけをまとめると、以下の4行です。

  • memory pressure モードに入ってしまうと warning です
  • TCP out of memory が出てしまうと critical です
  • 監視は /proc/ 以下のファイルを見ましょう
  • チューニングは net.ipv4.tcp_mem で行いましょう

LVS はどうなの?

LVS でロードバランシングしている場合は、TCP スタックを通らないため TCP oom や memory pressure モードは問題にならないと思います ( LVS のソースは呼んだことないので、確実ではないですが ... )

定量的な評価はしなかったのか?

Q「パフォーマンス」に触れているが、はたして、どれくらい性能に影響する問題なのですか?
A. すいません。測定してないです。

ソースを読んだ上での定性的な評価のみです。

定量的な評価はできませんでした。ツールの選定を始め、どのようにシミュレート環境を作るべきかが分からず 手を出せませんでした。力不足に尽きますね。

落穂拾い的な話

  • TCP/IP の理解が浅いところからスタートで、初歩の初歩から学び直しが必要だった。
  • ソースと書籍を読みあさって、お正月から 一ヶ月〜二ヶ月くらい費やしました。(コロナのせいでしばらく記事を寝かせていた)
  • 調査の過程で「TCP のパケットドロップってどういう条件で起きるんだ?」という長年の疑問が解決されたのもよかった

記事を書いた時に頻繁に参照したのが、以下の書籍です。

https://www.amazon.co.jp/dp/0470147733www.amazon.co.jp

TCP/IP Architecture, Design, and Implementation in Linux は、Linux カーネル 2.4系のソースを併記しながら TCP/IP スタックを細かく解説するカーネル本です。2.4 系であっても参考となる箇所は多く、この本がないと調べきるのは難しかったなと思います。編集や校正が詰めきれてないのか、ところどころアラが目立つ書籍ではあるので、ご注意を ... 。