Linux 名前空間は、Docker などのコンテナー テクノロジーの背後にある基盤となるテクノロジーです。これらは、コンテナ化されたプロセスが参照するリソースをシステムが制限できるようにする Linux カーネルの機能であり、どのプロセスも他のプロセスに干渉できないようにします。
ネームスペースとは何ですか?
Kubernetes などのデプロイメント ツールの場合と同様に、単一サーバー上で多くの異なるプロセスやアプリケーションを実行している場合、主にセキュリティを目的として、各プロセスを分離することが重要です。
あるコンテナが別のコンテナのリソースを制御できるようにすべきではありません。そのコンテナが侵害されると、システム全体が侵害される可能性があるからです。この攻撃方法は、CPU バグの メルトダウン の仕組みと似ています。プロセッサの異なるスレッドは相互に分離する必要があります。同様に、異なる仮想システム (コンテナー) で実行されているプロセスは、他のコンテナーから分離する必要があります。
名前空間は、カーネル レベルでこの分離を実現します。プロセスを別のルート ディレクトリに収容するアプリケーション chroot の動作と同様に、名前空間はシステムの他の側面を分離します。使用可能な名前空間は 7 つあります。
-
マウント
、または
mnt。非常によく似ています
、Mount 名前空間はファイル システムを仮想的に分割します。別のマウント名前空間で実行されているプロセスは、マウント ポイントの外部にあるファイルにアクセスできません。これはカーネル レベルで行われるため、ルート ディレクトリを変更するよりもはるかに安全です。chroot
。chroot -
プロセス
、または
。 Linux では、最初のプロセスは PID 1 の子として生成され、プロセス ツリーのルートを形成します。プロセス名前空間は PID ツリーのブランチを切り離し、そのブランチより上位へのアクセスを許可しません。子名前空間内のプロセスには実際には複数の PID があります。最初の PID はメイン システムで使用されるグローバル PID を表し、2 番目の PID は子プロセス ツリー内の PID を表し、1 から再開されます。pid -
プロセス間通信
、または
。この名前空間は、プロセスが相互に直接通信できるかどうかを制御します。ipc -
ネットワーク
、または
。この名前空間は、プロセスが認識できるネットワーク デバイスを管理します。ただし、これでは何も自動的に設定されるわけではありません。仮想ネットワーク デバイスを作成し、グローバル ネットワーク インターフェイスと子ネットワーク インターフェイス間の接続を管理する必要があります。 Docker などのコンテナ化ソフトウェアはすでにこれを理解しており、ネットワークを管理できます。net - ユーザー 。この名前空間により、プロセスは親システムへの実際の root アクセス権を持たずに、独自の名前空間内に「仮想ルート」を持つことができます。また、UID および GID 情報も分割されるため、子名前空間は独自のユーザー構成を持つことができます。
- UTS 。この名前空間はホスト名とドメインの情報を制御し、プロセスが別の名前のサーバー上で実行されていると認識できるようにします。
- Cgroup は 、名前空間によく似たもう 1 つのカーネル機能です。 Cgroups を使用すると、システムはプロセスのグループに対するリソース制限 (CPU、メモリ、ディスク容量、ネットワーク トラフィックなど) を定義できます。これはコンテナ化されたアプリにとって便利な機能ですが、名前空間のような「情報の分離」は行いません。 cgroup 名前空間 は別のもので、プロセスがどの cgroup を参照できるかを制御するだけであり、特定の cgroup に割り当てることはありません。
デフォルトでは、実行するプロセスはすべてグローバル名前空間を使用し、特に指定がない限り、システム上のほとんどのプロセスも同様に使用します。
名前空間の操作
lsns
コマンド (ls-namespaces) を使用すると、システムでアクティブになっている現在のネームスペースを表示できます。このコマンドは root として実行する必要があります。そうしないと、リストが不完全になる可能性があります。
上は、Ubuntu を新規インストールした場合の
lsns
出力です。各ネームスペースは、それを作成したプロセス ID、ユーザー、およびコマンドとともにリストされます。 7 つの名前空間は次から生成されました。
/sbin/init
PID 1 を持つ 7 つのグローバル名前空間です。他の名前空間は、システム デーモンの
mnt
名前空間と、Canonical の
Livepatch
サービスだけです。
コンテナーを使用している場合、このリストはさらに長くなります。このリストを JSON 形式で出力するには、
-J
このフラグは、スクリプト言語を使用するとはるかに簡単に使用できます。
現在の名前空間を変更するには、
nsenter
ユーティリティ。このコマンドを使用すると、通常はデバッグ目的で、別のプロセスの名前空間に「入る」ことができます。実際にはその名前空間で任意のコマンドを実行できますが、デフォルトではシェル (通常は
/bin/bash
) をロードしようとするだけです。
プロセス ID を指定してから、入力する各名前空間を指定します。
sudo nsenter -t PID --mount --net --pid //など。
たとえば、
kdevtmpfs
のマウント名前空間に入ろうとすると、その名前空間にロードされますが、
/bin/bash
が見つからないために失敗します。これは、見かけ上のルート ディレクトリが変更されているため、実際には機能したことを意味します。
子の
mnt
名前空間に
/bin/bash
が含まれている場合は、そこに入ってシェルをロードできます。これは手動で行うこともできますが、ディレクトリ ツリーを操作し、
mnt
名前空間全体でファイルをリンクできる
バインド マウント
を使用して行う必要があります。これは、2 つのプロセス
に同じファイルから異なるコンテンツを読み取らせる
など、興味深い使用例につながる可能性があります。
新しい名前空間を作成するには、既存の名前空間 (通常はグローバル) からフォークし、変更する名前空間を指定する必要があります。これは、マスターから「非共有」の新しい名前空間を使用してコマンドを実行する
unshare
コマンドを使用して行われます。
ホスト名の名前空間の共有を解除するには、次を使用します。
sudo unshare -u コマンド
コマンドを空白のままにすると、
unshare
デフォルトで bash を実行します。これにより、
lsns
の出力に表示される新しい名前空間が作成されます。
ここでは、バックグラウンドで bash を実行し続けるためにターミナル マルチプレクサ
screen
が使用されています。そうしないと、プロセスが閉じられると名前空間が消えてしまいます。
非常に低レベルのプログラミングを行っている場合を除き、おそらく自分で名前空間に触れる必要はありません。 Docker などのコンテナ化プログラムが詳細を管理します。プロセスの分離が必要なほとんどの場合、既存のツールを使用するだけで済みます。ただし、特に Docker コンテナーの低レベル構成を行っている場合や、手動でデバッグを行う必要がある場合には、コンテナー化のコンテキストで名前空間がどのように機能するかを理解することが重要です。





