Docker背后的内核知识Linux namespace

版权声明:本文为博主原创文章,如需转载请标明出处链接!否则追究法律责任! https://blog.csdn.net/peng314899581/article/details/73527702

Docker引擎的基础是Linux容器技术(Linux Containers,LXC)容器有效地将由单个操作系统管理的资源划分到孤立的组中,以便更好地在孤立的组之间平衡有冲突的资源使用需求。具体体现在6个方面:

namespaces
Mount CLONE_NEWNS 挂载点(文件系统)
UTS CLONE_NEWUTS 主机名与域名
IPC CLONE_NEWIPC 信号量、消息队列和共享内存
PID CLONE_NEWPID 进程号
Net CLONE_NEWNET 网络设备、网络栈、端口等等
User CLONE_NEWUSER 用户和用户组

模拟Docker引擎如何使用linux namespace实现容器隔离

/* 定义一个给 clone 用的栈,栈大小1M */
\#define STACK_SIZE (1024 * 1024)
static char container_stack[STACK_SIZE];
char* const container_args[] = {
    "/bin/bash",
    NULL
};

int container_main(void* arg)
{
    /* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */
    execv(container_args[0], container_args); 
    return 1;
}

int main()
{
    /* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */
    int container_pid = clone(container_main, container_stack+STACK_SIZE, CLONE_* | SIGCHLD, NULL);
    /* 等待子进程结束 */
    waitpid(container_pid, NULL, 0);
    return 0;
}

我们可以理解为,linux启动的时候会内核默认创建一个父命名空间,每一个docker都是父命名空间创建的子命名空间,子命名空间中的所有资源(以下6个资源)在子命名空间中都有自己的标识,同时会在父命名空间映射一个标识。该父命名空间是所有docker子命名空间的祖先,所以所有docker子命名空间对linux父命名空间来说都是可见的,但是docker子命名空间对于这些资源来收是它们独立的空间,不同命名空间的资源是不能共享的,保证了隔离。
1.每个docker都有自己的文件目录。
2.每个docker都有自己的主机名与域名。
3.每个docker都有自己的信号量、消息队列和共享内存。虽然进程间通信被隔离,但是大多数情况下docker之间的通信都是用socket来实现,例如本机上的不同docker之间使用unix socket,不同主机上的docker就可以理解为tcp/udp通信了。
4.每个docker都有自己的进程号。例如linux系统进程号为1的进程是init进程,在子命名空间中创建的第一个进程pid也是1,它映射到父命名空间中还有自己的一个pid,相互隔离。
5.每个docker都有自己的网络设备、网络栈、端口等等。
6.每个docker都有自己的用户和用户组。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页