以下のコードでは、syscall.CLONE_NEWNSでプロセスを開始すると、プロセスが終了すると名前空間内のすべてのマウントオプションがクリアされると考えました。golangマウント名前空間:マウントされたボリュームは、プロセスが終了してもクリアされません。
でもそうですか?
package main
import (
"fmt"
"os"
"os/exec"
"syscall"
)
var command string = "/usr/bin/bash"
func container_command() {
fmt.Printf("starting container command %s\n", command)
cmd := exec.Command(command)
cmd.SysProcAttr = &syscall.SysProcAttr{Cloneflags: syscall.CLONE_NEWPID |
syscall.CLONE_NEWNS,
}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println("error", err)
os.Exit(1)
}
}
func main() {
fmt.Printf("starting current process %d\n", os.Getpid())
container_command()
fmt.Printf("command ended\n")
}
これを実行してディレクトリをマウントすると、このディレクトリはプログラムの終了後でも終了します。
[[email protected] go]# go run namespace-1.go
starting current process 7558
starting container command /usr/bin/bash
[[email protected] go]# mount --bind /home /mnt
[[email protected] go]# ls /mnt
vagrant
[[email protected] go]# exit
exit
command ended
[[email protected] go]# ls /mnt
vagrant
[[email protected] go]#
これが望ましい動作であれば、どのようにprocをコンテナ実装にマウントしますか?なぜなら私が名前空間内にprocをマウントすると、私は
[[email protected] go]# mount -t proc /proc
[[email protected] go]# exit
exit
command ended
[[email protected] go]# mount
mount: failed to read mtab: No such file or directory
[[email protected] go]#
procを取り戻すために再マウントする必要があるからです。
更新: Cで同じことを行っても同じ結果が得られますが、これは意図した動作でなければならないと思います。
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#define STACK_SIZE (1024 * 1024)
static char container_stack[STACK_SIZE];
char* const container_args[] = {
"/bin/bash",
NULL
};
int container_main(void* arg)
{
printf("Container [%5d] - inside the container!\n", getpid());
sethostname("container",10);
system("mount -t proc proc /proc");
execv(container_args[0], container_args);
printf("Something's wrong!\n");
return 1;
}
int main()
{
printf("start a container!\n");
int container_pid = clone(container_main, container_stack+STACK_SIZE,
CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL);
waitpid(container_pid, NULL, 0);
printf("container ended!\n");
return 0;
}
コマンドの出力:
[[email protected] ~]# gcc a.c
[[email protected] ~]# ./a.out
start a container!
Container [ 1] - inside the container!
[[email protected] ~]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 08:57 pts/0 00:00:00 /bin/bash
root 17 1 0 08:57 pts/0 00:00:00 ps -ef
[[email protected] ~]# exit
exit
container stopped!
[[email protected] ~]# ps -ef
Error, do this: mount -t proc proc /proc
[[email protected] ~]# cat a.c
感謝を。記録のために、golangで 'mount --make-private /'を達成するために、マウントフラグは 'syscall.MS_PRIVATE | syscall.MS_REC'です –