🚨

【おうちk8s】コード修正ゼロで可視化する。BeylaとGrafana Stackで組むモダン監視基盤

に公開
2026/01/01

はじめに

最近、おうちk8sの監視周りを整備しているのですが、アプリケーションコードに手を加えずにトレース監視を行いたいなと思い、eBPFベースの自動計装ツールであるBeylaを導入してみました。

もともとPixieなどの自動計装ツールに興味があったのですが、分析基盤として独立しているPixieよりも、普段使い慣れているGrafanaエコシステムに統合できるBeylaの方が、自分のおうちk8s環境には馴染むだろうという判断です。

実際に組んでみると、アプリケーション側のコードを一切汚すことなく、Podをデプロイするだけで勝手にトレースが取れるようになり、かなり体験が良かったです。

この記事では、BeylaとGrafana Stackを組み合わせた構成と、構築してみた感想をまとめます。

なぜ今、OpenTelemetryなのか

OpenTelemetry (OTel) は、アプリケーションの観測データ(トレース、メトリクス、ログ)を収集、処理、エクスポートするためのオープンソースのフレームワークです。

2025年だけでも2冊の本がオライリーから出版されており、その注目度の高さが伺えます。

自分もいつか読んでみようかと思っていたのですが、座学より実際に構築した方が楽しいだろうという思いから、今回OpenTelemetryを用いたモダンな監視基盤を構築してみることにしました。

https://www.oreilly.co.jp/books/9784814401024/
https://www.oreilly.co.jp/books/9784814401031/

OpenTelemetryの概要については以下が参考になります。

https://zenn.dev/yuta28/articles/what-is-opentelemetry
https://zenn.dev/ryoyoshii/books/opentelemetry-firststep
https://speakerdeck.com/oracle4engineer/shi-jian-opentelemetry

環境

  • カーネルバージョン: 6.11.0-29-generic
  • OSバージョン: Ubuntu 24.10 (Oracular Oriole)

ざっくり構成図

やりたかったことはシンプルで、以下の4点を1つのダッシュボードで見ることです。

  • トレース: Beyla (eBPFで自動収集)
  • 保存: Tempo
  • メトリクス: Prometheus (Node Exporter / Kube State Metrics)
  • ログ: Loki + Promtail

構成は以下のようになっています。

Beylaがアプリケーションとカーネルのやり取りをeBPFでフックしてくれるため、サイドカーを大量に注入したり、アプリ言語ごとのSDKを導入したりする必要がないのが最大のメリットです。

実際に構築したもの(ゴール)

最終的に出来上がったGrafanaダッシュボードがこちらです。

上から順に「トレース」「ログ」「メトリクス」を並べています。
特に一番上のトレースビューが、Beylaを入れただけで自動生成されたのが感動的でした。
HTTPリクエストのパスやステータスコードが勝手に可視化されるので、デバッグがかなり捗りそうです。
トレースをクリックすると以下のように詳細が見られます。
アプリケーションに手を加えることなくここまで詳細なログが見られるというのはインフラ好きとしてとてもワクワクします!

※ 使用したDashboardのJSONはGitHubに置いてあるので、興味がある方は使ってみてください。

https://github.com/AobaIwaki123/k8s-cluster/pull/29/changes

技術スタックについて

今回は「Grafana Stackで統一する」ことをテーマに選定しました。

  • Beyla: 今回の主役。eBPFを使ってカーネルレベルで計測を行います。おうちk8sで動かしている自作アプリは全てカバーできました。
  • Tempo & Loki & Prometheus: 定番のセットです。これらを用いて OpenTelemetry Collector からのデータを受け取り、保存・可視化します。

Beylaの設定例

設定は非常にシンプルです。
DaemonSetとして全ノードに展開し、環境変数 BEYLA_OPEN_PORT に監視したいアプリケーションが使用しているポート番号を羅列するだけです。

# observability/beyla/manifests/beyla-resources.yaml (抜粋)
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: beyla
  namespace: observability
spec:
  # ... (省略) ...
  template:
    spec:
      serviceAccountName: beyla
      hostPID: true # プロセスを見に行くために必要
      containers:
      - name: beyla
        image: grafana/beyla:latest
        securityContext:
          privileged: true # eBPFプログラムをロードするために必要
        env:
        # 監視対象のポートを羅列するだけ(HTTP, Postgres, Redisなど)
        - name: BEYLA_OPEN_PORT
          value: "80,443,8080,3000,5432,6379,9090"
        # 収集したデータをどこに送るか(OTel Collector)
        - name: OTEL_EXPORTER_OTLP_ENDPOINT
          value: "http://otel-collector-collector.observability.svc.cluster.local:4318"
        # Kubernetesのメタデータ(Pod名など)を付与する
        - name: BEYLA_KUBE_METADATA_ENABLE
          value: "true"
        # ... (その他の設定)

私の環境ではWebアプリだけでなく、PostgreSQL (5432) や Redis (6379) も監視対象に入れていますが、ポート番号を書くだけで自動的にプロトコルを判別してトレースを取ってくれるのが非常に強力です。

