GNU/Linux >> Linux の 問題 >  >> Linux

手作業でコンテナを構築する:PID名前空間

名前空間シリーズの続きとして、この記事では PIDについて説明します。 名前空間。すべての名前空間の一般的な概要が必要な場合は、最初の記事を確認してください。以前、新しい mntを作成しました 名前空間。興味深いことに、あなたが発見したように、新しい mntを作成した後でも 名前空間では、元のホストのプロセスID(PID)に引き続きアクセスできます。 / procをマウントしようとしたとき 名前空間、かなり複雑な許可が拒否されました 以下に示すように、エラー:

root@new-mnt$ mount -t proc proc /proc
mount: permission denied (are you root?)

root@new-mnt$ whoami
root

新しいマウント名前空間であらゆる種類のマウントを作成することはできますが、 / procを操作したり変更したりすることはできませんでした。 。この記事では、 PIDについて説明します。 名前空間と、それを使用する方法を mntとともに示します 名前空間、駆け出しのコンテナをさらに保護します。

[読者も気に入っています:LinuxPID名前空間がコンテナとどのように連携するか]

プロセスIDとは何ですか?

PIDに直接ジャンプする前に 名前空間については、この名前空間が重要である理由について少し背景を説明することをお勧めします。

ほとんどのUnixライクなオペレーティングシステムでプロセスが作成されると、プロセスIDと呼ばれる特定の数値識別子が与えられます。 (PID)。このPIDは、人間が読み取れる同じ名前を共有する2つのプロセスがある場合でも、プロセスを一意に識別するのに役立ちます。たとえば、システム上でアクティブな複数のsshセッションがあり、特定の接続を閉じる必要がある場合、PIDは、管理者が正しいセッションが閉じられていることを確認する方法を提供します。

これらのプロセスはすべて、procfsと呼ばれる特別なファイルシステムで追跡されます。 。このファイルシステムは技術的にはどこにでもマウントできますが、ほとんどのツール(および規則)はprocfsを想定しています。 /procの下にマウントされます 。 /procのリストを作成する場合 、システムで現在実行されているすべてのプロセスのフォルダが表示されます。このフォルダ内には、プロセスのさまざまな側面を追跡するために使用されるあらゆる種類の特別なファイルがあります。この記事の目的上、これらのファイルは重要ではありません。 /procを知っていれば十分です。 ほとんどのUnixライクなシステムは、実行中のシステム上のプロセスに関する情報を格納する場所です。

PID名前空間

PIDの主な理由の1つ 名前空間は、プロセスの分離を可能にするためのものです。より具体的には、manページにあるように:

PID名前空間は、プロセスID番号スペースを分離します。つまり、異なるPID名前空間のプロセスは同じPIDを持つことができます。

これは、プロセスが他のプロセスと競合するPIDを持たないことが保証されることを意味するため重要です。もちろん、単一のシステムを検討する場合、システムはプロセスID番号を継続的にインクリメントし、同じ番号を2回割り当てることはないため、PIDが競合する可能性はありません。複数のマシンにまたがるコンテナを扱う場合、この問題はより顕著になります。マニュアルページで説明されているように:

PID名前空間を使用すると、コンテナーは、コンテナー内の一連のプロセスを一時停止/再開したり、コンテナー内のプロセスが同じPIDを維持しながら、コンテナーを新しいホストに移行したりするなどの機能を提供できます。

分離を除けば、PIDシステムはほぼ機能します 名前空間の外側と同じです。新しい名前空間内のプロセスIDは1から始まります 、最初のプロセスは initと見なされます 処理する。 init プロセスは、ホスト上の他のすべてのPIDとは非常に異なる方法で処理されます。これは、このシリーズの範囲外の実行中のシステムに特に影響します。詳細については、LWN名前空間の記事の「シグナルと初期化プロセス」セクションを参照してください。

ただし、注目すべきは、どのプロセスでもPIDが 1であるということです。 名前空間の寿命に不可欠です。 PIDの場合1 何らかの理由で終了した場合、カーネルはSIGKILLを送信します 名前空間内の残りのすべてのプロセスに対して、その名前空間を効果的にシャットダウンします。

PID名前空間の探索

私のように、 PIDをネストできるかどうか疑問に思っている場合 名前空間、答えはイエスです。実際、カーネルは最大32個のネストされた PID用のスペースを確保します 名前空間。これは一方向の関係と見なされます。つまり、親は子供や孫などのPIDを見ることができます。ただし、祖先のPIDは見ることができません。次のことを考慮してください:

[user@localhost ~] sudo unshare -fp /bin/bash
[root@localhost ~] sleep 90000 &

[root@localhost ~] ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
[truncated ]
.....
root       11627   11620  0 09:16 pts/0    00:00:00 sudo unshare -fp /bin/bash
root       11633   11627  0 09:17 pts/0    00:00:00 unshare -fp /bin/bash
root       11634   11633  0 09:17 pts/0    00:00:00 /bin/bash
root       11639   11634  0 09:17 pts/0    00:00:00 sleep 90000
root       11641   11634  0 09:17 pts/0    00:00:00 ps -ef

