Two women colleagues sitting in front of a Mac laptop: one woman on the left with a black shirt, and another woman on the right with glasses and a gray blazer

セキュリティ、ネットワーク、オブザーバビリティなどに関する機能などを実装する際には、Linuxカーネルでの作業が理想的です。しかし、課題がないわけではありません。カーネルのソースコードを修正するにしても、モジュールを追加するにしても、開発者は従来、複雑なインフラや抽象化されたレイヤーに悩まされ、デバッグが困難になっていました。 これらの問題を解決するのが拡張BPF(eBPF)です。

eBPF(Extended Berkeley Packet Filter)は、カーネルのソースコードを変更したり、モジュールを追加したりすることなく、プログラムを実行することができる(Linux 4.xより導入された)カーネル技術です。eBPFはLinuxカーネル内の軽量なサンドボックスされた仮想マシン(VM)と考えることができ、プログラマーは特定のカーネルリソースを利用したBPFバイトコードを実行することができます。

eBPFを使用することで、カーネルのソースコードを変更する必要がなくなり、ソフトウェアにより効率的に既存のレイヤを活用できます。その結果、eBPFは、ネットワーク、オブザーバビリティ、セキュリティなどのサービスの提供方法を根本的に変える可能性を秘めた強力な技術となります。

ここでは、この技術が何なのか、どのように機能するのか、そしていつ導入を検討すべきなのかを詳しく説明します。

eBPF はどのように動作するのか

eBPFプログラムはイベントドリブンで、コードパスに添付されます。コードパスには、フックと呼ばれる特定のトリガーが含まれており、フックがトリガーされると添付されているeBPFプログラムが実行されます。フックの例としては、ネットワークイベント、システムコール、関数エントリ、カーネルのトレースポイントなどがあります。

eBPFプログラムがトリガーされると、コードはまずBPFのバイトコードにコンパイルされます。さらに、そのバイトコードが実行される前に検証され、ループが発生しないことが確認されます。このステップにより、プログラムが誤って、または意図的にLinuxカーネルを破壊することを防ぎます。

プログラムは、フックでトリガーされた後、ヘルパーコールを実行します。ヘルパーコールとはeBPFにメモリアクセスのための様々な機能を持たせるための関数です.ヘルパーコールは、カーネルによってあらかじめ定義されている必要がありますが、利用可能な関数は今後増えていくでしょう

eBPFは、当初、ネットワークパケットをフィルタリングする際に、オブザーバビリティや安全性を高めるために使われていました。しかし時が経つにつれ、ユーザーが提供するコードの実装をより安全に、より便利に、より良いパフォーマンスで行うための手段となっていきました。

eBPFのメリット

eBPFは、一般的にユーザー空間のプロセスをトレースするために使用されますが、その利点はここで発揮されます。以下のことがらを確保するための安全で有用な方法です。

  • スピードとパフォーマンス。eBPFは、パケット処理をカーネル空間からユーザー空間に移すことができます。同様に、eBPFはジャストインタイム(JIT)コンパイラです。バイトコードがいったんコンパイルされた後は、メソッドごとにバイトコードを新たに解釈するのではなく、eBPFが起動されます。
  • 煩雑さの少なさ。デバッガとして利用する場合、eBPFは、プログラムの状態を観測するためにプログラムを停止する必要がありません。
  • セキュリティ。プログラムは効果的にサンドボックス化され、カーネルのソースコードは保護され、変更されません。また、検証を行うことにより、無限ループのプログラムでリソースが圧迫されないように保証しています。
    利便性。カーネルの機能をフックするコードを作成することは、カーネルモジュールを構築して維持することよりも少ない労力で済みます。
  • 統一されたトレース。eBPFはプロセスをトレースするための単一の、強力でアクセス可能なフレームワークを提供します。これにより可視性とセキュリティが向上します。
  • プログラムのしやすさ。eBPFを使用することで新たなレイヤを追加することなく、環境の機能を豊富にすることができます。同様に、コードはカーネル内で直接実行されるため、他のトレーサのようにデータをダンプするのではなく、eBPFのイベント間にデータを保存することが可能です。
  • 表現力。eBPFは、通常は高級言語でしか実現できない機能を表現力豊かに実現します。

eBPFのベストプラクティス

eBPFは非常に新しい技術であるため、まだ使い込まれていないところがたくさんあります。eBPFのベストプラクティスは、この技術が注目されるにつれ、まだ進化し続けています。明確なベストプラクティスは存在しませんが、効果的かつ効率的なプログラムを実現するためにできることがいくつかあります。