ただし、eBPFを使用する特性上、privileged: true や hostPID: true といった特権権限が必要になる点には注意が必要です。

なぜ強い権限(privileged, hostPID)が必要なのか?

BeylaはeBPFを用いてカーネルレベルで動作するため、通常のアプリケーションよりも広い権限を必要とします。セキュリティリスクを理解した上で導入するために、それぞれの設定の意味を補足します。

1. DaemonSetである理由

Beylaはサイドカー(Podごとにコンテナを同居させる方式)ではなく、DaemonSet(各ノードに1つずつPodを配置する方式)としてデプロイします。
eBPFはLinuxカーネル上で動作するため、ノードごとに1つのBeylaがいれば、そのノード上で動く全てのPodの通信をカーネル経由で監視できます。これにより、サイドカー方式に比べてリソース効率が良く、管理も楽になります。

2. privileged: true が必要な理由とリスク

  • 理由: eBPFプログラムをカーネルにロードしたり、カーネル内の関数をフック(介入)したりするためには、非常に高い権限(主に CAP_SYS_ADMIN や CAP_BPF など)が必要です。Kubernetesやコンテナランタイムの仕様上、これらを確実に動作させるために privileged: true (特権モード)を付与するのが一般的です。
  • リスク: 特権モードのコンテナは、実質的にホストOSのrootユーザーと同等の権限を持ちます。万が一Beylaのコンテナが乗っ取られた場合、ホストOS全体が攻撃者に掌握される危険性があります。そのため、商用環境などで利用する際は、可能であれば細かいCapability設定(CAP_BPFなどのみ許可する)での最小権限運用を検討するのが望ましいです。

3. hostPID: true が必要な理由

  • 理由: 通常、コンテナはPID(プロセスID)名前空間が隔離されており、自分のコンテナ内のプロセスしか見えません。しかしBeylaは、ノード上で動いている他のアプリケーションプロセス(の通信)を特定・監視する必要があります。hostPID: true を設定することで、ホスト側のプロセスID空間を共有し、ノード上の全プロセスを「見る」ことができるようになります。
  • リスク: 監視対象外のプロセスも含め、システム上の全てのプロセス情報が見えてしまうため、情報漏洩のリスクなどが高まります。

トラブルシューティング

特定のメトリクスがGrafana上でno dataになる

研究室でPrometheus × Grafanaを運用した際にもいくつかのメトリクスがno dataとなってしまったことがありました。
原因は様々あるのですが、今回の原因はOpentelemetry CollectorがメトリクスをExportする際にotelcol_というprefixを付与していたことでした。
メトリクスがno dataとなってしまった場合は、prefixやsuffixに何かついていないかという視点で調査すると良いかもしれません。

Beylaがなぜか落ちる

設定は間違えていないのにBeylaのpodが再作成を繰り返すという現象に遭遇しました。
最初は何が原因か全くわからなかったのですが、調査の結果デバッグのために追加したBEYLA_TRACE_PRINTER=textが標準出力を大量に消費してしまい、OOMキラーに殺されていたことがわかりました。
今回の場合のようにOOMキラーが起こると謎の挙動でアプリケーションが落ちてしまうため、メモリは十分に確保しておくことをおすすめします。
以下は私の環境で動作しているBeylaのリソース設定例です。

https://github.com/AobaIwaki123/k8s-cluster/blob/add-otel/observability/beyla/manifests/beyla-resources.yaml#L87-L93

eBPFを使ってみた感想

eBPF (extended Berkeley Packet Filter) [1] [2] 自体はLinuxカーネルの中でサンドボックス化されたプログラムを動かす技術ですが、ユーザーとしては「特権モードでDaemonSetを動かすだけで、魔法のように中身が見える技術」という感覚でした。

従来ならOpenTelemetryのSDKをimportして、初期化コードを書いて…とやっていた手間がゼロになるのは大きいです。
ただ、Kernelのバージョン要件(基本的には5.8以上推奨など)があるため、古いラズパイOSなどを使っている場合は注意が必要かもしれません。
私の環境ではKernel 6.x系を使用していたため、特にトラブルなく動作しました。

おわりに

Beylaは、一度動いてしまえばアプリ側の改修なしでリッチな可視化ができるので、個人開発や小規模なクラスタ運用には非常に相性が良いと感じました。

今回は導入編でしたが、今後はこれを使って実際のアプリのボトルネック特定などができるか検証してみたいと思います。

また、OpenTelemetry自体の技術的な深掘りが足りていないと感じているため、今後はOpentelemetry自体の勉強もやってみたいです。

自動計装、一度味わうと戻れない便利さがあるので、おうちk8s運用中の方はぜひ試してみてください。

脚注
  1. LinuxカーネルのコアであるeBPFを実装したSysdigとFalco ↩︎

  2. eBPFとは? - eBPF ドキュメント ↩︎

Discussion