システムをコンテナ化せずに複数テナントのワークロードを同一ホスト上で動かしたい、という要件は今も現場に少なくありません。レガシーバイナリが OCI イメージに乗らない、ランタイム依存が複雑すぎる、あるいは単純にオーバーヘッドを抑えたいといった理由から、コンテナエンジンを介さず Linux namespace だけでテナント境界を設けるアプローチが選ばれることがあります。本記事では、namespace をどの範囲まで信頼し、どこに逸脱リスクを見るか、そして 2026 年時点の現行カーネルで変わっている点を含めて、設計から運用判断まで一本通しで整理します。
なぜ「コンテナなし namespace」が選ばれるのか
Docker や Podman のようなコンテナランタイムは、内部では namespace と cgroup を組み合わせて分離を実現しています。コンテナエンジン自体がその複雑さを隠蔽しているため使い勝手は高い反面、導入するとデーモン・OCI ランタイム・ネットワークプラグインといったコンポーネントが積み上がります。「分離機能だけ欲しい、ランタイム一式は要らない」と判断した現場では、unshare(1) や nsenter(1) を直接操作するアプローチが採用されます。
典型的なユースケースとしては、同一ホスト上でサービスプロバイダが複数顧客の処理を動かす構成、あるいは開発・ステージング・本番の各テナントを同一物理機に載せて管理コストを圧縮したいケースが挙げられます。namespace はカーネル機能そのものなので、カーネルさえ対応していれば追加パッケージゼロで利用できます。
namespace が提供する分離の範囲を把握する
namespace を設計に組み込む前に、どの資源が分離されてどの資源が分離されないかを正確に把握しておく必要があります。過信すると予期しない情報漏洩や資源枯渇を招きます。
主要 8 種類の namespace と分離対象
- pid namespace:PID 空間を分離します。テナントのプロセスからはホストの PID が見えなくなり、自身の空間内で PID 1 を持てます。
- net namespace:ネットワークインタフェース・ルーティングテーブル・iptables ルールを分離します。テナントごとに独立したネットワークスタックを持てる半面、veth ペアや bridge の設定が別途必要です。
- mnt namespace:マウントポイントを分離します。ホストのファイルシステムツリーとは別のビューをテナントに提供できます。
- uts namespace:ホスト名・ドメイン名を分離します。テナントごとに異なる hostname を名乗れます。
- ipc namespace:System V IPC オブジェクトと POSIX メッセージキューを分離します。
- user namespace:UID/GID マッピングを分離します。テナント内で root に見えるプロセスを、ホスト上では非特権ユーザにマッピングできます。
- cgroup namespace:cgroup ファイルシステムのビューを分離します。テナントが自身の cgroup ルートより上位を参照できなくなります。
- time namespace:CLOCK_MONOTONIC および CLOCK_BOOTTIME のオフセットを分離します。Linux 5.6 で導入され、2026 年の主要ディストリビューションでは標準利用可能です。
重要な注意点として、namespace はアクセス制御の機能ではなく、あくまで「見え方」を分離する機能です。たとえば mnt namespace を設定していても、テナントがカーネルの脆弱性を突けばホストファイルシステムにアクセスできる可能性があります。本番環境でマルチテナント分離に namespace を使う場合は、seccomp・LSM(AppArmor / SELinux)との組み合わせが前提になります。
unshare と nsenter で分離環境を構成する手順
以下は、pid・net・mnt・uts・ipc の各 namespace を一括で分離した環境でシェルを起動する基本操作です。
# テナント A 用の分離シェルを起動する
sudo unshare --pid --net --mount --uts --ipc --fork --mount-proc /bin/bash
--fork は pid namespace の作成に必要なオプションです。--mount-proc は新しい pid namespace に合わせて /proc を再マウントします。起動したシェルは独立した PID 空間を持ち、ホストのプロセスツリーからは隔離されます。
起動した環境の namespace ID は /proc/<PID>/ns/ ディレクトリのシンボリックリンクで確認できます。
# ホスト側でテナントプロセスの namespace 一覧を確認
lsns -p <TENANT_PID>
# namespace ファイルを直接確認(inode が namespace ID に対応)
ls -la /proc/<TENANT_PID>/ns/
テナント環境にホスト側から入り込む場合(運用上の調査・デバッグ)は nsenter を使います。
# テナントの全 namespace に入る
sudo nsenter --pid --net --mount --uts --ipc --target <TENANT_PID> /bin/bash
常駐プロセスとして管理する場合は、systemd の Unit ファイルで PrivatePID=yes・PrivateNetwork=yes・PrivateMounts=yes 等を指定するほうが宣言的で安全です。systemd はこれらのオプションを内部で namespace として実装しており、起動・停止・依存関係の管理がユニット単位で完結します。手動で unshare するより、まず systemd 経由で実現できないかを検討するのが現行環境ではスタンダードです。
逸脱を検知する:audit と eBPF によるモニタリング
namespace を設定してもプロセスが意図的・偶発的に境界を越えようとする行動は起こりえます。特に user namespace を介した権限昇格を狙った逸脱は、設計上の穴になりやすいポイントです。検知の主な手段は二つあります。
auditd による clone / unshare システムコール監視
namespace の作成は clone(2) または unshare(2) システムコールで行われます。auditd にルールを追加しておくと、想定外の namespace 作成をログに残せます。
# /etc/audit/rules.d/namespace.rules に追加
-a always,exit -F arch=b64 -S unshare -k namespace_unshare
-a always,exit -F arch=b64 -S clone -F a0&0x10000000 -k namespace_clone
a0&0x10000000 のフラグは CLONE_NEWUSER(user namespace)に対応しています。user namespace の作成は権限昇格の踏み台になりやすいため、特に重点的に記録します。ルール適用後は augenrules --load で反映してください。
eBPF トレーシングによるリアルタイム検知
2026 年時点では bpftrace や Falco(eBPF バックエンド)が実用段階にあり、カーネルイベントをリアルタイムにフィルタリングできます。Falco のデフォルトルールセットには namespace 脱出に関するパターンが含まれており、コンテナなし環境でも有効に機能します。
lsns コマンドを定期実行して namespace の一覧を収集し、想定外の namespace が生成されていないかを確認する運用も有効です。cron や CI/CD パイプラインから実行して差分を比較するシンプルなアプローチでも、多くの異常を早期に検出できます。util-linux 2.40 以降の lsns は --json オプションを持つため、スクリプトからの処理が容易です。
切り戻し手順と運用上の落とし穴
namespace の「切り戻し」は比較的シンプルです。namespace はそれを参照するプロセスがすべて終了した時点で自動的に破棄されます。unshare で起動したシェルを終了するか、kill でプロセスを停止すれば namespace は解放されます。systemd Unit であれば systemctl stop で同様の結果が得られ、クリーンアップも自動です。
ただし bind mount で namespace を固定化(/var/run/netns/ などに名前付けする方法)している場合は、プロセスが終了しても namespace が残り続けます。これは意図して行うこともありますが、管理し忘れると「プロセスがないのに namespace だけが残っている」という状態になります。定期的に lsns で孤立した namespace がないかを確認する運用ルールを設けておくことが推奨されます。
net namespace を手動で作成して veth ペアを設定した場合、namespace を削除するだけでは veth の片方がホスト側に残ることがあります。ネットワーク設定を手動管理している場合は、削除後の掃除を手順書に明記しておいてください。systemd の PrivateNetwork=yes 経由で作成した場合は Unit 停止時に自動クリーンアップされるため、この問題は発生しません。
もう一つの落とし穴は、mnt namespace で /proc を再マウントしている環境での chroot との組み合わせです。chroot 環境から namespace を新たに作成する操作は、カーネルバージョンによって挙動が異なるケースがあるため、テスト環境での動作確認を先行させることが求められます。
2026 年の現行カーネル・systemd で変わっている点
2026 年現在、主要な Linux ディストリビューション(Ubuntu 24.04 LTS / RHEL 9 系 / Debian 12+)のカーネルは 6.x 系が標準です。namespace に関する主な変化を整理します。
time namespace の実用化:Linux 5.6 で導入された time namespace は、カーネル 6.x 系では安定稼働しています。テナントごとに異なるモノトニック時計オフセットを持たせる用途(バックアップやレプリケーションのタイムスタンプ管理)での活用が進んでいます。2020 年以前のドキュメントには time namespace の記述がないため、古いリファレンスを参照する際は注意が必要です。
user namespace のセキュリティ強化:カーネル 6.x では kernel.unprivileged_userns_clone の扱いが従来より厳格化されています。Ubuntu 24.04 以降はデフォルトで非特権ユーザによる user namespace 作成に制限をかける設定になっており、従来の手順がそのまま通らないケースが出ています。AppArmor プロファイルによる制御と組み合わさっているため、/proc/sys/kernel/apparmor_restrict_unprivileged_userns の値を確認してから設計を進めるのが安全です。
systemd 255 以降の namespace 委譲改善:systemd 255 では cgroup v2 と namespace の統合がさらに進み、ユーザーセッションへの cgroup namespace 委譲が改善されています。systemd-run で一時的なスコープを作成しつつ namespace を組み合わせる手法が、より扱いやすくなっています。
コンテナなしの namespace 設計は、仕組みをそのまま扱う分だけ「隠蔽されない」という利点があります。一方でランタイムが自動化している設定(veth の管理・cgroup 制限・seccomp プロファイルの適用など)をすべて手動またはスクリプトで担う必要があるため、運用のオーバーヘッドはコンテナ利用時より高くなります。どちらを選ぶかは、既存アーキテクチャとの親和性・運用チームのカーネル理解度・セキュリティ要件の 3 軸で判断するのが現実的です。
「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。
ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。
>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)
※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。
PR・広告
[試して理解]Linuxのしくみ 増補改訂版(Amazon)
プロセス・権限・ファイルシステムなどLinux内部を図解で理解できる一冊。運用判断の勘所に。
※ Amazonのアソシエイトとして、当サイトは適格販売により収入を得ています。
