私は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