BPF Performance Toolsを読んだ感想

BPF Performance Toolsを読んだので、感想ブログです。

先に感想を言っておくと「最高」でした。

BPF Performance Toolsとは? 

NetflixでKernel・パフォーマンスにかかわるチューニング・アーキテクチャを専門にしているBrendan Greggさんが書いた本です。BPFのiovisorというTracing分野の第一人者でもあります。

www.brendangregg.com 

2019年12月に発売したばかりなので、BPFの分野では最新の本でしょう。他の著書に有名な本として(日本語版の)「詳解システム・パフォーマンス」があります。

BPF Performance Toolsは「詳解システム・パフォーマンス」第二弾と言えるかもしれません。ちなみにページ数は880Pあり、Kindleで表示される読み終わるための平均的な時間は「27時間30分」で、大作RPG並です。

www.oreilly.co.jp

読書時のレベル

BPF is 何くらいのレベル。インフラ経験は2年目くらい。

BPFという単語はCiliumとかカンファレンスとかで聞いたことがあった程度

「BPF Performance Tools」の良いところ

先にBPF Performance Toolsの良いところを書いておきます。

  • BPFをかなり詳細に扱った本(英語でも数は少ない。2冊くらい?)
  • NetflixやShopifyなどの実例が多く載っており、本番環境で実践することを念頭に置かれている
  • BPFプログラムを使ったTracingをするときの考え方や戦略が載っている
  • CPU/メモリ/ファイルシステム/ネットワークなど、レイヤごとに戦略、ツールなどを詳細に紹介している

BPFって何? あと何に使えるの?

BPFはよく名前を聞きますが、「なんだか分からないけどすごいもの」くらいの印象しかありませんでした。バズワードかな、くらいに思っていましたが、本書を読んで印象が180度変わりました。

Brendan GreggさんがBlogで「Linux BPF Superpowers」という記事を公開していますが、Linux上でなんでもできるマジックツール、という表現がしっくり来るかもしれません。

BPFの由来・用途 

簡単に由来や用途についてまとめます。

BPFはBerkeley Packet Filterの略で、パケットフィルターの名前のとおり、登場当初の1992年はネットワーク用途のものでした。

ただし、現在では名前こそパケットフィルターを冠していますが、システムコールのフィルタリングやトレーシング、セキュリティなど様々な用途に使われています。

eBPFというextended Berkeley Packet Filterという名称もありますが、どうやら現在はBPFとeBPFは特に区別していないそうです(BPF Performance Toolsでも言及されていましたが、BPFとeBPFを同じものとして扱ってます)。

Linux Observability with BPFというO'reilly本もありますが、とくにTracingやObservabillityを確保するためにBPFツールを使うこともできます。

shop.oreilly.com

Linux Traditional Observability

たとえば、「なんかいつもより調子悪いサーバーがあるので見てみよう」と思った時にすることといえば、 だいたい次のようなことをすると思います。

  1. サーバーにSSHする
  2. uptimeでLoad Averageを確認する
  3. psコマンドでプロセスの状態を確認する
  4. pidstat, mpstatなどでCPU使用率を確認する
  5. freeやsarなどでメモリ消費量を確認する
  6. iostatやsarなどでI/Oを確認する
  7. netstatやsarなどでネットワーク状況を確認する

調子の悪いサーバーがあれば、SSHしてLinuxコマンドで状況を確認します。 

BPF Performance Toolsの3章にも載っていましたが、Netflixのパフォーマンスエンジニアがサーバーにログインして60秒で確認する内容がまとまっています。使われるのは伝統的なコマンドです。

↑のTweetで反響があったように、Linuxの基礎は10年以上の時を経ても変わっていません。

しかし、BPFはこれまでの伝統的なツールでは手が届かなかった領域に容易に手を入れられるようになってきています。そうしたBPFを活用したTracingプログラムが、今後は主流になっていくかもしれません。

 同じくBPF Performance Toolsの3章にはBPFを使ったTracingプログラム「bcc」のChecklistが載っています。これらのBPFツールが今後、topコマンドやsarコマンドと同じように当たり前に使われていくかもしれません。

  1. execsnoop
  2. opensnoop
  3. ext4slower(or btrfsslower, xfsslower, zfsslower)
  4. biolatency
  5. biosnoop
  6. cachestat
  7. tcpconnect
  8. tcpaccept
  9. tcpretrans
  10. runqlat
  11. profile

