bpftrace には cgroup
という変数があって、イベントが起こったプロセスの cgroup ID(後述しますが、?な数字です)を取得できます。
$ bpftrace -e 'uretprobe:/bin/bash:readline { printf("input(%d@%d) = %s\n", pid, cgroup, str(retval)); }' Attaching 1 probe... input(16277@2055) = input(16277@2055) = echo $$ > /sys/fs/cgroup/unified/sample100/cgroup.procs # <= ここで変更 input(16277@2139) = ls -l
これはちなみに、カーネルのバージョンが古いとこういうエラーになります。
stdin:1:38-46: ERROR: BPF_FUNC_get_current_cgroup_id is not available for your kernel version
使う場合、Ubuntu Bionicあたりはカーネル5.0.0を入れられるので、それを入れてbpftraceを自分でビルドすればOKです...
と言いたいところですが、なぜかビルドで参照するヘッダが入っている linux-libc-dev
というパッケージがカーネル 4.4 相当のままなので、先のバージョンのディストロから当該のものを個別に入れます。それでいいのかな。最初からDiscoあたりで試すのなら問題はないはずです。
wget http://kr.archive.ubuntu.com/ubuntu/pool/main/l/linux/linux-libc-dev_5.0.0-29.31_amd64.deb dpkg -i linux-libc-dev_5.0.0-29.31_amd64.deb
こういうコマンドを打って get_current_cgroup_id
が見つかれば大丈夫です。
$ grep 'FN(' /usr/include/linux/bpf.h | grep cgroup FN(get_cgroup_classid), \ FN(skb_under_cgroup), \ FN(current_task_under_cgroup), \ FN(skb_cgroup_id), \ FN(get_current_cgroup_id), \ FN(skb_ancestor_cgroup_id), \
しかし、この「プロセスの cgroup ID」だと思われる値がなんなのか、ここから path に変換するにはどうすればいいのか、の情報がなく、知見があれば嬉しいです。
ちなみに tracepoint の tracepoint:cgroup:cgroup_mkdir
などで取れる cgroup ID とは違うものです。なんでやねん...。
root@ubuntu-bionic:~# cat /sys/kernel/debug/tracing/events/cgroup/cgroup_mkdir/format name: cgroup_mkdir ID: 426 format: field:unsigned short common_type; offset:0; size:2; signed:0; field:unsigned char common_flags; offset:2; size:1; signed:0; field:unsigned char common_preempt_count; offset:3; size:1; signed:0; field:int common_pid; offset:4; size:4; signed:1; field:int root; offset:8; size:4; signed:1; field:int id; offset:12; size:4; signed:1; field:int level; offset:16; size:4; signed:1; field:__data_loc char[] path; offset:20; size:4; signed:1; print fmt: "root=%d id=%d level=%d path=%s", REC->root, REC->id, REC->level, __get_str(path) root@ubuntu-bionic:~# echo 1 > /sys/kernel/debug/tracing/events/cgroup/cgroup_mkdir/enable root@ubuntu-bionic:~# mkdir /sys/fs/cgroup/unified/sample100 root@ubuntu-bionic:~# cat /sys/kernel/debug/tracing/trace # tracer: nop # # entries-in-buffer/entries-written: 10/10 #P:4 # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | systemd-1 [001] .... 11267.304951: cgroup_mkdir: root=0 id=93 level=2 path=/system.slice/phpsessionclean.service systemd-1 [001] .... 11267.304983: cgroup_mkdir: root=1 id=44 level=2 path=/system.slice/phpsessionclean.service systemd-1 [001] .... 11267.305028: cgroup_mkdir: root=4 id=7 level=2 path=/system.slice/phpsessionclean.service systemd-1 [001] .... 11267.305072: cgroup_mkdir: root=7 id=7 level=2 path=/system.slice/phpsessionclean.service systemd-1 [001] .... 11267.305201: cgroup_mkdir: root=5 id=22 level=2 path=/system.slice/phpsessionclean.service systemd-1 [001] .... 11267.305228: cgroup_mkdir: root=12 id=7 level=2 path=/system.slice/phpsessionclean.service systemd-1 [001] .... 11267.305249: cgroup_mkdir: root=3 id=43 level=2 path=/system.slice/phpsessionclean.service mkdir-17339 [003] .... 11269.994534: cgroup_mkdir: root=0 id=93 level=1 path=/sample100 mkdir-17340 [000] .... 11271.699314: cgroup_mkdir: root=0 id=94 level=1 path=/sample200 mkdir-17341 [002] .... 11273.392368: cgroup_mkdir: root=0 id=95 level=1 path=/sample300
この情報だけなら /sample100
というcgroupのIDは 93
のはず。しかし。。。
$ bpftrace -e 'uretprobe:/bin/bash:readline { printf("input(%d@%d) = %s\n", pid, cgroup, str(retval)); }' Attaching 1 probe... input(16277@2055) = input(16277@2055) = echo $$ > /sys/fs/cgroup/unified/sample100/cgroup.procs # <= ここで /sample100 に所属 input(16277@2139) = ls -l # 2139 とは???
桁が小さいから inode とかでもない気がするんですが。。
周辺のカーネルのドキュメントやソースコードなどを追う必要がありそう。
そしてカーネル 5.0 だと、例の PSI も使えるので、コンテナモニタリング周りで色々道具が増えそうですね。楽しそう。