我们可以用以下几个步骤来实验下 UTS Namespace 功能:
创建 UTS Namespace
利用 clone()
创建一个新进程,同时创建一个 UTS 类型的 namespace,新进程中修改主机名,此时新进程可使用与全局不一样的主机名:
1
2
3
4
5
6
7
8
|
# hostname # 全局系统的 hostname
k8s-test11
# ./new_uts
parent 21963 start up
parent => start a child process
parent => child process 21964 is started
# hostname # 子进程中使用了 UTS namespace,hostname 已被改变
new_uts
|
执行完 new_uts
后,当前 shell 其实已经转入子进程的 shell 中,运行 uname
命令将看到 hostname 已经被更改为 new_uts
,new_uts
的代码片段如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
...
static char child_stack[STACK_SIZE];
char* const child_args[] = {
"/bin/bash",
NULL
};
int child_main(void *args) {
...
sethostname("new_uts", 9);
execv(child_args[0], child_args);
...
}
int main(void) {
...
int child_pid = clone(child_main, child_stack+STACK_SIZE, CLONE_NEWUTS|SIGCHLD, NULL);
waitpid(child_pid, NULL, 0);
...
}
|
详细可参考 new_uts.c;
查看 /proc
信息
查看父进程 20762 和子进程 20763 的 /proc
信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# ls -l /proc/21963/ns
total 0
lrwxrwxrwx 1 root root 0 Apr 15 12:22 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 net -> net:[4026531993]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 pid_for_children -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 uts -> uts:[4026531838]
# ls -l /proc/21964/ns
total 0
lrwxrwxrwx 1 root root 0 Apr 15 12:22 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 net -> net:[4026531993]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 pid_for_children -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Apr 15 12:22 uts -> uts:[4026532301]
|
从 /proc
上可看到,父子进程除了 uts
的 namespace 号不一样外,其他的 namespace 均一致。也就是说,父子进程除了分别使用各自的 UTS namespace 外,其他类型 namespace 仍处于同一集合中;
将新进程加入到 UTS Namespace 中
利用 setns()
将当前进程加入到已创建子进程(上文中 pid 为 21964 的进程)的 UTS namespace 中,其中 ns_exec
的代码片段如下所示:
1
2
3
4
5
6
7
8
9
|
...
int main(void) {
...
fd = open(argv[1], O_RDONLY); // 获取 /proc 下对应进程的 namespace 文件
setns(fd, 0); // 标记 0 代表是 UTS Namespace
execvp(argv[2], &argv[2]); // 我们将会让其执行 /bin/bash
...
}
...
|
详细代码可参考代码 ns_exec.c):
1
2
3
4
5
6
7
|
# hostname # 全局系统的 hostname
k8s-test11
# ./ns_exec /proc/21964/ns/uts /bin/bash # 将启动进程加入到
process 26018 start up # 21964 的 uts namespace 中
# hostname
new_uts
|
此时我们查看 26018 的 /proc
信息:
1
2
3
4
5
6
7
8
9
10
|
# ls -l /proc/26018/ns/
total 0
lrwxrwxrwx 1 root root 0 Apr 15 12:41 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Apr 15 12:41 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Apr 15 12:41 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Apr 15 12:41 net -> net:[4026531993]
lrwxrwxrwx 1 root root 0 Apr 15 12:41 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Apr 15 12:41 pid_for_children -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Apr 15 12:41 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Apr 15 12:41 uts -> uts:[4026532301]
|
可以看到 21964 和 26018 的 uts namespace 号是一样的,即这两个进程同属于一个 uts namespace。