Linux Observability with BPF

BPFの仕組みの詳細は本記事では省きますが、Linuxの既存の仕組みを活用しています。

システムコールをフィルタリングできると書きましたが、BPFを使ったプログラムは次のEvent Sourceなどを使ったトレーシングができます。

Event Source 概要
kprobe Kernel Level Dynamic Tracepoint
uprobe User Level Dynamic Tracepoint
tracepoints Kernel Level Static Tracepoint
USDT User Space Static Tracepoint
Dynamic USDT User Space Dynamic Tracepoint
PMCs Programmable Hardware Counters
perf event Perfコマンドで使われているイベント

 これらはBPFのためだけに用意されたわけではなく、Linuxの長い歴史の中で築き上げられたものです。BPFはこれらを活用して、伝統的なツールでは探りきれない部分を探ることができます。

BPFの仕組みの詳細は、BPF Performance Toolsの第2章やLinux Observability with BPFに詳しく載っています。

BPFは様々な可能性を秘めたマジックツールです。BPF Peformanace Toolsでは、特にパフォーマンスを上げるためのツールではなく、パフォーマンスを上げるためのボトルネックを探すためのツールとしてBPFを活用しています

bccとbpftrace

次の図は、Tracingを主としたBPFツール「bcc」と「bpftrace」で使える、レイヤーごとのTracing Commandをまとめたものです。

f:id:go_vargo:20200311002620p:plain

出典: http://www.brendangregg.com/blog/2019-07-15/bpf-performance-tools-book.html

かなりの数があります。伝統的なLinuxコマンドではレイヤーによっては調べることがそもそもできないものもありますが、これらのTracingツールを使えばそうしたレイヤーの状態も確認することができます。

たとえば、bccのChecklistにあったexecsnoop, biolatency, tcpconnectを例にコマンドの出力を確認してみます。

execsnoop

f:id:go_vargo:20200329011956p:plain

execsnoop
biolatency

f:id:go_vargo:20200329012103p:plain

biolatency
tcpconnect

f:id:go_vargo:20200329012236p:plain

tcpconnect

それぞれのCommandで、Traditional Toolでは見れない情報が分かりやすく取得できることが分かると思います。

注意点としては、bccでしか使えないコマンド・bpftraceでしか使えないコマンドがあり、目的によっては使い分ける必要があります。

  • bccは、どちらかというと既にできているツールを使うために使う初心者向け
  • bpftraceは、目的に合わせて自分でスクリプトを書くために使う中級者・上級者向け

といった感じでしょうか。

Gregg先生のブログ記事「Learn eBPF Tracing: Tutorial and Examples」でも、

  1.  初心者: bccのツールを使ってみる
  2. 中級者: bpftraceのツール(スクリプト)を作ってみる
  3. 上級者: bccのツールを開発する、bccやbpftraceにコントリビュートする

という段階での実践を進めています。

bccを試してみたい人は、Local Kubernetesを構築するMinikubeで簡単に試すことができます。MinikubeはVMを立てて、その上でKubernetesを作ってくれるツールですが、ここではVM部分だけを使います。

VM DriverはWindowsLinuxMacのどれでも動くVirtualBoxで試すのがオススメです。(Docker Driverだと動かないので気をつけてください)

minikube.sigs.k8s.io

BPF Performance Toolsの構成

ここまで前置きが長くなりましたが、ここからようやく本の内容紹介です。

BPF Performance Toolsは全18章 + Appendixの構成です。簡単に各章の内容をまとめると、次の感じになります。

 1. Introduction

BPFやeBPFの説明や、bcc, bpftraceの簡単な説明、kprobe, uprobe, tracepoints, USDTなどの簡単な説明などを行う導入部です 

2. Technology Background

BPFの技術を支えるBackgroundを詳細に解説している章です。2章が難易度としては一番高いかもしれません。

BPFの歴史から始まり、BPFの仕組み、Kernel Modulesとの比較、Event Sources(kprobe, uprobe, tracepoints, USDTなど)の仕組みを詳細に説明しています