[root@localhost ~] sudo unshare -fp /bin/bash
[root@localhost ~] sleep 8000 &

[root@localhost ~] ps -ef
[truncated ]
.....

UID          PID    PPID  C STIME TTY          TIME CMD
root       11650   11634  0 09:17 pts/0    00:00:00 sudo unshare -fp /bin/bash
root       11654   11650  0 09:17 pts/0    00:00:00 unshare -fp /bin/bash
root       11655   11654  0 09:17 pts/0    00:00:00 /bin/bash
root       11661   11655  0 09:17 pts/0    00:00:00 sleep 8000
root       11671   11655  0 09:17 pts/0    00:00:00 ps -ef

PID が原因で、出力が切り捨てられたことに注意してください。 名前空間が表示されます /proc内のすべてのPIDに完全にアクセスできるようにする 。祖先にあるプロセスを停止しようとするとどうなるかを観察します:

[root@localhost ~] kill -9 11361
bash: kill: (11361) - No such process

どうしてこれなの?簡単に言えば、psのような従来のツール 名前空間を認識せず、実際には/procから読み取られます ディレクトリ。 ls /procを実行した場合 、前回の記事で説明したように、 PID があるため、以前のすべてのフォルダとファイルが引き続き表示されます。 名前空間継承 すべてのmnt 名前空間がマウントされます。この状況については後で説明します。今のところ、手元の例に戻ります。

別のシェルで、スリープ状態のプロセスを特定します。

[user@localhost ~] ps -ef |grep sleep
root       11639   11634  0 09:17 pts/0    00:00:00 sleep 90000
root       11661   11655  0 09:17 pts/0    00:00:00 sleep 8000

これらのプロセスが異なる名前空間にあることを確認する場合は、bashを見つける必要があります プロセスPID。 sudo unshare -fp /bin/bashを実行したので、覚えておいてください 、bash プロセスは初期化です 新しい名前空間で処理します。したがって、名前空間IDにリンクされるのはPIDです。 PIDを取得しましょう:

[root@localhost ~] ps -ef |grep bash
root       11627   11620  0 09:16 pts/0    00:00:00 sudo unshare -fp /bin/bash
root       11633   11627  0 09:17 pts/0    00:00:00 unshare -fp /bin/bash
root       11634   11633  0 09:17 pts/0    00:00:00 /bin/bash
root       11650   11634  0 09:17 pts/0    00:00:00 sudo unshare -fp /bin/bash
root       11654   11650  0 09:17 pts/0    00:00:00 unshare -fp /bin/bash
root       11655   11654  0 09:17 pts/0    00:00:00 /bin/bash

PIDを確認できます11634 および11655 出力で。これをlsnsの出力と比較すると (名前空間のリスト)、次のように表示されます:

[root@localhost ~] lsns |grep bash
        NS TYPE   NPROCS    PID USER             COMMAND
4026532952 pid         4 11634 root             /bin/bash
4026532954 pid         4 11655 root             /bin/bash

ご覧のとおり、名前空間IDが異なるため、プロセスは異なる名前空間にあります。

名前空間が実際に異なることを確認したので、前述のPIDの祖先を見てみましょう。これを行うには、 NSpidを特定します。 /proc内の特定のPIDの属性 以下に示すように、ディレクトリ:

sudo cat /proc/11655/status |grep NSpid
NSpid:    11655    6    1

列は左から右に読み取られ、それぞれの名前空間のPIDを示します。左端のPIDは、プライマリまたはルートの名前空間です。この場合、PIDは 11655です。 、 6のセカンダリPID 、および 1の3次PID 。名前空間は各子孫を所有しているため、 PID 名前空間、次のように考えることができます:

  • ホストでは、bash sleep 8000を実行しているプロセス コマンドのPIDは11655です 。
  • 最初の「コンテナ」内のbash sleep 8000を実行しているプロセス コマンドのPIDは6です 。
  • ネストされた2番目の「コンテナ」内では、PIDは 1です。 。これは、実際にプロセスを起動したコンテナです。

これらのbashのそれぞれ コマンドは独自の名前空間内に作成されましたが、親(この場合はルート)に表示されます 名前空間)。

/ proc、PID、および非特権ユーザー

賢明な読者は、最後の2つの記事で、通常のユーザーが両方のユーザーを作成できることに気づいたでしょう。 およびmnt 名前空間。この記事では、sudoを使用しています。 指図。これは、 PIDを作成できないためです。 非特権ユーザーによる名前空間自体。これに対する答えは、複数の名前空間の作成を1つのイベントに結合することです。 /procをマウントするためのいくつかの異なる解決策があります 非特権ユーザーとして。

