Ubuntu Weekly Recipe

第688回 eBPFのコンパイラーに対応したツールでさまざまな挙動を可視化する

この記事を読むのに必要な時間:およそ 8.5 分

実行中のシステムの挙動を詳細にトレースする仕組みは、特に「よくわからない問題」に遭遇している時に重要です。今回はLinux向けのトレーシングツールの本命とも言えるeBPFを利用した各種ツールを紹介します。

eBPFとBPF Compiler Collection

改めて言うまでもなく,Linuxカーネルもしくはカーネル上で動いている各種タスクのパフォーマンスや挙動を調べなくてはならないケースはよくあります。たとえば単なる不具合の調査から,予期せぬ挙動に対する原因の特定,セキュリティ対応,高速化のための計測などが考えられるでしょう。この手の調査は「動いているカーネルをそのまま使う」ことがポイントでもあります。

第584回のSystemTapでカーネルの挙動を確認するや第585回のSystemTapを活用してネットワークの動作を確認するで紹介したSystemTapは,そんな「カーネルをそのまま使う」ことが可能な調査ツールでした。SystemTapは調査用のコードをカーネルモジュールとしてビルドしてロードするため,厳密な意味での「カーネルをそのまま」ではないのですが,それでもカーネルを再コンパイルしなくても調べられるのは強力な利点となります。

それに対して,より新しいカーネルで使えるようになった「eBPF」は任意の外部プログラムをカーネルの中で,より安全に実行できる仕組みです。カーネルモジュールを作る代わりに,独自のバイトコードをコンパイラーで生成し,それをカーネル内部にロード・実行することになります。よって独自のコンパイラーと新しいカーネルがあれば,比較的簡単に導入できます。SystemTapで必要だったデバッグシンボル付きのイメージも不要です。

