MicroArchitectures
H.Ueda
Programmer
ブログ
zeroserve: eBPFで「設定ファイル」を「スクリプト」に置き換えるWebサーバーの新しい形
今回は、zeroserve: a zero-config web server you can script with eBPF という記事を読んで、Webサーバーの設定とカスタマイズのあり方について面白い視点が得られたので、内容を整理して紹介したいと思います。
設定ファイルが eBPF って心憎い感じですね。一度、試してみたいな。
Webサーバーを運用する際、複雑なルーティングや認証、レート制限などを設定ファイル(nginx.confなど)で記述するのは、意外と骨が折れる作業かと思います。zeroserveは、こうした「宣言的な設定ファイル」の限界を、eBPFによる「スクリプト記述」で解決しようとするユニークなプロジェクトです。
zeroserve の概要と特徴
zeroserveは、軽量で高速な、設定不要(zero-config)を謳うHTTPSサーバーです。大きな特徴は、Webサイトのコンテンツを一つの tar ボールとして扱い、その中に eBPF プログラムを含めることで、リクエストごとの処理を自在に制御できる点にあります。
主な特徴をまとめると、以下のようになります。
- 高いパフォーマンス:
io_uringを全面的に採用しており、1コア環境でのベンチャマークでは多くのワークロードで nginx を上回る性能を見せています。 - プログラムによる設定: 独自の設定言語(DSL)を持つ代わりに、eBPFプログラムそのものを「設定」として扱います。
- シングル・ターボール配信: サイトの全データを一つの
tarファイルにまとめ、展開せずにそのまま配信します。 - アトミックな更新:
SIGHUPシグナルを送るだけで、サイト内容、スクリプト、TLS証明書を瞬時に、かつ接続を切らさずに更新できます。
処理の流れ
リクエストが届いてからレスポンスが返るまでの流れは、以下の図のようなイメージです。
flowchart TD
Client[クライアント] -- HTTP/2 / TLS 1.3 --> Server[zeroserve 本体]
subgraph zeroserve [zeroserve Process]
IO[io_uring ネットワークI/O] --> Dispatcher[リクエスト・ディスパッチャ]
Dispatcher --> EBPF[ユーザ空間 eBPF サンドボックス]
EBPF -- ルーティング / 認証 / 加工 --> Content[tar ボール内の静的ファイル]
EBPF -- プロキシ --> Backend[外部バックエンド]
end
Content --> Client
Backend --> Client
「設定」としての eBPF プログラム
既存の Web サーバー(nginx や Caddy など)では、location ブロックや rewrite ルールといった「宣言的」な設定を書くのが一般的です。しかし、要件が複雑になると、こうした設定ファイルだけでは対応できず、Lua スクリプトを組み込んだり、独自のプラグインを書いたりする必要が出てきます。
zeroserve の設計思想で興味深いのは、「最初からプログラム(eBPF)を設定として使う」と決めている点です。
なぜ eBPF なのか
通常、eBPF は Linux カーネル内で動作するものですが、zeroserve ではユーザ空間で eBPF を実行しています。これには以下のようなメリットがあると考えられます。
- 安全性: サンドボックス化されているため、スクリプトのミスでサーバー全体がクラッシュするリスクを抑えられます。
- 速度: JIT(Just-In-Time)コンパイルによってネイティブコードとして実行されるため、リクエストごとに実行してもオーバーヘッドが極めて小さいです。
- 柔軟性: C言語などで記述したロジックをそのまま持ち込めるため、複雑な条件分岐も直感的に記述できます。
たとえば、特定のヘッダーがある場合だけリバースプロキシに飛ばす、といった処理も、一つのスクリプト内で完結して記述できるわけですね。
実務的な運用サイクル
運用のシンプルさも、こちらが注目したいポイントです。一般的なデプロイでは、多数のファイルをサーバーに転送し、設定ファイルを書き換えて再起動、という手順を踏みますが、zeroserve は「パックして置換するだけ」という手軽さです。
# 1. コンテンツとスクリプトを一つの tar にまとめる
zeroserve --pack ./my_site > site.tar
# 2. サーバーを起動する
zeroserve --addr 0.0.0.0:443 site.tar
# 3. 更新時は tar を置き換えてシグナルを送る
killall -SIGHUP zeroserve
このように、tar ファイルがドキュメントルートの役割を果たすため、不用意な設定ミスによって意図しないディレクトリが露出してしまう、といったセキュリティリスクも構造的に防いでいます。
既存サーバーとの比較
zeroserve と、従来の Web サーバーの特徴を比較してみます。
| 特徴 | nginx / Caddy | zeroserve |
|---|---|---|
| 設定形式 | 宣言的(Confファイル) | 手続き的(eBPFスクリプト) |
| デプロイ単位 | ディレクトリ、複数ファイル | 単一の tar ボール |
| I/O モデル | epoll など | io_uring (monoio) |
| 拡張性 | モジュール、Lua、外部プラグイン | 標準の eBPF プログラム |
| ホットリロード | 設定の再読み込み | アトミックな完全置換 |
まとめ:Webサーバーの新しい選択肢
zeroserve は、従来の Web サーバーが抱えていた「設定の複雑化」という課題に対し、eBPF と io_uring というモダンな技術を組み合わせて一つの回答を出しているように見えます。
もちろん、大規模なエコシステムを持つ nginx などと比べれば、まだ実験的な側面もあるかもしれません。しかし、シングルバイナリで動作し、設定とロジックを統合できるこのアプローチは、マイクロサービスの前段に置くゲートウェイや、エッジでの高速な配信において、非常に有力な選択肢になるのではないかと感じました。
「設定ファイルが肥大化して、どこで何が起きているか分からなくなる」という経験がある方にとって、zeroserve のような「プログラムこそが設定である」という割り切りは、一考の価値があるかもしれません。
参照記事
- zeroserve: a zero-config web server you can script with eBPF
- 7 Underused Rust Features Every Senior Developer Knows
- The One Python Trick That Made My Code 20x Faster
- I Changed One Line in postgresql.conf. Query Performance Jumped by 100×
- 7 uvicorn/gunicorn Settings That Actually Move the Needle
- I Made My App 10× Lighter and Faster Using Native Web APIs