KubernetesでのSensorの成立性の検証
- 状態: 設計・成立性の検証まで(実装未着手)
- 開始日: 2026年10月2日
- 最終更新: 2026年10月3日
目的
Kubernetes のノードで Sensor(実行時の情報を観測する部品)の観測が成り立つかを確かめ、Docker 向けの配置・権限・隔離のうち、引き継げる部分と変更が必要な部分を整理する。
実行時証拠による優先順位付けの開発で定めた Sensor を対象とする。Kubernetes対応の開発で実装したイメージの発見・スキャンに、ノード上で得る実行時の証拠をつなぐための検証である。
現時点では、起動処理と他の Pod の読み取りを実機で確認し、配置と権限境界を設計したところまでである。Kubernetes 向けの実装は、Docker 向けの Runtime 機能の運用検証が終わってから着手する。
方針
- KestreLynx のコードを変えずに確かめられる範囲を先に確認する
- Sensor のイメージと検証モードを使い、起動時の権限取得・隔離・他の Pod の読み取りを実機で確かめる
- 設定で成立する部分と、コンテナの特定などコードの変更が必要な部分を分ける
- Docker 向けの権限と役割分担を引き継ぐ
- 観測に必要な権限を Sensor に限定し、本体や中継用コンテナには持たせない
- Kubernetes では Sensor が各ノードで動き、KestreLynx の本体は別のノードで動くことがあるため、各ノードに中継用コンテナを置き、Sensor がノードに書いた証拠を本体へ渡す
- 観測の権限を持つ Sensor がネットワークに出ないよう、Sensor のネットワーク通信を一切禁止しているため、本体との通信は観測の権限を持たない中継用コンテナが担う
- 本体が中継用コンテナから証拠を取得する
- 読み取りのための権限と、書き込み・通信・解析を制限する仕組みを組み合わせる
- 観測に必要な権限を Sensor に限定し、本体や中継用コンテナには持たせない
- 確認した範囲を明示する
- 起動や読み取りの成功と、証拠を正しいコンテナへ対応付けて判定に使えることを区別する
- 環境ごとの結果を記録し、未検証の構成へ一般化しない
検証方法
環境
- 2026年10月3日 に単一ノードの K3s を、AppArmor のない WSL2 と、AppArmor が有効な Ubuntu の VPS で動かした
- AppArmor は、プログラムごとにファイルへのアクセスやプロセス間の操作などを制限する仕組みである
- AppArmor の動作は、同じ VPS 上の Docker とも比較した
- プロセスをグループ化する cgroup の階層は、WSL2 の cgroup v2・systemd ドライバで確認した
- リソース保証の区分である QoS が異なる Pod と、補助処理を担う native sidecar、Pod の実行環境を支える pause コンテナを調べた
起動処理と読み取り
- Sensor の検証モードで、権限の取得と隔離、eBPF によるカーネル内の観測処理の準備を確認した
- Sensor は非 root で動かし、ホストのプロセスを見渡せる PID 名前空間を共有した
- Linux の権限を細分化した capability、システムコールを制限する seccomp、AppArmor の条件を変えて比較した
- 追加の権限取得を防ぐ
no_new_privs、ファイルへのアクセス範囲を制限する Landlock、隔離の自己点検を確認した
- 他の Pod の読み取りは、root と非 root のコンテナを対象に確認した
- VPS では、対象 Pod が既定の AppArmor プロファイルを使う場合と、AppArmor の制限を外した Unconfined の場合を比較した
- 対象の識別情報を既存の検証モードが受け取れる Docker 向けの形式で渡したため、Kubernetes の自動発見や照合の検証には当たらない
- 対象 Pod への書き込み操作は行わず、Sensor 自身の隔離の自己点検とは分けて確認した
結果
権限の取得と seccomp
非 root の Sensor の権限取得は、次の条件で比較した。
| 条件 | 結果 |
|---|---|
| Pod に capability を指定するだけ | 観測権限を使えなかった |
| 起動前に追加の権限取得を禁止する | 実行ファイルに付けた権限も取得できなかった |
起動時の権限取得を許可し、その後に Sensor 自身が no_new_privs とメモリダンプなどの制限を設定する |
Docker 向けの仕組みが成立した |
ノード上の seccomp プロファイルを使う Localhost 設定では、次の結果になった。
| プロファイルの配置 | 結果 |
|---|---|
| Docker 向けのプロファイルをそのまま配置する | 起動でき、自己点検でも禁止した操作が拒否された |
| プロファイルを配置しない | 制限を外さず起動に失敗した |
- 起動前の準備を行う init コンテナでプロファイルを配置する方法も成立した
- init コンテナにはランタイム既定の制限を使い、Sensor にだけ配置後のプロファイルを指定することで、未配置のプロファイルへの依存を避けられた
- 成立した構成では、Landlock の適用、eBPF に必要なカーネルの型情報の読み取り、eBPF の読み込み・接続を確認した
- イベントを正しい Kubernetes コンテナへ対応付ける処理は未検証である
他の Pod の /proc の読み取り
- Sensor の権限で、検証対象の root・非 root の Pod から、
/procが公開するプロセス情報やファイルシステム内の一覧を読めた- 権限を取得できない条件では読み取りの一部が拒否され、確認した読み取りに Sensor の権限が働いていることを確かめた
- VPS では Sensor を AppArmor の Unconfined にすると、対象 Pod 側の AppArmor 設定を変えずに読み取れた
- パッケージデータベース、名前空間の情報、IPv6 の通信情報は個別には検査していないため、パッケージの使用判定まで成立したとは扱わない
cgroup 名前空間とコンテナの特定
- 検証した Pod は、cgroup 階層の見え方を分ける独立した cgroup 名前空間で動き、ホストの名前空間を必要とする現在の Sensor は通常の起動では終了した
- 他のプロセスの cgroup パスは読む側の位置に応じて変わるため、固定の方法で先頭部分を削るだけでは照合できない
- ホストの cgroup 階層を別の場所へ読み取り専用でマウントすると、階層全体を辿り、所属プロセスから Sensor 自身の cgroup も特定できた
- コンテナの特定には、この階層を基準に Pod・コンテナ・cgroup の識別情報と所属プロセスを照合する設計を採る
- native sidecar は同じ Pod 内で独立した cgroup を持つ一方、pause コンテナはパスの形だけでは通常のコンテナと区別できなかった
- 本体が Kubernetes API のコンテナ情報と照合し、pause コンテナを対象から外す必要がある
- 既存の検証モードは Docker 向けのパス形式だけを扱うため、読み取りが成功した対象でも cgroup の照合には失敗した
- ホスト階層へのアクセスは確認済みだが、KestreLynx による Kubernetes コンテナの照合は未実装・未検証である
AppArmor と起動処理の停止
Sensor の AppArmor 設定ごとの結果と扱いは、次のとおりである。
| Sensor の AppArmor 設定 | 結果 | 扱い |
|---|---|---|
| 既定プロファイル | AppArmor が有効な VPS の K3s で、自分自身へのシグナルが禁止され、起動処理が途中で止まった | Sensor の既定には使わない |
| Unconfined | 起動処理・隔離の自己点検・eBPF・対象 Pod の読み取りが成立し、AppArmor のないノードでも起動できた | Sensor だけに適用する既定値とする |
| 専用プロファイル | 起動と読み取りが成立し、自己点検で禁止した操作は拒否されたが、AppArmor のないノードでは起動できなかった | AppArmor が有効なノードだけのクラスタで選べる任意設定とする |
- 既定プロファイルでは、AppArmor の識別ラベルが重なって許可条件に一致しなくなり、全スレッドへの権限と
no_new_privsの設定が完了しなかった- 一部の権限だけを持って CPU を使い続け、検証モードの監視処理や通常の終了要求でも止まらず、Pod の強制削除が必要になった
- 同じ VPS の Docker ではラベルの重なりは起きず、ほかの環境での再現は未確認である
- 専用プロファイルは、自分自身へのシグナルと他のプロセスを読み取る操作を許す
- 専用プロファイル使用時に、カーネル監査ログへ拒否が残るかは未確認である
- 起動処理が完了せず回り続ける挙動は不具合として修正し、一定時間で明確なエラーを出して終了させる
- 終了は、今回機能しなかった監視処理や拒否されるシグナルだけに依存させない
決めたこと
以下は検証結果を受けた設計の判断であり、Kubernetes 向けの実装はこれからである。
配置と証拠の受け渡し
- Sensor と中継用コンテナは、対象ノードごとに配置する DaemonSet をそれぞれ用意する
- Sensor はホストの PID 名前空間を共有し、中継用コンテナにはホストのプロセスを見渡す設定や観測権限を与えない
- Sensor はノード上の証拠ディレクトリへ書き込み、中継用コンテナはそこを読み取り専用で参照する
- クラスタ内の本体が、TLS によるサーバー認証とベアラートークンを使って中継用コンテナから証拠を取得する
- 本体は受信内容を独立に検証してから利用する
cgroup の照合
- Kubernetes 向けのモードを明示的に選んだ場合にだけ、ホストの cgroup 名前空間を必要とする起動条件を外す
- ホストの cgroup 階層は、コンテナ自身の階層に重ねず、別の場所へ読み取り専用でマウントする
- 相対パスの先頭を固定の方法で削るのではなく、ホストの階層と所属プロセスを照合の基準にする
AppArmor と残る隔離
- Sensor は AppArmor の Unconfined を既定とし、専用プロファイルは AppArmor が有効なノードだけのクラスタ向けの任意設定とする
- 中継用コンテナと本体の AppArmor は既定のままとする
- この構成では、Docker の既定プロファイルに相当する AppArmor の防御層は Sensor にない
- 観測する部分には、Docker 向けの権限と隔離の制限を引き継ぐ
- 非 root・非 privileged で必要な権限だけを取得し、eBPF の準備にだけ必要な権限は準備後に手放す
- 権限取得後は全スレッドで追加の権限取得とメモリダンプなどを制限する
- seccomp で操作を制限し、Pod にネットワーク名前空間があっても Sensor の通信を禁止する
- ルートファイルシステムを読み取り専用にし、書き込み先を自身の証拠に限定する
- パッケージデータベースの解析は、観測権限を持たない子プロセスへ分ける
- Landlock と seccomp で、解析部分のファイル操作・通信・プログラム実行を制限する
- これらの隔離は書き込みや通信などを制限するものであり、権限を持つ観測部分が他の Pod の秘密情報を読めないことは保証しない
未検証・次の作業
- 初期の実装対象は Linux・cgroup v2・containerd(runc)とし、本体をクラスタ内に配置する
- これは実装する範囲であり、すべての構成で動作を確認したという意味ではない
- コンテナの照合を実装し、証拠が正しい対象へ結び付くことを確認する
- QoS の異なる Pod で通常コンテナと native sidecar を識別し、pause コンテナと Sensor 自身を除外する
- cgroup の管理方式や階層、プロセスの移動、識別子の再利用が変わっても、証拠を別のコンテナへ付けないことを確かめる
- パッケージデータベース・名前空間・IPv6 の情報を読み取り、使用・待ち受け・権限の証拠を対応付ける
- 起動処理が止まった場合の終了と、AppArmor の環境差を検証する
- 全スレッドへの権限と
no_new_privsの設定が完了しない場合の終了処理を実装する - ほかのディストリビューションやカーネル、対象 Pod の独自プロファイルで、ラベルの重なりや読み取り可否を確認する
- 専用プロファイルの監査ログ・配布・更新・再起動後の読み込みを確認する
- 全スレッドへの権限と
- 中継用コンテナと転送を実装し、複数ノードでの運用を検証する
- 中継用コンテナの隔離と、TLS・トークンによる取得、証拠の検証・保存を確認する
- 一部の Sensor や中継用コンテナが停止しても、ノードごとの証拠と鮮度を混同しないことを確かめる
- Pod や cgroup、短命コンテナ、イベントが増えたときの走査・転送の負荷と欠落を測る
- seccomp プロファイルと Sensor の版の対応、更新とロールバックを確認する
- 実装とこれらの検証は、Docker 向けの Runtime 機能の運用検証が完了してから進める
更新履歴
2026年10月3日
- 成立性の検証結果を記録
この記事は、KestreLynxの開発記録です。KestreLynxについて