私はLinuxコンテナの内部の仕組みを理解しようとしています。私が学んだことの1つは、特別なフラグを渡してシェルをコンテナ化できることです。フラグの1つはPID用です。
ps
ただし、これはまだホストとコンテナのすべてのプロセスを表示するため、コマンドに望ましい効果はありません。これはps
ディレクトリからの読み込みによるものです。/proc
コンテナで実行されているプロセスのみを表示する方法の1つps
は、偽のルートファイルシステム(オペレーティングシステムのディレクトリ/ユーティリティのみを含む)としてルートを指定し、ホストディレクトリを/proc
偽のfsのprocディレクトリにマウントすることです。
私はこれが実際になぜ動作するのか理解していません。/proc
ディレクトリを別のマウントポイントにマウントすると、コンテナ化されたかのように動作するのはなぜですか?
Dockerのようなコンテナが正しく機能するために偽のルートファイルシステムが必要なのはなぜですか?
私は何を逃したことがありませんか?
私が説明する技術はこの動画DockerConで。
メソッドが完了する正確な時刻へのリンクを設定しました。
答え1
そのunshare
コマンドについて話していると仮定すると、解決策は--mount-proc
マウントネームスペースを共有解除し、/proc
新しいpidネームスペースを参照する新しいネームスペースをマウントするオプションを使用することです。pid_namespaces(7)
マニュアルページを参照してください。
/proc および PID 名前空間
/ procファイルシステム(/ proc / [pid]ディレクトリにあります)は、/ procファイルシステムが別の名前空間のプロセスで表示されていても、マウントを実行しているプロセスのPID名前空間に表示されるプロセスにのみ表示されます。
新しいPID名前空間を作成した後、子がルートディレクトリを変更し、/ procに新しいprocfsインスタンスをマウントすると、ps(1)などのツールが正しく機能できるようにするのが便利です。
clone(2) または unshare(2) のフラグ引数に CLONE_NEWNS を含む新しいマウント名前空間を同時に作成する場合、ルートディレクトリを変更する必要はありません。新しいprocfsインスタンスは/ procに直接マウントできます。
シェルから/ procをマウントするコマンドは次のとおりです。
$ mount -t proc proc /proc
/proc/self パスで readlink(2) を呼び出すと、procfs によってマウントされた PID 名前空間 (つまり、procfs をマウントするプロセスの PID 名前空間) に呼び出し元のプロセス ID が生成されます。これは、プロセスが別の名前空間からそのPIDを取得しようとするときに自己検査目的に役立ちます。
$ sudo unshare -p -f ps -o pid,ppid,pidns,mntns,comm
PID PPID PIDNS MNTNS COMMAND
27462 24107 4026531836 4026531840 sudo
27463 27462 4026531836 4026531840 unshare
27464 27463 4026532863 4026531840 ps
$ sudo unshare -p --mount-proc -f ps -o pid,ppid,pidns,mntns,comm
PID PPID PIDNS MNTNS COMMAND
1 0 4026532864 4026532863 ps
unshare
dockerなどの名前空間にアクセスするためのラッパーとシステムコール用の低レベルユーティリティですnsenter
。unshare(2)
setns(2)
strace
何が起こっているのかを彼らに伝えることができます。第二に:
mntとpidの名前空間共有を解放します。
5281 unshare(CLONE_NEWNS|CLONE_NEWPID) = 0
子供をフォークする(なぜなら
-f
)5281 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f6b0af4a7d0) = 5282
受け継がれた子供共有されていません名前空間
マウントが親名前空間と子名前空間の両方に伝播しないように、新しい mnt 名前空間でマウント伝播を無効にします。
5282 mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL) = 0 5282 mount("none", "/proc", NULL, MS_REC|MS_PRIVATE, NULL) = 0
内部に新しいpid名前空間の新しいprocをマウントします
/proc
(なぜならps
それが見つかると予想される場所であり、私たちがmnt名前空間を作成した理由だからです)。別のオプションは、いくつかのバインドマウントとを使用することですchroot
。 fsはpid名前空間をproc
親mnt名前空間にマウントすることもできますが、そうすると大きな問題が発生する可能性があります。5282 mount("proc", "/proc", "proc", MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL) = 0
ps
この名前空間で実行5282 execve("/bin/ps", ["ps", "-o", "pid,ppid,pidns,mntns,comm"], 0x7fff5a325dd8 /* 73 vars */) = 0
答え2
ただ映像を見ました。彼女はprocタイプを/ procとしてマウントし、できるだけ多く表示しました(他のプロセス名前空間にありました)。ホストを表示できますが、/proc
プロセスの名前空間にリークがあります。
状況が混ざっています。さまざまな名前空間があります。ビデオには、ホスト名の名前空間(彼女はあまり注意を払わなかった)、プロセスの名前空間、およびファイルシステムの名前空間(chroot経由)が表示されます。ファイルシステムとプロセスの名前空間を混在させています。それはおそらくファイルps
システム(/proc
)を使用していますが、プロセス名前空間を使用したいからです。 procはプロセス名前空間を使用するため、新しいprocが作成されると新しい名前空間になります。
インストールする
インストールは再インストールではありません(再インストールオプションはありません)。
複数のプロセスを持つことができますか?試してみてください。はい、しかし他の場所では、psはそれを使用します/proc
。チートのために静的ファイルに置き換えることもできます。ただし、ファイル、ディレクトリ、または特殊ファイル(chrootを実行しない限り)はps
1つしか存在できません。/proc
カーネルがすべてのproc
sを書くかどうか
いいえ、カーネルは同時に2つの場所に書き込まれません(書き込む内容はありません(ディスクスペースではありません))。 procから読み取ると、カーネルは適切なデータを生成します(使用する名前空間によって異なります)。 re in)一度に1つしか読み取ることができないので、一度に1つだけを作成でき、必要なだけ読み取ることができます(1ファイルのみ)。
Linuxのどの名前空間がどのファイルシステムに対応するかについての文書はありますか?
ls
これは、名前空間がどの名前空間にあるのかを尋ねるのと同じです。そうではありませんが、名前空間の影響を受けます。したがって、procは現在のプロセス名前空間内のプロセスについてのみ知ることができます。 procの他の部分は、異なる名前空間タイプの影響を受ける可能性があります(その機能によって異なります)。