LXCとLinuxシステムコンテナ

最終更新: 2026-08-23 10:41:42 +0800 +0800
原文は英語で書かれています。あなたはAI翻訳版を読んでいます。

LXCは、Linuxのコンテインメント機能を利用するためのユーザー空間インターフェースである。liblxcライブラリ、コマンドラインツール、およびディストリビューションテンプレートを組み合わせて、ホストのカーネルを共有する分離されたLinuxユーザー空間であるシステムコンテナを作成する。

LXCコンテナは、initシステムを起動し、複数のサービスを実行し、永続的なパッケージ状態を維持し、仮想ネットワークインターフェースを公開できる。したがって、その運用モデルはOCIアプリケーションコンテナよりも軽量なLinuxマシンに近い。ただし、ゲストカーネルを起動せず、ハードウェアもエミュレートしないため、LXCはあくまでコンテナランタイムである。

仮想化スタックにおける位置付け #

LXCは、単一の独立したサブシステムで分離を実装するのではなく、複数のカーネル機構を連携させる。

NamespacCiieonssniottlaai+tneesdcregrrrAvooiouctpefsssvH2ostLiclcCiinaioonsupfnnioxalefttlbiciaaKibygi+tellcunerixlresdntceareeitrrleaiBvosnoiodnctefssseccompCiionsniottlaai+tLneSesdMresrrCvoioctefss

各コンテナには、選択された一連の分離済みカーネルビューが割り当てられる。

機構LXCコンテナ内での機能
NamespacesプロセスID、マウント、ネットワーク、IPC、ホスト名、ユーザー、cgroupビュー、およびクロックを分離する。
cgroups v2CPU、メモリ、プロセス数、I/O、およびデバイスアクセスを計測し、制限する。
Capabilities従来のroot権限を、個別に削除可能な権限へ分割する。
Seccompコンテナプロセスが利用できるシステムコールをフィルタリングする。
AppArmorまたはSELinux共有カーネルを通して引き続き可視となるホストリソースへのアクセスを制約する。
ユーザー名前空間コンテナのrootを含むコンテナUIDおよびGIDを、非特権のホストIDへマッピングする。

Namespacesはプロセスから何が見えるかを決定し、cgroupsはプロセスが消費できるリソース量を決定する。名前空間による分離だけでは完全なセキュリティポリシーにならないため、Capabilities、seccomp、およびLinuxセキュリティモジュールによって独立した制約を追加する。

LXCのコンポーネントと周辺エコシステム #

関連する複数のプロジェクトは、それぞれ異なる役割を担う。

プロジェクト役割
LXCliblxc Cライブラリ、lxc-*ライフサイクルツール、設定形式、およびディストリビューションテンプレート。
LXCFSコンテナ固有のCPU情報やメモリ情報など、cgroupを認識した/procデータを提示するFUSEファイルシステム。
DistrobuilderYAML定義からルートファイルシステムとイメージを構築する。
IncusLXCをデフォルトのコンテナランタイムとして使用する、上位レベルのシステムコンテナおよび仮想マシンマネージャー。

Incusは、デーモンとREST API、管理対象イメージ、プロファイル、ストレージプール、ネットワーク、プロジェクト、クラスタリング、およびマイグレーションを追加する。一方、管理デーモンを介さず、ホスト上でコンテナを直接ローカル制御する必要がある場合には、LXC自体が引き続き有用である。

LXDとIncusをLXCの別名として扱ってはならない。LXDは、LXC上に構築されたマネージャーとして誕生した。その後、IncusはLXDからフォークされ、現在はLinux Containersプロジェクトで保守されている。

コンテナのライフサイクル #

downloadテンプレートは、Linux Containersイメージサーバーからディストリビューションのルートファイルシステムを取得する。以下のコマンドは、ホストのディストリビューションにLXCがインストールされ、実行ユーザーに必要なUID/GID範囲とネットワークが設定されていることを前提とする。

sh
lxc-create --name web01 --template download -- \
  --dist debian --release trixie --arch amd64

lxc-start --name web01 --daemon
lxc-info --name web01
lxc-attach --name web01

lxc-stop --name web01
lxc-destroy --name web01

システム全体で使用されるデフォルトのコンテナ格納場所は/var/lib/lxc/<name>/である。ルートファイルシステムが別のストレージバックエンドを使用しない限り、コンテナディレクトリには設定とルートファイルシステムが格納される。主なライフサイクルツールは次のとおりである。

  • コンテナとその状態を一覧表示するlxc-ls --fancy。
  • 設定済みのコンソールへ接続するlxc-console。
  • cgroup freezerを介して実行を一時停止および再開するlxc-freezeとlxc-unfreeze。 cgroup freezer。
  • lxc-copy バッキングストアがサポートしている場合にコンテナをコピーまたはスナップショットするための 要求された操作をサポートすること、および
  • 状態変化を監視するlxc-monitorとlxc-wait。

LXCの設定ではkey = valueエントリを使用する。簡略化した設定では、識別情報、ストレージ、ネットワーク、UIDマッピング、およびリソース制御を組み合わせられる。

