Keisuke
多分特定のIPアドレスから来たリクエストをドロップしたりとか、
そういったこともできるかなと思います。
ken
多分結構厳格なAPIという印象なんですけど、
Linuxでそもそもユーザーが書いたアプリケーションが動く以降、
ユーザーランドっていうところと、
あとカーネルが提供しているシスコールが動くカーネルランドみたいなのがあって、
そこのインターフェースが今まではシステムコールシスコールでやり取りしてたんですけど、
EBPFっていうのは、
普通に例えばレールズアプリケーションとかノードアプリケーションを書いて、
バイトコードにするとユーザースペースで動くんですよね。
だけどEBPFプログラムが実行されるのはカーネルランドのほうということで理解してるんですけど、
Keisuke
それあってますか。
そうだと思うかも認識していて、
そうですね、EBPFのプログラムを書くっていうのは、
プログラムの中身自体は最初Cで書きます。
Cで書いたのをクランっていうコンパイルを使って、
EBPFのバイトコードにしまして、
このバイトコードをカーネルにロードして、
なのでカーネルが領域で動くんですよね、プログラムは。
ken
BPFのバイトコードでまずコンパイルするんですよね、EBPFプログラムを書いてCで。
Keisuke
その書いたEBPFのプログラムと、
ユーザースペースで動くプロセスっていうのを通信させて、
なのでEBPFプログラムが取得した情報をもとにユーザースペースで何かしたいっていうことがあったときに、
そのブリッジになるみたいな部分がEBPFのマップって呼ばれる機能があって、
そこでEBPFのプログラムとユーザースペースのプロセスのやり取りに使われるって感じですね。
ken
明示的にどんなやつをやり取りするか、メッセージやり取りするかってのを書かなきゃいけないから、
例えばフロントエンジニア向けに他のアナロジを紹介する、
例えばサービスワーカー同士でセンドメッセージ、ポストメッセージするとかみたいな感じだったりなのかなと思ってはいるんですけど、
そこでコンパイルされたBPFのバイトコードの中に、
例えばさっきのセキュリティの話で言うと危険なコードとか入っていても、
それが実行される前に多分検証プロセスが入るから、
Keisuke
意図的にLinuxカーネルをぶっ壊すようなコードとかもそこで弾かれるっていうことなのかなと思います。
そうですね。BPFのバイトコードが実行される前に、
ベリファイヤーって呼ばれるものがカーネル領域にいまして、検証ですよね。
バイトコードが何か違反してないかっていうのをチェックしまして、
違反してるようなプログラムであればそもそも実行できない、拒否しちゃうみたいなことがあって、
そのベリファイヤーに通過したものだけが実行されるので、
安全かなと。
よくEBPFでできることで、カーネルモジュール変えちゃえば同じようなことができると思うんですけど、
カーネルモジュールってカーネルにロードして任意のプログラムを実行できるっていう点では、
EBPFと似てるかなと思うんですけども、
カーネルモジュールの中では何でもできちゃうので、
もし何かパニックが起きちゃうと、もうシステム自体ダウンしちゃったりするんですけれど、
EBPFだったらその辺りは、そうですね、より安全かなというふうに思ってます。
Kazunari Okuda
なるほど。何が新しいのかなっていうのが、EBPFの良さ、
似たようなことはLinuxの中でできなかったのかなとちょっと思ってたんですよ。
私は詳しくないのでわかんないんですけど、
でもそこが安全にできるという点がEBPFの良さなのかなと。
Keisuke
注目されてる点に、やっぱり安全な実行環境が用意されていて、
手軽にカーネル領域に対して何かできるっていうところがやっぱり有利でして、
以前だとやっぱり、もうそもそもカーネル自体に変更を加えちゃってやりたいことを実現するのか、
カーネルモジュールを用意してやりたいことを実現するっていうのが大きくあったとしたときに、
カーネルに直接加えるっていうのはかなり長い時間を要してデビュープロセスとか、
あと実際にマージされてもUbuntuとかRELとかそういったディストリビューションに配布されるにはもう何年もかかっちゃうみたいなことがあって、
そういう時間をスキップしてEBPFでとりあえずやりたいことを簡単に実現しようみたいなのは、
今注目されてる理由にあるかなというふうに思ってます。
ken
なるほどね。だからビジネス上、本番展開をしたりとか、ユーザーに早く届けたりとか、
デプロイメントとかマシン展開の用意さみたいなことを考えると、
カーネルモジュールを変えて頑張ってインストールして配布してよりは、
EBPFのバイトコードをコンパイルして動かす方がまだ簡単だよねみたいな。
かつ安全だよねみたいな感じなのかな。
Keisuke
僕もそういうふうに認識してます。
なるほど。
僕がEBPF注目したのもやっぱりその手軽さなんですけれども、
もともとLinuxカーネルのことをもっと勉強したいなって思ったときに、
カーネルにちょっと変更を加えてみたいなって思って、
壊して作って、壊して作ってっていうプロセスで新しいことって勉強できると僕は思ってるんですけど、
カーネルを壊しちゃうと復帰が大変だなと思ってて、
なかなかハードル高いなって僕は思ってたんですけど、
高そう。
EBPFのテクノロジーを使うと手軽にできるなと思って、
まずカーネルのことをもっと深く知る前にEBPFでできることをいろいろやって、
カーネルのことを勉強しようって思ったのが、
僕が勉強を始めたモチベーションです。
ken
カーネル自体、かなり深淵な技術領域ですからね。
僕はもう全然ヒヨコなのでわからないし、
ナックスカーネルだけで一生食ってるようなエンジニアの方もいますからね。
これ流行り始めたのって5,6年前くらいから、
多分技術としてもっと前からあったと思うんですけど、
多分元Netflixのブレンダー・グラックとかが本を書いたりとか、
彼はシステムパフォーマンスみたいな本を書いて、
わりとオピニオンリーダーみたいなところがあるので、
SREとかインフラ領域とかで僕は知ったんですけれども、
そこからその後いろんな人がEBPF使い始めて、
結構サービスとかも出てきたりして、
っていう感じで、
わりとここ2,3年は、
ただEBPFを言うだけじゃなくて、
実際に本番こういうの展開しました?サービスはしました?
みたいなアプリケーションというか応用、
実際の展開みたいなのがニュースに出てくるような印象ではありますけれども、
けいすけさんは何年ぐらいから?
Keisuke
2年前ぐらいですかね。
知ったきっかけが、
カーネルのこと勉強したいなと思っていろいろ調べてたときに、
EBPFって言葉を、その時点では言葉しか知らなかったので、
何も具体的な中身とか知らなかったんですけど、
そんなテクノロジーがあるんだっていうふうに、
ちょっと頭の片隅にあって、
そしたら速報してるうちに、
僕が働いてる会社がEBPFを使った製品を出しまして、
聞いたことあるテクノロジーが使われてると思って、
その出してる製品がやってることっていうのが、
Linuxのホストで動いてる、
そのホスト上で起きてるHTTPの通信とかを監視して、
ネットワークのパフォーマンスを監視するっていうような製品を出していて、
最初僕が使ったときに魔法みたいだなっていうふうに感じまして、
わざわざアプリケーションにセットアップをしなくても、
アプリケーションっていうのを個別に認識していて、
それぞれのAPIのリクエストとかのレイテンシーとか、
そんなのが分かったりして、すごいなと思いまして、
それでどうやって動いてるんだっていうのが気になって、
どんどん仕組みをしていろうと勉強した流れですね。
なので僕自身が知ったのは2年ぐらい前なんですけど、
先ほどちょっと話出たBrendan GreggのBPF Performance Toolsっていう本があって、
ken
僕はLinuxも全然わかんないし、
インストールとかそもそもどうするのみたいな、
ツーリングも全然なかった状況なので、
それで頑張ってやろうとしたんだけど、
なんかよくわかんなくてBPFの本読んでたら、
もう海外地味に遺跡の時間が来ちゃったみたいな、
挫折した技術としてだいぶ思い出深いので、
今こうして話してるのがすごい懐かしいんですけど、
僕は最近のツーリングの発展と全然追ってなくて、
当時ってBPFトレースみたいな、
トレーシングランゲージっていうのを書いて、
実行させるものがあったりとか、
あとはBCCっていう割と初学者向けにも使いやすいような
ツールキットっていうのを提供して、
バイソンとかでもバインディングとか提供して書けるようなものがあった印象なんですけど、
最近のツーリングはどういったものがあるかとかっていうのも
けいさけさんに聞いてみたいなと思っていて、
多分BCC、BPFトレースぐらいだったら僕も聞いたことあるんだけど、
どういったものがあるのかなと思っていて。
Keisuke
なるほど。
最近、僕が作ったOSSで使ってるライブラリっていうのは
シリアムっていうプロジェクトがあって、
そこが出してるEBPF、
Goで書いたんですけれども、そのツール自体は。
シリアムっていうGitHubのレポジトリがありまして、
そこにEBPFっていうレポジトリがあるんですが、
そのライブラリを使って僕はそのツールを開発しました。
これ使うと。
ken
何をしてくれるやつなんですか?
Keisuke
書いたものとしてはCのコードとGoのコードって2つ言語があるんですけれど、
そのCの部分はEBPFのプログラムに該当します。
そのEBPFのプログラムで取得した情報を得て何か、
ユーザースペースで何かしたいっていうその何かしたい部分をGoで実現していて、
そのEBPFのプログラムとGoで書いたプロセスっていうのを、
あんまり中身で何が起きてるかっていうのはあまり意識せずに、
簡単につなげてくれるようなライブラリっていうのが提供されていて、
そこでチュートリアルとか、
Exampleのコードっていうのもレポジトリ内に存在していて、
そのExampleを手元でちょっとビルドして動かしてみて、
っていうみたいなとこから始めましたね。
で、そのExampleのコードの中身をちょっと変えてみてまたビルドして動かして、
壊れたとかうまくいったとか、そんなのを繰り返しながら勉強しました。
ken
なるほど。
だからGoで書いたアプリケーションプログラムは、
その1プロセスとしてユーザーランドで動いており、
Cで書いたものが多分ツーリングがいい感じに途中でBPFプログラムとして、
BPFのバイトコードにコンパイルしてくれて、
それがKernel&動き、
その間がさっき言ったメッセージングAPIでやり取りされてるっていう理解であってますか。
Keisuke
Goで書いたバイナリを実行する前にやることとしては、
Cで書いたプログラムをクランを使ってコンパイルして、
バイトコードにしておいて、
そのバイトコードがあると、
Ciliumのライブラリを使っていると、
そのバイトコードっていうのを使って、
バイナリの実行時、なので起動プロセスぐらいのときに、
Kernelにロードしてみたいな処理をしてくれるんですよね。
なので、
ken
ロードしてくれるんですね。
Keisuke
eBPFのプログラムをコンパイルするタイミングは実行前。
それはCiliumのプロジェクト内に提供されている、
なんて名前でしたっけ。
BPF2GOっていうツールがあるんですけど、
そのツールによって変換して、
プログラムをバイトコードに。
それをしておくと、
実行時に下準備はしてくれるというか。
ken
なるほど。
なんかハマりどころってありました?
それを聞いたら単純な僕はできそうかなって思ってしまったんですけど。
Keisuke
僕もできそうかなって思ってたんですけど、
まず僕はその時点で、
僕の技術レベルとしては、
Kernelも勉強中で全然詳しくないですし、
今でも勉強中ですけど、
そもそもCのコードも読んだことぐらいしかなくて、
ken
ちゃんと書いたことなくて。
Keisuke
なんか5のことは知ってるけど、
Cだとどうやるんだっけみたいな。
あとポインタの操作っていうのを結構しまして、
あとそのeBPFのプログラムで、
例えばですけど、
Kernelのファンクションをフックすることもできるんですけど、
ユーザープロセスのユーザー定義のファンクションに
アタッチすることもできるんですね、
eBPFのプログラムを。
僕はそのuProveっていう名前がついてるんですけどそれは、
Kernel内のファンクションにアタッチするのはkProveっていう名前がついてて、
kがKernelでuがユーザーだと思うんですが、
そのuProveっていうのを使って、
僕はツールを作ってたんですけど、
その時にユーザー定義のファンクションにアタッチして、
そこでeBPFのプログラムが呼ばれて、
その中でアクセスできるものがCPUのレジスタにアクセスできるんですね。
そのファンクションが呼ばれたときのCPUのレジスタにアクセスできて、
そのCPUのレジスタの中に、
もちろん扱ってるデータがインテージャーとかだったら、
レジスタから直接取れるんですけど、
ストリングとかストラクトとかだったら、
メモリのアドレスだけ書いてあって、
そこから飛んで、上から何倍飛め?
オフセットとか使って、
そこのデータを取りたいとかってなると、
そういったポイントの操作が必要になってくるんですが、
そういうの全然意識したことがなかったので、それまで。
確かに。
どうやってやるんだっていうのが全然わかんなくて、
そこはかなり苦労しました。
なんですけど、
僕が見つけた方法としては、
GDPっていうデバッカーがあると思うんですが、
Cとか、
Goにも使えるんですけど、
Cのデバッカーとかで有名だと思うんですが、
そのデバッカーを使って、
アセンブリが見れるので、
アセンブリの行動とかを見て、
このメモリの操作とかしてるのを見て、
ここでプラス何倍としてるから、
ってことはマイナス何倍とすればとか、
そんなのを見て地道にポイントの操作っていうのをやって、
初めてのことだったんで、僕は。
多分それって今ではあんまりお勧めされないっていうか、
アンセーフな作業なので、
Goとかモダンな言語のラストとかだったら、
あんまりできないように何とかしてると思うんですけど、
ken
高級言語だとそうですよね。
Keisuke
でもCだとそういうのができるし、
それは自分にとって新鮮で面白かったですね。
なるほど、なるほど。
なんでそこはハマったっていうか、
初めてだったんで、
Kazunari Okuda
ファードルがかなり高かったです。
ken
技術的に面白そうですけどね。
なかなかそれをデッドラインの限られたファンクション、
フィーチャーのプロダクトアウトに合わせてそれをしてくださいって言われると、
なかなか厳しいものがありそう。
それが本業だったらいいけれどね。
Keisuke
完全に趣味プロジェクトだったんで、
いっぱい時間を使えたんですけど。
Kazunari Okuda
大学時代思い出しました。
CS取ったんですけど、そこでアセンブリで、
ライトをピカピカさせるみたいな、
一緒に学部内でやったんですよ、その時に。
僕の学生時代ってマッチで、
本当にあんまり興味なかったんですよね、
プログラミング正直言って。
ポインターとか本当に理解するの、
今だったら興味があるんですけど、
その時は全然興味なくて、
なんだこれみたいな。
でもできた時は面白かった。
こういう順番でライトをピカピカさせてみたいな、
アセンブリでプログラムを書いてやるんですけど、
Keisuke
わざわざユーザープロセスまでいかなくていいっていうか、
そっか、それは実装次第ですか。
ken
例えばよくLinuxビギナー本とか読んだりすると、
いろんなコマンドが出てきますよね。
そのコマンドを叩くと、
例えば今動いているプロセス一覧が出てきたり、
ネットワークトレースができたりして、
あれって確かほとんどは、
例えばあくまでユーザーランドで動いているアプリケーションで、
例えば添付ファイルとかファイルシステムとかに書き出したものを読んで、
整形したりとかしてるんですけど、
EBPFだともうカーネルランドで全部必要な情報を取って、
整形して落としてくれるから、
例えばもうそれこそさっき出てきたGoogleとかAzureとか、
クラウドベンダーとかが大規模なマシンにスケールさせる
オブザーバリビリティツールを提供しますってなったら、
圧倒的にコストパフォーマンスのほうが勝つと思うんですよね。
実装の大変さとか保守性とかを加味した上でも。
だから一スタートアップとかのオブザーバリビリティエンジニアが
すごい詳しいかっていうと分からないけれども、
そういった大きい会社にスケールメリットがあるような会社で
オブザーバリビリティに近い仕事をしてる人は
割と最近やってる人が多いのかなと思ったりします。
Keisuke
そうですよ。
なんか使ったことはないんですけど、
多分有名な例としてFacebookが、カトランだっけな。
ロードバランサー?
ロードバランサー、あれもEBPFを使ってたはずで。
ken
そうですね。
Keisuke
それもパフォーマンスを向上させたいっていう目的で
EBPFを使ってたと思います。
ken
あった、カトランですね。L4ロードバランサーですよね。
ネットワーク周りで何かエッジを効果したいみたいなときに
EBPFの技術を知っておくと多分こういうことができるんでしょうね。
なんかそのEBPFのすごいコアコミッターの
アレクセイさんみたいな人も確かFacebookの人ですよね。
そうですね。
ファミリーネーム何て読むのか分かんない。
僕も分かんないです。
ストラボイトフとかかな。
Keisuke
あれは多分今もレビュアーでいて
ちょっと詳しくは見えてないですけど
Linux関連6.9のリリースに含まれている
2つぐらい大きなEBPF関連のリリースがあったんですけど
それのレビューとかに彼の名前があったような気がします。
ken
なるほど。
Keisuke
レビュアーの中か。
Kazunari Okuda
すいません。
そのEBPFのOSS開発されていらっしゃるって聞いたんですけど
例えばNodeとかRubyとかみたいに
EBPFのプログラムをディストリビュートさせるサービスみたいな
こういうのを監視できますよみたいな
ジェムみたいな、Rubyでいうジェムみたいな
そういうプラットフォームとかってあったりするんですか?
それともそういうのってGitHub上で
好みのやつっていうか調べて
ダウンロードしてインストールするみたいな感じなんですかね?
どういう感じなのかな?
Keisuke
あと僕もうまく配布する方法っていうのが分かってなくて
僕のもうプロジェクトは完全趣味の簡単なツールだと思ってるんで
もう手元でビルドしてくださいっていう風に書いてます。
でもどうなんでしょう?
世の中のEBPF使ってるプログラムは
どういう風に確かに作ったものをディストリビュートしてるかっていうのは
ちょっと想像がとんじゃないです。
かなり複雑なことをしてたような印象があります。
あとテストもすごく難しいと思ってまして
Unitテストとか書くのすごく難しい。
ken
確かに。どうしてるんですか?
Keisuke
書けないのかな?多分E2Eとかで担保してるような気がしますけど
なんか自分の会社で聞いたのは
もういろんなバージョンのUbuntuとかDellとか用意して
もうその上で走らしてでE2Eとかやってるって聞きましたね。
なんでもうお金がかかると思います。かなり。
もうマシンを大量に用意してる。
なかなか体力ある会社じゃないとできないですね。
Kazunari Okuda
そうですね。
モバイル機種ごとにいろいろテストするみたいな
わからないですがアプリのテストとか
モバイルのゲームのテストみたいな感じを思い出しましたね。
ken
そうか。かずさんゲーム会社でも働いてたことありましたもんね。
けいすけさんが作ってるOSSの話もまとめて聞いてみたいなと思っていて
どんなものを作っていてどんな機能があって
開発費はとかデバッグの大変さとか
そういうことテストどうしてるのかとか
詳しく聞いてみたいなと思うので
よかったら紹介してもらってもいいですか?
Keisuke
僕が作ってるツールが
Goで書かれてるプログラムのプロセスを監視する
デバッグツールみたいなものを開発していて
Goにはゴルーチンっていうのがありまして
スレッドみたいな形のものなんですけれども
ゴルーチンが作成されたときと終了したときっていうのを
そのイベントその2つのイベントに対して
GPFのプログラムを書いていて
作成と終了っていう2つのイベントから
ゴルーチンのライフタイムみたいなのを計測したり
あとゴルーチンが作成されたときの
そのプログラムのスタックトレースっていうのを取得して
どんなスタックトレースで
そのゴルーチンが作成されたかっていうのを
アウトプットするようなツールを作りました
ken
なるほど
それアウトプットとしては今はどういったものがサポートされてるんですか
コンソールに吐き出すような感じ
メトリックスで取りにいくような感じですか
Keisuke
高純出力に吐くものと
あとオープンメトリックスの形式で
ゴルーチンの作成カウントと終了カウントと
あとそのゴルーチンのアップタイムっていうのを
Kazunari Okuda
3つのメトリックスを出力するようなものを作りました