気をつけなければいけないのは「新しいカーネル」の部分です。パケットフィルターとしてのBPF自体は古くから存在する機能ではあるものの,eBPFに向けてLinux 3.15で大きな対応が入り,仕組みやその周辺ツールについてはその後のカーネルのリリースごとに拡充されていったという経緯があります。よって「やりたいこと」に合わせてカーネルのバージョンがどうなっているかを調べる必要があります。たとえば現在サポートされているUbuntuのバージョンは次のとおりです。

  • Ubuntu 14.04 LTS(ESM⁠⁠:3.13から4.4
  • Ubuntu 16.04 LTS(ESM⁠⁠:4.4から4.15
  • Ubuntu 18.04 LTS:4.15から5.4
  • Ubuntu 20.04 LTS:5.4から5.13以降
  • Ubuntu 21.04:5.11
  • Ubuntu 21.10:5.13

ここで「ESM」と書いているものはExtended Security Maintenanceに入っているものを示します。つまりすでにサポート期間は終了し,追加の有償サポート期間に入っているものです。よって「不具合やパフォーマンスの調査」が必要になるであろう,活発に保守されているサーバーはおそらく18.04以降にはなっていると期待できそうですし,そうすると古くとも4.15以降のカーネルが使われていることになります。

4.15ぐらいであれば,eBPFの基本的な機能なら問題なく使えます。今回はUbuntu 20.04 LTSを前提に話を進めましょう。

eBPFを使うツールはいろいろ存在しますが,その中でも基本的なツールであり広く使われているのがBPF Compiler Collection(BCC)です。コンパイラーと名前のついているとおり,バイトコードを生成するコンパイラーを提供しているのですが,それ以上に便利なのが「eBPFを使ってよく作られるツール」をサンプルコマンドとしてまとめている点でしょう。つまりBCCを導入すれば,コードを書かなくてもeBPFを利用した各種トレーシングが行えるというわけです。

BCCのインストール方法

Ubuntuの場合,BCCはaptとsnapの2種類のインストール方法が存在します。

apt版は普通にDebianパッケージとしてインストールする方法です。シンブルな方法ではあるものの,他のaptパッケージと同じく「バージョンが古くなりがち」という問題を抱えています。たとえばBCCの2021年10月時点での最新版は0.22.0ですが,apt版のBCCは次のようなバージョンになっています。

  • Ubuntu 18.04 LTS: 0.5.0
  • Ubuntu 20.04 LTS: 0.12.0
  • Ubuntu 21.04: 0.18.0
  • Ubuntu 21.10: 0.18.0

それに対してsnap版のBCCは,0.21.0をインストール可能です。snap版はCanonicalがメンテナンスしているため,Ubuntuでも5.14カーネルが使えるようになるまでには,0.22.0以降のsnapパッケージも用意されることでしょう。

特にBCCの場合は,新しいカーネルの機能を使いたいなら,BCC側も新しくしなくてはなりません。使いたい機能を満たせるならapt版でも問題ないですが,より新しいカーネルでより新しい機能を使いたいならsnap版を使いましょう。またapt/snapともに名前や使い方に若干のクセが存在します。ここでは両方のインストール方法を紹介します。

apt版のインストール

apt版のパッケージ名はbpfcc-toolsです。これはDebianも同じです。bpfcc-toolsには前述の各種ツールが含まれます※訂正⁠。またPython 3バインディング等も一緒にインストールされます。

2021年11月1日訂正
記事公開時には「コンパイラーであるbpfcが含まれる」と記述していましたが,bpfcはnetsniff-ngパッケージに含まれる,Classic BPF向けのコンパイラーでした。大変失礼いたしました。
$ sudo apt instal bpfcc-tools

各種ツールにはすべて-bpfccという接尾辞が付きます。たとえば「execsnoop」コマンドのapt版での名前は「execsnoop-bpfcc」です。少しわかりにくいですが,タブ補完を活用すればそこまで気にならないでしょう。

ちなみにDebianの場合は,bpfc-toolsパッケージだけでなく「linux-headers-amd64」パッケージも一緒にインストールしておいてください。DebianのカーネルはCONFIG_KHEADERSが有効化されておらず,/sys/kernel/kheaders.tar.xzからカーネルのヘッダーファイルを取得できないためです。

snap版のインストール

snap版のパッケージ名はそのままbccです。Canonicalがビルド・公開していますが,パッケージングのメタデータ(snapcraft.yaml)公式プロジェクトに取り込まれています

$ sudo snap install bcc --devmode

現状のbccパッケージは--devmode付きでインストールしないと,いくつかのツールが動作しません。bccを動かす時点で特権が必要なため,ここは諦めるしかないでしょう。また,上記BCCのページではsnap connectを使う説明がありますが,ストアサイトからインストールする場合は自動的に設定されるため,あらためて対応する必要はありません。

各種ツールにはすべてbcc.という接頭辞が付きます。たとえば「execsnoop」コマンドのsnap版での名前は「bcc.execsnoop」です。もしよく使うもので,オリジナルと同じ名前にしたい場合はsnap alias bcc.execsnoop execsnoopとエイリアスの設定をすると良いでしょう。元に戻すのはsnap unalias bcc.execsnoopです。

Linuxカーネルのフレーバーに注意

BCCはeBPFだけでなくツールに応じてdebugfsやkprobesなどといった,カーネルコンフィグを必要としています。しかしながら,Ubuntuのカーネルフレーバーによっては,これらのカーネルコンフィグが有効化されていません。

たとえばUbuntu Cloud Imagesから提供され,VM版のLXDインスタンスで使われるKVMフレーバーはCONFIG_KPROBESが有効になっていないため,BCCの大半のツールが使えません。具体的には次のようなエラーメッセージが表示されてしまいます。

$ sudo bcc.execsnoop
create_probe_event: open(/sys/kernel/debug/tracing/kprobe_events): No such file or directory
Traceback (most recent call last):
  File "/snap/bcc/159/usr/share/bcc/tools/execsnoop", line 229, in <module>
    b.attach_kprobe(event=execve_fnname, fn_name="syscall__execve")
  File "/snap/bcc/159/usr/lib/python3/dist-packages/bcc/__init__.py", line 834, in attach_kprobe
    (fn_name, event))
Exception: Failed to attach BPF program b'syscall__execve' to kprobe b'sys_execve'

よってKVMフレーバーを使っている環境でどうしてもBCCを使いたい場合は,genericフレーバーに切り替えてしまいましょう。

$ sudo apt install -y linux-generic
$ sudo apt remove -y --purge '~nlinux-.*kvm ~i'

2行目でKVMフレーバーを削除しているのは,genericフレーバーのみで起動するようにしたいためです。generic/KVMを併用する場合はそのまま残しても問題ありません。その場合,grub-rebootコマンドで設定するかGRUBメニューから手動でUbuntu, with Linux 5.4.0-88-genericと末尾に「generic」と書かれたメニューを選択してください。

なお,KVMカーネルで起動している状態でKVMカーネルを削除しようとすると,⁠起動中のカーネルを削除しようとしているが,きちんと別のカーネルで起動してから削除することを強く推奨する。よって削除を中止して良いか?と聞かれます。削除したい場合は,きちんとNoを選びましょう。

ちなみに今のところ問題になりそうなのは,KVMフレーバーのみです。AWS・GCP・GKE・Azureフレーバーについてはざっと見た限り問題なさそうです。

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member株式会社 創夢所属。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。