ini
lxc.uts.name = web01
lxc.rootfs.path = dir:/var/lib/lxc/web01/rootfs

lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up

lxc.idmap = u 0 100000 65536
lxc.idmap = g 0 100000 65536

lxc.cgroup2.memory.max = 2147483648
lxc.cgroup2.pids.max = 1024
lxc.cgroup2.cpu.max = 200000 100000

設定はホストに依存する。UID/GID範囲はsubordinate IDの割り当てと一致し、ネットワークデバイスが存在し、cgroup値が実行中のカーネルでサポートされている必要がある。LXCは、多くのcgroup設定をランタイム固有のリソースモデルへ正規化せず、カーネルへ渡す。

特権コンテナと非特権コンテナ #

UIDマッピングによって、コンテナのrootがホストのrootでもあるかどうかが決まる。

  • 特権コンテナでは、コンテナ内のUID 0は、 ホストカーネルから見てもUID 0である。Namespaces、Capabilityの削除、seccomp、および強制アクセス制御によってアクセスを制限できるが、アップストリームのLXCは、特権コンテナをrootに対して安全であるとは明示的に見なしていない。
  • 非特権コンテナでは、UID 0は、たとえば 100000. したがって、ユーザー名前空間により、コンテナのrootが 通常のホストリソースを所有することを防止できる。

たとえば、マッピングu 0 100000 65536は、コンテナUID 0~65535をホストUID 100000~165535へマッピングする。newuidmapとnewgidmapは、/etc/subuidと/etc/subgidで許可されたマッピングを設定する。非特権ネットワークでは、用途を限定したlxc-user-nicヘルパーを使用して、許可された仮想インターフェースを作成することもできる。

ホストレベルの識別情報やデバイスアクセスを必要としないワークロードでは、非特権コンテナをデフォルトにすべきである。ただし、ユーザー名前空間によって共有カーネルのリスクが解消されるわけではない。許可されたシステムコールを通じて到達可能なカーネル脆弱性は、依然としてコンテナ境界を越える可能性がある。

ストレージ #

ルートファイルシステムには、ディレクトリ、イメージファイル、ブロックデバイス、またはサポート対象のコピーオンライトバックエンドを使用できる。lxc-createは、ビルド構成とホスト構成に応じて、ディレクトリ、Btrfs、LVM、ループファイル、ZFS、Ceph RBDなどのバッキングストアをサポートする。

バックエンドの選択によって運用特性が変わる。

バックエンド運用特性
ディレクトリ設定が最小限で、ファイルへ直接アクセスできるが、コンテナをコピーするにはそのファイルをコピーする必要がある。
BtrfsまたはZFSホストファイルシステムが適切に設定されている場合、ネイティブスナップショットと効率的なクローンを利用できる。
LVM thin poolシンプロビジョニングとスナップショットをサポートするブロックデバイス分離。
ループファイル専用の論理ボリュームを必要としないファイルシステムイメージ。ただし、ストレージ層が1つ増える。
Ceph RBDすでにCephと統合されているホスト向けの、ネットワークを介したブロックストレージ。
OverlayFS1つ以上の下位レイヤー上に配置される書き込み可能な上位レイヤー。一時的なルートやクローンしたルートに適している。

idmapped mountを使用すると、すべてのinodeの所有権を再帰的に変更せずに、コンテナのUID/GIDマッピングを通してファイルシステムの所有権を提示できる。採用前に、カーネル、ファイルシステム、およびLXCのすべてが対応していることを確認する必要がある。

ネットワーク #

LXCは複数の種類のネットワークインターフェースを作成できる。

  • vethはEthernetペアを作成し、一般にホスト側の端点を lxcbr0などのブリッジへ接続する。
  • vlanは、ホストの親インターフェース上にVLANインターフェースを作成する。
  • macvlanとipvlanは、異なる レイヤー2またはレイヤー3のセマンティクスで、コンテナを親インターフェースへ接続する。
  • physは、物理インターフェースをコンテナのネットワーク名前空間へ移動する。
  • emptyは、ループバックのみを含む分離されたネットワーク名前空間を作成する。
  • noneは、ホストのネットワーク名前空間を維持する。

ブリッジが提供するのは接続性であり、テナントのセキュリティではない。同じレイヤー2セグメントへ接続されたコンテナは、アドレススプーフィングを試みたり、悪意のある制御トラフィックを送信したりできる。したがって、信頼できないテナントには、ブリッジの分離、ホスト側でのフィルタリング、および明示的なIPv6 Router Advertisement制御が必要である。

リソースとデバイスの制御 #

LXC 7.0はcgroups v2のみをサポートする。運用担当者は、たとえばlxc.cgroup2.*を通じてコントローラー値を書き込める。

  • メモリ制限とメモリプレッシャーを制御するmemory.maxとmemory.high。
  • CPU帯域幅と配置を制御するcpu.maxとcpuset.cpus。
  • fork bombを封じ込めるpids.max。
  • サポート対象のブロックデバイスに対するI/Oコントローラー設定。