単に新しいユーザーを作成しようとした場合 名前空間では、奇妙な結果が得られます:

[ user@localhost ~] unshare -Urp
-bash: fork: Cannot allocate memory
-bash-5.1# ps -ef
-bash: fork: Cannot allocate memory
-bash-5.1# ls
-bash: fork: Cannot allocate memory

ここで何が起きてるの?新しいPID内の最初のプロセスがどのように行われたかを覚えておいてください 名前空間はinitになります 処理する?この場合、現在のシェルは名前空間を移動できません。 ルートに存在します 名前空間、および新しい PIDを作成したとき 名前空間、システムはそれを処理する方法を知りませんでした。これに対する解決策は、プロセスフォーク自体を用意することです。これにより、現在のシェルをunshareの子プロセスにすることができます。 指図。 -fを使用する フラグを設定すると、名前空間が作成されます:

[ user@localhost ~] unshare -Urfp
[ root@localhost ~]

ただし、/procの汚染は依然として見られます マウントポイント。これには2つの解決策があります。まず、新しい mntを作成できます 名前空間を作成してから、/procを再マウントします 自分:

[ user@localhost  ~]$ unshare -Urpmf
[ root@localhost ~]# mount -t proc proc /proc
[ root@localhost ~]# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:31 pts/0    00:00:00 -bash
root          10       1  0 09:31 pts/0    00:00:00 ps -ef

実際、長年の間、これが唯一のオプションでしたが、フラグ--mount-proc これを1つのステップで実行するために少し前に作成されました。マニュアルページには次のように書かれています:

プログラムを実行する直前に、マウントポイントにprocファイルシステムをマウントします(デフォルトは/ procです)。これは、新しいPID名前空間を作成するときに役立ちます。また、/ procマウントはシステム上の既存のプログラムを台無しにするため、新しいマウント名前空間を作成することも意味します。新しいprocファイルシステムは明示的にプライベートとしてマウントされます(MS_PRIVATE | MS_RECを使用)。

したがって、次のコマンドへの参照が表示される場合があります。

unshare -Urpf --mount-proc

これにより、新しい mnt が作成されます /procのマウント中の名前空間 あなたのために。

名前空間の入力

複雑さを軽減するために、以前に作成した名前空間を終了しました。次のコマンドで新しい名前空間を作成しました:

unshare -Urfp --mount-proc

異なるも作成しました sleep 名前空間の識別を支援するためだけに処理します。新しい名前空間は1つしかないため、lsnsを使用できます。 正しいPIDを判別するコマンド:

[ user@localhost  ~]$ lsns |grep bash
4026532965 pid         2 13142 user -bash

次に、nsenterを実行します コマンド:

sudo nsenter -t 13142 -a

-a フラグはnsenterに通知します そのPIDのすべての名前空間を入力するコマンド。 sudo -aでは必須です フラグを立てないと、適切な名前空間すべてに変更できなくなります。これで、このNS内のすべてのPIDSを一覧表示できるようになります。

[ root@localhost  ~]$ ps -ef

UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:54 pts/0    00:00:00 -bash
root           8       1  0 09:54 pts/0    00:00:00 sleep 99999
root          25       0  0 10:15 pts/1    00:00:00 -bash
root          31      25  0 10:15 pts/1    00:00:00 ps -ef

[この無料のチートシートでKubernetesの使用の基本を学びます。 ]

まとめ

PID 名前空間は、分離された環境を構築する場合に重要です。これにより、ホストシステムに関係なく、プロセスが独自のPIDを持つことができます。複数のホストが分離された環境(コンテナー)の調整に関与する可能性がある世界では、プロセスの凍結および移行時に一意のPIDを保証する機能が不可欠になります。さらに、セキュリティ上の理由から、アプリケーションを分離するために名前空間を実行している場合は、 PID 名前空間は、ホストが実行している可能性のあるプロセスを介した情報漏えいを防ぐために不可欠です。

ユーザーと組み合わせると およびmnt 名前空間、 PID 名前空間は、root権限を必要とせずに多くの保護を提供します。 FirefoxやVivaldiなどの最新のブラウザーは、名前空間を使用してブラウザーのサンドボックス化を提供します。次の記事では、ネットのデモを行います。 名前空間を作成し、個別のネットワークコンポーネントを追加して、手動でコンテナを構築し続ける方法を確認してください。


Linux
  1. 子プロセスのPgidが親のPidではないのはなぜですか?

  2. プロセスIDの最大値は?

  3. Linux –特定のポートを使用してプロセスのPidを見つけますか?

  1. どのプロセスにPid0がありますか?

  2. TaxCloudの構築

  3. プロセスが死なない限り、プロセス PID は同じままであることが保証されていますか?

  1. 名前空間を使用して手動でコンテナを構築する:UTS名前空間

  2. Ubuntu でプロセス ID を見つけるにはどうすればよいですか?

  3. プロセスが実行されている特定のプロセッサを特定する