3. Performance Analysis

 Performance Analysisの方法論・コマンドなどをまとめた章です。「詳解システム・パフォーマンス」で紹介された内容も多くあります。

冒頭で前述した「Netflixのperformance engineerがサーバログインしてから最初の60秒で確認する内容」やBPFツール(bcc)を使った調査方法なども簡単に紹介されています。

4. BCC

bccコンポーネントや仕組み、インストール要件、ツールの特性の他、bccの中の代表的なツールとしてfunccount, stackcount, trace, argdistなどが紹介されています。

章の最後には「BCC Internals」として、仕組みの詳細や開発者向けのDebugの情報なども紹介されています。

5. bpftrace

4章と同じ構成で、bpftraceのコンポーネントや仕組み、インストール要件、ツールの特性などが紹介されています。

bccとbpftraceの大きな違いとして、bccで使えるようなツールを備えている一方で、bpftraceはDtraceのようなスクリプトを書けることが特徴の一つです。5章ではそのスクリプトの書き方がまとめられています。後半の章でもbpftraceのソースがかなりの量で紹介されているので、この書き方をある程度押さえておくとソースが読みやすくなります。

章の最後には4章と同じく、「bpftrace Internals」として、仕組みの詳細や開発者向けのDebugの情報なども紹介されています。

【6章以降の補足】

6章のCPUsから10章のNetworkingは「BPF Performance Tools」の核と言えます。

「詳解システム・パフォーマンス」でも「CPU」「メモリ」「ファイルシステム」「ディスク」「ネットワーク」のテーマを、6章から10章までのそれぞれの章で取り扱っていました。「BPF Performance Tools」も同じテーマをそれぞれの章で取り扱っています。

各章に共通している構成として、各テーマごとに次のようにまとまっています。

  • Learning Objectives: その章で学べること
  • Background: その章の対象技術の基礎知識(※CPUの章なら、CPUの基礎知識)
  • BPF Capabilities: BPFを使って、どういったトレースが実行できるか
  • Traditional Tools: 伝統的なトレース方法の紹介
  • BPF Tools: BPFのツール(bcc, bpftraceの両方)とワンライナー紹介

BPF CapabilitiesにはStrategyとして、どの部分をどの順番に見ていくと良い、という戦略をGregg先生が教えてくれるので、この部分だけでもすごく価値があります。

6. CPUs

CPUに特化した説明がまとまっています。

Traditional Toolsとして、次のツールを紹介しています。

Tool Description
uptime Load Averageと起動時間を表示する
top プロセスごとのCPU timeやシステム全体のCPU modeを表示する
mpstat CPUごとのCPU modeを表示する
perf タイムサンプリングのプロファイル
Ftrace Kernel Functionの統計やEventトレーシング

また、CPU関連のBPF Toolとして次のツールのUsage・Output・Args・SourceCode(bpftraceのみ。bccはなし)などが詳細に説明されています。

Tool Source Description
execsnoop bcc/bpftrace 実行されているプロセスを一覧表示
exitsnoop bcc exitしたプロセスと理由を表示
runqlat bcc/bpftrace CPU run queue latencyをまとめる
runqlen bcc/bpftrace CPU run queue lengthをまとめる
runqslower bcc 規定値より遅いrun queueの表示
cpudist bcc on-CPU timeをまとめる
cpufreq book プロセスごとのcpu frequencyのサンプリング
profile bcc CPU stack traceのサンプリング
offcputime bcc/book off-CPU stack traceと時間をまとめる
syscount bcc/bpftrace system callをカウント
argdist bcc system call解析に利用可能
trace bcc system call解析に利用可能
funccount bcc function callをカウント
softirps bcc software 割り込み時間をまとめる
hardirps bcc hardware 割り込み時間をまとめる
smpcalls book SMP call functionの時間をまとめる
llcstat bcc プロセスごとのLLCヒット率をまとめる

Traditional Toolsと比べても、CPU関連だけでもかなりのツールがあります。 BPFツールは単一目的のツールがほとんどなので、このコマンドだけ押さえればいいというものではなく、状況やレイヤーに応じてコマンドを使い分けていきます。