プロセスがコンテナ内で実行されているというだけでは、リソース上限は設定されない。明示的な制限がなければ、コンテナはホストで利用可能なメモリ、CPU、プロセスID、I/O、およびネットワーク容量を奪い合う可能性がある。

デバイスアクセスにも注意が必要である。cgroups v2では、デバイスフィルタリングはcgroups v1のデバイス制御ファイルではなく、cgroupにアタッチされたeBPFプログラムによって適用される。GPU、ディスク、その他のデバイスをパススルーすると、コンテナプロセスがホストドライバーと直接やり取りするため、攻撃対象領域が拡大する。

セキュリティモデル #

LXCの分離は、単一の境界ではなく多層防御に基づく。本番環境の設定では、次の対策を講じるべきである。

  1. 重複しないUID/GID範囲を割り当てた非特権コンテナを使用する。
  2. LXCはデフォルトで完全な制限を 適用しないため、メモリ、CPU、プロセス数、およびI/Oの制御を適用する。
  3. ワークロードが必要としないCapabilityを削除する。
  4. 適切なseccompポリシーを読み込み、ホストのディストリビューションがサポートする場合はAppArmorまたはSELinuxによる 制約を維持する。
  5. バインドマウント、デバイスパススルー、共有名前空間、および書き込み可能な ホストパスを最小限に抑える。
  6. 信頼できないネットワークセグメントを分離し、ホスト向けトラフィックをフィルタリングする。
  7. すべてのコンテナがホストカーネルを共有するため、ホストカーネルとLXCパッケージを 最新の状態に保つ。

相互に信頼しないコンテナ間では、subordinate IDのマッピングが重複しないようにすべきである。重複すると、同じホストUIDに関連付けられたカーネルのアカウンティングと制限によって、コンテナ間で干渉が発生する可能性がある。

LXC内で別のコンテナランタイムをネストするには、追加の権限、マウント動作、cgroup委譲、またはセキュリティポリシーの例外が必要になる。LXCコンテナ内でDockerを実行すると、ライフサイクルと設定状態を分離できるが、最終的に両方の層が同じホストカーネルを使用するため、VM相当のセキュリティ境界は形成されない。

LXC、OCIコンテナ、および仮想マシン #

LXC、OCIランタイム、および仮想マシンは、異なるパッケージングと分離の問題を解決する。

特性LXCシステムコンテナOCIアプリケーションコンテナ仮想マシン
典型的な単位initと複数のサービスを含むLinuxユーザー空間アプリケーションプロセスと依存関係完全なオペレーティングシステム
カーネルホストと共有ホストと共有独立したゲストカーネル
イメージモデルディストリビューションのrootfsまたはカスタムシステムイメージコンテンツアドレス方式の階層化OCIイメージ仮想ディスクとマシンイメージ
状態モデル一般に永続的かつ可変一般に再構築して置換一般に永続的
管理lxc-*ツールによる直接管理、またはIncusなどのマネージャーDocker、containerd、CRI-O、Kubernetes、および関連ツールハイパーバイザーとVM管理ツール
OSの制約ホストカーネルと互換性のあるLinuxユーザー空間ホストカーネルと互換性のあるLinuxユーザー空間仮想ハードウェアがサポートするゲストOS
分離境界Namespaces、ユーザーマッピング、cgroups、およびセキュリティポリシーNamespaces、ユーザーマッピング、cgroups、およびセキュリティポリシーハードウェア仮想化とハイパーバイザー

ワークロードをLinuxマシンとして運用する場合、すなわちinitシステム、連携して動作する複数のデーモン、インプレースのパッケージ管理、またはOSレベルの統合テスト環境が必要な場合は、LXCを選択する。

デプロイ単位がアプリケーションイメージであり、配布システムがレジストリ、階層化ビルド、イミュータブルな置換、またはKubernetesに依存する場合は、OCIランタイムを選択する。

ワークロードに別のカーネル、Linux以外のゲスト、カーネルモジュールの制御、または敵対的なテナントに対するより強固な境界が必要な場合は、仮想マシンを選択する。パフォーマンスはカテゴリだけから推測せず、実際のワークロードで測定する必要がある。

プロジェクトの状況 #

2026年8月時点で、LXC 7.0は現行の長期サポートシリーズであり、2031年6月までのサポートが予定されている。LXC 6.0は2029年6月まで、LXC 5.0は2027年6月まで引き続きサポートされる。

LXC 7.0では、cgroups v1のサポート、およびpidfdsまたは新しいmount APIを備えていないカーネルのサポートが削除された。したがって、以前のLXCリリースからアップグレードする環境では、ホストカーネルの機能を検証し、残存するcgroups v1設定を移行する必要がある。

バージョン番号とサポート期限は、アップストリームのリリースに関する情報である。Linuxディストリビューションでは、異なるパッケージバージョン、バックポート、および保守ポリシーが適用される場合がある。

参考資料 #

コメント

GitHub で閲覧・コメントする(投稿にはログインが必要です)