namespace是linux内核用来隔离内核资源的方案。 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前 namespace 里的进程,对其他 namespace 中的进程没有影响。
名称 | 宏定义 | 隔离的资源 |
IPC | CLONE_NEWIPC | System V IPC(信号量、消息队列、共享内存) 和POSIX MESSAGE QUEUES |
Network | CLONE_NEWNET | Network devices、stacks、ports(网络设备、网络栈、端口等) |
Mount | CLONE_NEWNS | Mount points(文件系统挂载点) |
PID | CLONE_NEWPID | Process IDs(进程编号) |
User | CLONE_NEWUSER | User and Groups IDs(用户和用户组) |
UTS | CLONE_NEWUTS | Hostname and NIS domain name(主机名与NIS域名) |
Cgroup | CLONE_NEWCGROUP | Cgroup root directory(cgroup的根目录) |
# 查看进程18863的namespace ll /proc/18863/ns
可以看到,namespace 是链接文件,格式为[隔离类型:唯一标识],唯一标识可看成namespace的ID,同一个ID下的进程共享该namespace的全局资源。
#define _GNU_SOURCE #include <sys/mount.h> #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 - inside the container!\n"); execv(container_args[0], container_args); printf("Something‘s wrong!\n"); return 1; } int main() { printf("Parent - start a container!\n"); int container_pid = clone(container_main, container_stack+STACK_SIZE, CLONE_NEWNS | SIGCHLD , NULL); waitpid(container_pid, NULL, 0); printf("Parent - container stopped!\n"); return 0; }
编译并执行:
# 编译 gcc -o ns ns.c -D_GNU_SOURCE -lpthread # 执行 ./ns
结果:
执行ns,显示我们进入到了一个容器中。假象我们容器是挂载到/tmp目录下,查看/tmp,其实这里仍然是宿主机的文件。紧接着,把容器以 tmpfs(内存盘)格式,重新挂载了 /tmp 目录。
#define SOURCE #include <sys/mount.h> #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("进入容器里面!\n"); mount("none", "/tmp", "tmpfs", 0, ""); execv(container_args[0], container_args); printf("错误\n"); return 1; } int main() { printf("宿主机启动一个容器!\n"); int container_pid = clone(container_main, container_stack+STACK_SIZE, CLONE_NEWNS | SIGCHLD , NULL); waitpid(container_pid, NULL, 0); printf("容器停止!\n"); return 0; }
在容器启动前加 mount("none", "/tmp", "tmpfs", 0, "");
再编译执行ns,挂载后,就看不见任何宿主机的文件了。这就是在当前容器下的单独的文件系统了。
https://time.geekbang.org/column/article/17921
https://www.cnblogs.com/lioa/p/12664686.html
原文:https://www.cnblogs.com/lioa/p/12666497.html