また、cpudistでon-CPU time, offcputimeでoff-CPU timeがわかるので、何か重い処理があったときにCPUかそれ以外に問題があるのか、切り分けに役立ちそうです。

7. Memory

Memoryに特化した説明がまとまっています。

Traditional Toolsとして、次のツールを紹介しています。

Tool Description
dmesg OOM Killer event詳細
swapon Swap device設定の表示
free システム全体のメモリ状況の表示
ps プロセス統計
pmap アドレスセグメントごとのprocess memoryの表示
vmstat システム全体の様々な統計の表示
sar page faultとpage scanner rateを表示可能
perf メモリ関連のPMC統計とevent sampling

また、Memory関連のBPF Toolとして次のツールが詳細に説明されています。

Tool Source Description
oomkill bcc/bpftrace OOM Kill eventの情報を表示
memleak bcc memory leak code pathを表示
mmapsnoop book システム全体のmmap(2)をトレース
brkstack book user stack traceとbrk(2) callを表示
shmsnoop bcc shared memory callを表示 
faults book user stack traceごとにpage faultsを表示
ffaults book ファイル名ごとにpage faultsを表示
vmscan book VM scannerのシュリンク・拡張を測定
drsnoop bcc reclaim eventのトレースとlatencyの表示
swapin book プロセスごとのswap-inを表示
hfaults book プロセスごとにhuge page faultsを表示
8. File Systems

File Systemsに特化した説明がまとまっています。

Traditional Toolsとして、次のツールを紹介しています。

Tool Description
df file systemの使用状況を表示
mount file systemの一覧やtypeを表示
strace system callをトレースでき、file systemのオペレーションも確認できる
perf file systemのtracepointsをトレースできる
fatrace Linux fanotify API(file access notify)に利用できるトレーサー

また、VFS, File Sysmte関連のBPF Toolとして次のツールが詳細に説明されています。

Tool Source Description
opensnoop bcc/bpftrace openされたファイルをトレース
statsnoop bcc/bpftrace stat(2) callをトレース
syncsnoop bcc/bpftrace sync(2) callをトレース
mmapfiles book mmap(2) fileをカウント
scread book read(2) fileをカウント
fmapfault book file map faultsをカウント
filelife bcc/book short lived fileのライフスパンを表示
vfsstat bcc/bpftrace VFS operationの統計
vfscount bcc/bpftrace すべてのVFS operationをカウント
vfssize book VFS read/write sizeを表示
fsrwstat book file system typeごとのVFS read/writeを表示
fileslower bcc/book 遅いfile read/writeを表示
filetop bcc top(1)コマンドのファイル版
filetype book file typeとプロセスごとのVFS read/writeを表示
writesync book sync flagによるregular fileへのwriteを表示
cachestat bcc Page cacheの統計
writeback bpftrace write-back eventとlatencyの表示
dcstat bcc/book directory cache ヒット統計
dcsnoop bcc/bpftrace directory cache lookupをトレース
mountsnoop bcc システム全体のmount, umountsをトレース
xfsslower bcc 遅いXFS operationを表示
xfsdist bcc XFS operation latency ヒストグラムを表示
ext4dist bcc/book ext4 operation latency ヒストグラムを表示
icstat book inode cache ヒット統計
bufgrow book buffer cache growthを表示
readahead book read ahead ヒットと効率を表示

 Traditional ToolsだとVFS, File Systemレイヤーのトレース方法が少なかったですが、かなりの種類のBPFツールがあり、よりObservabilityを確保する方法が増えました。

9. Disk I/O

DISK I/Oに特化した説明がまとまっています。

Traditional Toolsとして、次のツールを紹介しています。

Tool Description
iostat diskごとのI/O統計をまとめる
perf block tracepointを使ったdisk解析に利用可能
blktrace block I/O eventをトレース

また、Disk I/O関連のBPF Toolとして次のツールが詳細に説明されています。