エコシステムにeBPFを使用する場合、以下のことをお勧めします。

  • LLVM Clangを使ってC言語をバイトコードにコンパイルしましょう。eBPFが登場した当初は、プログラムのコーディングやアセンブルを手作業で行う必要がありました。その後、開発者はカーネルのアセンブラを使ってバイトコードを生成していました。幸いなことに、このような作業はもう必要ありません。Clangは、C言語のフロントエンドとツールのインフラを提供しています。
  • BPFプログラムを書くときは、BCCツールキットを使いましょうBPF Compiler Collection(BCC)は、効率的なカーネルトレースや操作プログラムを作成するのに役立つツールキットです。特に、パフォーマンス解析やネットワークトラフィックの制御に関する作業に適しています。

eBPFの落とし穴

eBPFは強力ではありますが、すべてのプロジェクトやエコシステムに適合する銀の弾丸ではありません。eBPFにはいくつかの顕著な欠点があり、特定のケースでは動作に不満を感じることがあります。開発者の中には、eBPFを使いこなせないと感じる人もいるかもしれません。

  • Linuxのしかも最近のカーネルでのみ動作します。eBPFは、Linuxカーネルで開発されており、完全にLinuxカーネル指向です。そのため、他のトレーサーに比べて移植性に劣ります。さらに、かなり新しいカーネルが必要です。v4.13より古いものを使用している場合は使用することができません。
  • サンドボックス化されたプログラムは制限されています。eBPFは、プログラムがアクセスできるリソースを制限することでセキュリティを高めています。しかし、プログラムがアクセスできるOSの部分を制限することで、機能も制限される可能性があります。

eBPFが一般的にうまく機能する場合

eBPFはクラウドネイティブアプリケーションで急速に普及しています。その結果、eBPFは2つの状況で最もよく使われています。

  • カーネルトレースを使ったオブザーバビリティが必要な場合。このような状況では、eBPFはより速く、より正確です。コンテキストスイッチの必要がなく、eBPFのプログラムはイベントベースなので、特定のトリガーなしには何も実行されず、発生した事象を見逃すことがありません。
  • 従来のセキュリティ監視では対応できない場合。 eBPFはKubernetesをはじめとする分散環境やコンテナベースの環境で多く利用されています。このような環境では、eBPFはHTTPトラフィックを可視化することができるため、可視性のギャップを埋めることができます。

また、以下のような他のセキュリティ対策にもeBPFが導入されていることがあります。

  • ファイアウォール
  • デバイスドライバー
  • ネットワークパフォーマンス監視

New RelicとeBPF

Pixie(New Relicが買収)は、オープンソースのkubernetesネイティブなクラスター内でのオブザーバビリティプラットフォームで、手動での計装なしにKubernetesワークロードを即座に可視化します。 eBPFがPixieプラットフォームを支える魔法のほぼすべてです。前述のように、eBPF ではイベントがトリガーされたときに制限されたコードを実行することができます。このイベントは、カーネル空間 (kprobes) またはユーザ空間 (uprobes) の関数である可能性があります。Pixie はuprobesとkprobesの両方を使用して、サービスとアプリケーション間のオブザーバビリティを実現しています。 

PixieはeBPFを活用してテレメトリーデータを自動的に取得し、Kubernetesのメタデータと接続することで、データをローカルに保存したまま可視性を提供します。この可視性はNew Relicの強力なKubernetesオブザーバビリティソリューションを補完するものです。また、5月下旬から、Pixieが生成したテレメトリーデータをNew Relic Oneに送信することができるようになり、スケーラブルな保存期間、強力な可視化、高度な相関関係、インテリジェントなアラート機能を得ることができます。

eBPFによるオブザーバビリティの効率化

eBPFは、Linuxカーネルのオブザーバビリティ、ネットワーク性、セキュリティを向上させる新技術です。カーネルのソースコードを変更したり、モジュールを追加したりする必要がないため、複雑になりすぎず、システムを支えるリッチなインフラを構築することができます。

この記事では、eBPFとは何か、どのように機能するのか、そしてなぜ分散環境で有用なのかを見てきました。カーネル層から監視することで、クラウドにおけるオブザーバビリティに関する課題の多くが解決されます。より深い可視性、より多くのコンテキスト、そしてより正確なデータを得ることができます。