注:本文分析基于3.10.0-693.el7内核版本,即CentOS 7.4
背景
容器技术的产生主要依赖于Linux内核的两大技术,Namespace和Cgroup,也就是资源隔离和资源限制。这两种技术都可以单独使用,但是把它们放到一起后,实现的功能更为强大。我们今天就来了解了解Namespace技术。
Namespace种类
目前,内核中实现了6中Namespace:
Namespace | 作用 |
---|---|
UTS | 隔离主机名和域名 |
IPC | 隔离信号量、消息队列 |
PID | 隔离进程编号 |
Network | 隔离网络设备、协议栈、端口 |
Mount | 隔离文件系统 |
User | 隔离用户和用户组 |
体验Namespace
对于Namespace的操作,主要通过clone()、setns()和unshare()这三个系统调用来实现,也就是Namespace的创建、加入和删除操作。
A、创建
由上我们知道有六种Namespace,因此对应到clone上,也有六个标志位与此对应。
Namespace | clone标志 |
---|---|
UTS | CLONE_NEWUTS |
IPC | CLONE_NEWIPC |
PID | CLONE_NEWPID |
Network | CLONE_NEWNET |
Mount | CLONE_NEWNS |
User | CLONE_NEWUSER |
在使用clone前我们先了解一下clone函数的入参,
int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg);
其中,
child_func:表示子进程运行的主函数
child_stack:子进程使用的栈空间
flags:表示使用哪些 CLONE标志位
args:可用于传入用户参数
接下来我们以UTS隔离为例,看下效果。创建namespace.c,输入以下代码。
#define _GNU_SOURCE
#include <sys/wait.h>
#include <sys/utsname.h>
#include <sched.h>
#include <stdio.h>
#define STACK_SIZE (1024 * 1024)
#define FLAGS SIGCHLD|CLONE_NEWUTS
static char stack[STACK_SIZE];
static char * const child_args[] = {"/bin/bash", NULL };
static int child(void *arg)
{
execv("/bin/bash", child_args);
return 0;
}
int main(int argc, char *argv[])
{
pid_t pid;
pid = clone(child, stack+STACK_SIZE, FLAGS, NULL);
waitpid(pid, NULL, 0);
return 0;
}
该代码运行后会新创建一个bash交互窗口,类似于在终端输入bash命令。
使用以下命令编译,
gcc namespace.c -o namespace
然后我们运行namespace,并进行修改hostname的操作,
[root@CentOS-7-4 /home/namespace]# ls
. .. namespace namespace.c
[root@CentOS-7-4 /home/namespace]# hostname
CentOS-7-4
[root@CentOS-7-4 /home/namespace]# ./namespace
[root@CentOS-7-4 /home/namespace]# hostname
CentOS-7-4
[root@CentOS-7-4 /home/namespace]# hostname newname
[root@CentOS-7-4 /home/namespace]# hostname
newname
[root@CentOS-7-4 /home/namespace]# exit
exit
[root@CentOS-7-4 /home/namespace]# hostname
CentOS-7-4
可见,通过UTS隔离后,我们进入新的终端修改主机名成功后,返回原先终端,修改的主机名并没有影响到原先的主机,因此达到了主机名的隔离效果。
我们再看下IPC的隔离效果,在上面代码的基础上,将FLAGS变量定义如下:
#define FLAGS SIGCHLD|CLONE_NEWUTS|CLONE_NEWIPC
同样进行编译,然后执行创建消息队列操作,
[root@CentOS-7-4 /home/namespace]# ./namespace
[root@CentOS-7-4 /home/namespace]# ipcmk -Q
Message queue id: 0
[root@CentOS-7-4 /home/namespace]# ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
0x217cc434 0 root 644 0 0
[root@CentOS-7-4 /home/namespace]# exit
exit
[root@CentOS-7-4 /home/namespace]# ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
我们在新终端创建一个消息队列,但是在host上却看不到任何消息队列,因此IPC的隔离达到了效果。
其他的隔离也都可以通过相应的标志位由clone创建,就不再一一测试了。