Tool Source Description
biolatency bcc/bpftrace block I/O latencyのヒストグラムを表示
biosnoop bcc/bpftrace disk I/OをPIDとlatencyなどとまとめる
biotop bcc top(1)のblock I/O版
bitesize bcc/bpftrace プロセスごとのdisk I/O sizeをヒストグラムで表示
seeksize book disk I/O seekのsizeを表示
biopattern book diskアクセスパターンをrandom/sequentialに分類
biostacks book I/O initialization stack traceとlatencyを表示
bioerr book disk errorをトレース
mdflush bcc/bpftrace md flush requestをトレース
iosched book I/O schedulerのlatencyをまとめる
scsilatency book SCSI command latencyを表示
scsiresult book SCSI command resultを表示
nvmelatency book NVME driver command latencyを表示

Disk I/Oに関してもiostat以外の選択肢が増えたのは嬉しいです。 

10. Networking

Networkingに特化した説明がまとまっています。

Traditional Toolsとして、次のツールを紹介しています。

Tool Description
ss Socket 統計
ip IP 統計
nstat Network stack 統計
netstat Network stack 統計と状態を表示するマルチツール
sar Networkとその他の統計を表示するマルチツール
nicstat Network interface 統計
ethtool Network interface driver 統計
tcpdump 解析用のパケットキャプチャ

 また、Networking関連のBPF Toolとして次のツールが詳細に説明されています。

Tool Source Description
sockstat book high-level socket 統計
sofamily book プロセスごとに、new socketのaddress familiyをカウント
soprotocol book プロセスごとに、new socket protocol(TCP,UDP,UNIX)を表示
soconnect book socket IP-protocol connectionをカウントする
soaccept book socket IP-protocol acceptをカウントする
socketio book I/Oをカウントしつつsocket詳細をトレース
socksize book socket I/O sizeをプロセスごとのヒストグラムで表示
sormem book socket receive bufferとoverflowの状況を表示
soconnlat book stackと一緒にIP socket connection latencyをまとめる
solstbyte book socket first byte latencyをまとめる
tcpconnect bcc/bpftrace/book TCP active connection(connect())をトレース
tcpaccept bcc/bpftrace/book TCP passive connection(accept())をトレース
tcplife bcc/book TCP sessionのlifespanをトレース
tcptop bcc top(1)のTCP
tcpretrans bcc/bpftrace TCP retransmitをトレース
tcpsynbl book TCP SYN backlogをヒストグラムとして表示
tcpwin book TCP send congestion widow sizeや他のパラメータを表示
tcpnagle book TCP nagleの状況とtransmit delayをトレース
udpconnect book new UDP conncetionをトレース
gethostlatency book/bpftrace library call経由でDNS lookup latencyをトレース
ipecn book IP inbound explicit congestion notificationをトレース
superping book ICMP echo latencyをトレース
qdisc-fq(多数) book FQ qdisc queue latencyを表示
netsize book net device I/O sizeを表示
nettxlat book net device transmission latencyを表示
skbdrop book kernel stack traceと一緒にsk_buff dropをトレース
skblife book sk_buffのlifespanを表示
ieee80211scan book IEEE 802.11 WiFi scanningをトレース

Socket、TCPはかなりの数のBPFツールがありますが、UDPはまだまだ数が少ないです。今後の開発に期待しています。 

Networkingの章で、特に面白かったのが次のGregg先生の開発エピソードです。

11. Security

BPFツールを活用したセキュリティ関連の説明がまとまっています。ここでだけ紹介されているBPFツールとして、elfsnoop, modsnoop, bashreadline, shellsnoop, ttysnoop, eperm, capable, setuidsなどがあります。

12. Languages

プログラミング言語のトレースについてまとまっています。C言語Java, Bash,その他の言語(JavaScript, C++, Golang)をテーマに取り扱っています。

BPFでのstack traceを有効にするには、frame pointer registerを有効にした上で(言語のRuntimeを)ビルドする必要があるので、そこはネックになりそうです。

13. Applications

プログラム言語の次は、Application(Software)のトレースについてまとめています。この章ではMYSQLを題材にして、6章から紹介されてきたBPFツールやMySQL用のBPFツールを使って解析をしていきます。

14. Kernel

これまでシステムの各レイヤーやプログラミング言語やアプリケーションのトレースが説明されてきましたが、Kernel自体のトレースが14章のテーマです。

loads, wakeuptime, offwaketime, mlock, mheld, kmem, kpages, memleak, slabratetop, mumamove, workqなどのBPFツールが紹介されています。

15. Containers

ContainerやNodeのトレースについてまとめている章です。この章でもContainer向けのコマンドが紹介されていますが、どちらかというと6章「CPU」〜10章「Networking」の内容が重要になってくると、本文中にもあります。

Traditional Toolsは、sytemd-cgtop, kubectl top, docker stats, perfなどが紹介されています。

対してBPFツールは、runqlat, pidness, blkthrot, overlayfsが紹介されています。

16. Hypervisors

Hypervisorのトレースについてまとまっている章です。xenhyper, cpustolen, kvmexitsなどが紹介されています。

17. Other BPF Performance Tools

bccとbpftrace以外のBPF Performance Toolを紹介した章です。17章では、次のツールが紹介されています。

18. Tips, Tricks, and Common Problems

最終章です。

BPFツールを作ったり、トレースしたりするときのTipsやテクニック、アドバイスなどが載っています。トレースにかかるOverheadの計算式や開発の極意など12個もアドバイスがあり、「Gregg先生は読者の心も読めるのか?」と思うような的確ぶりでした。

Kubernetes上のBPFによるトレーシング

ここまでが本の内容でしたが、人によっては面白いかもしれないので、自分が仕事で(たまに)使っているBPFツールによるトレーシングについて簡単に書こうと思います。

普段から使っているわけではありませんが、すぐに解決できない問題があった時はBPFツールを使って問題解決をすることがあります。

Kubernetes上のPodに、Ephemeral Containersのような形でPodを立てて、そのContainer内でbccやbpftraceを使っています。

BPFツールを自作するレベルではないので、基本的にbccとbpftraceに用意されているツールを利用しています。

この方法があれば、Traditional Toolsだけでは取れない領域も情報が取得できるようになるのですが、今だと次のような課題もあります。

  • Nodeレベルでしかトレースできない(Containerごとに取れない)
  • Node上に複数プロセスが立ち上がっていると、対象コンテナ以外のノイズが酷い
  • 複数Podがいると、トレースしたいPodがいるNodeをうまくコントロールしないとトレースできない

上記のように、複数プロセス・複数のNode、複数のPodがあると非常に目当てのトレースがしにくいです(Kubernetesとは相性が悪いですね)。

ただし、業務でも役立っています。たとえば、ある時 特定のApplicationのAPIをコールすると、Nginxが502を返すという問題がありました。その時点では、ログらしいログがなく原因が不明でした。

原因自体はOOM KillによってプロセスがKillされて、Nginx → App間で応答できなくなり502が発生していたのですが、signalkillsnoop, sysdig inspectを使って、SIGKILLを実行したプロセスを特定し、oomkillでOOM Killが発生していることが特定でき、原因を解明できました。

PerformanceチューニングにもBPFを活用したいので、いずれは用意されていないツール用に自作の道に進むかもしれません。

感想

かなり分厚い本ですが、これだけ多くの話題とツールを扱っているので納得の重厚さでした。インフラを始めたばかりの頃は、topコマンドやpsコマンドなどを見ても、情報量が多くてどこを見ていいか戸惑ったり、表示されている数字が何を意味しているのか、よく分からないことが多くありました。

初めて本書で触れたBPF Toolsたちも同じで、表示される数字が何を示しているのか、どのパターンでどんなコマンドを使っていけばいいのか、まだまだ分からないことが多いです。本の分量や内容ともに一度読めば理解できるものではないと思っています。きっと、何度もコマンドを打って、考えなくても分かるようにしないとなぁ、と思っています。

また、bccやbpftraceに出てくるBPFツールは特定レイヤーにおける単一目的を持ったツールばかりなので、これさえ押さえておけば良いという代物ではありません。結局Linuxの各レイヤーの振る舞いの理解や、OS・カーネルの動作の理解が必要になった上で、適切なツールの選択が重要になってきます。

ただ確実に言えることは、BPF Performance Toolsで出てきたBPFツールは強い武器になる、ということです。Netflixのエンジニアが本番で活用しているように、システムでPeformanceの問題が出た時にその原因を特定するための手がかりになってくれます。この武器を繰り返し使って、手に馴染ませていくのが今後の課題になりそうです。

 

以上