Docker探索namespace详解

Docker通过namespace实现了资源隔离,通过cgroups实现了资源限制,通过写时复制(copy-on-write)实现了高效的文件操作。

1.namespace资源隔离

namepsace的6项隔离:

namespace 系统调用参数 隔离内容
UTS CLONE_NEWUTS 主机名与域名
IPC CLONE_NEWIPC 信号量,消息队列和共享内存
PID CLONE_NEWPID 进程编号
Network CLONE_NEWNET 网络设备,网络栈,端口等
Mount CLONE_NEWNS 挂载点(文件系统)
User CLONE_NEWUSER 用户和用户组

Linux内核实现namespace的主要目的之一是实现轻量级虚拟化(容器)服务。在同一个namespace下的进程可以感知彼此的变化,而对外界进程一无所知。这样就可以让容器中的进程产生错觉,仿佛自己置身于一个独立的系统环境中,以达到独立和隔离的目的。

进行namespace API操作的4种方式

namespace的API包括clone(),setns()以及unshare(),还有/proc下的部分文件。为了确定隔离的到底是哪6项namespace,在使用这些API时,通常需要指定以下6个参数的一个或多个,通过位或操作来实现。

CLONE_NEWUTS,CLONE_NEWIPC,CLONE_NEWPID,CLONE_NEWNET,CLONE_NEWNS,CLONE_NEWUSER.

通过clone()在创建新进程的同时创建namespace

使用clone()来创建一个独立namespace的进程是最常见的做法,也是Docker使用namespace的最基本的方法,它的调用方式如下。

NAME
    clone, __clone2 - create a child process
SYNOPSIS
    /* Prototype for the glibc wrapper function */
    #include <sched.h>
    int clone(int (*fn)(void *), void *child_stack,
         int flags, void *arg, ...
         /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ ); 

clone()实际上是fork系统调用的一种更通用的实现方式,它可以通过flags来控制使用多少功能。一共有20多种CLONE_*的flag(标志位)参数用来控制clone进程的方方面面(如是否与父进程共享虚拟内存等).

查看/proc/[pid]/ns文件

从3.8版本内核开始,用户可以在该文件下看到指向不同namespace号的文件:

 ls -l /proc/2597/ns
total 0
lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 net -> net:[4026531957]
lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 pid -> pid:[4026531836]
lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 user -> user:[4026531837]
lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 uts -> uts:[4026531838]

如果2个进程namespace号相同,说明它们在同一个namespace下。

/proc/[pid]/ns里设置这些符号链接的另一个作用是,一旦上述链接文件被打开,那么就算该namespace下的所有进程都已经结束,这个namespace也会一直存在,后续进程也可以再加进来。在Docker中,通过文件描述符定位和加入一个存在的namespace是最基本的方式。

另外,把/proc/[pid]/ns目录文件使用--bind方式挂载起来可以直到同样的作用:

# mount --bind /proc/2454/ns/uts uts

通过setns()加入一个已经存在的namespace

上面提到,在进程都结束的情况下,也可以通过挂载的形式把namespace保留下来,保留namespace的目的是为以后有进程加入做准备。在Docker中,使用docker exec命令在已经运行着的容器中执行一个新命令,就需要用到该方法。通过setns()系统调用,进程从原先的namespace加入某个已经存在的namespace,使用方法如下。通常为了不影响进程的调用者,也为了使新加入的pid namespace生效,会在setns()函数执行后使用clone创建子进程继续执行命令,让原先的进程结束。

NAME
    setns - reassociate thread with a namespace
SYNOPSIS
    #define _GNU_SOURCE       /* See feature_test_macros(7) */
    #include <sched.h>
    int setns(int fd, int nstype); 
fd = open(argv[1],O_RDONLY);
setns(fd,0);
execvp(argv[2],&argv[2]); 

假设编译后的程序为"setns-test"
# ./setns-test ~/uts /bin/bash

至此,就可以在新加入的namespace中执行shell命令了。

通过unshare()在原先进程上进行namespace隔离

它与clone()很像,不同的是,unshare()运行在原先的进程上,不需要启动一个新进程。

NAME
    unshare - disassociate parts of the process execution context
SYNOPSIS
    #include <sched.h>
    int unshare(int flags); 

调用unshare()的主要作用就是不启动一个新进程就可以起到隔离的效果,相当跳出原先的namespace进行操作。这样,就可以在原进程进行一些需要隔离的操作。Linux自带的unshare命令,就是通过unshare()系统调用实现的。Docker目前并没有使用这个系统调用。

总结

以上就是本文关于Docker探索namespace详解的全部内容,希望对大家有所帮助,感兴趣的朋友可以继续参阅本站:浅谈Docker安全机制内核安全与容器之间的网络安全、详解Docker使用Linux iptables 和 Interfaces管理容器网络等,有什么问题可以随时留言,小编会及时回复大家的。感谢朋友们对本站的支持!

(0)

相关推荐

  • Docker端口映射实现网络访问的方法

    Docker运行容器之后却发现没IP,没端口,那要如何访问容器呢? 下面我来介绍下docker通过端口映射来实现网络访问 一.从外部访问容器应用 在启动容器的时候,如果不指定对应参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的. 当容器中运行一些网络应用,要让外部访问这些应用时,可以通过-P或-p参数指定端口映射. 先来说说p和P吧 -p 可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器 -P 它会随机映射一个端口至容器内部开放的网络端口(范围不详,似乎都上万) 先申明

  • Docker网络之单host网络及使用案例

    前言 前面总结了Docker基础以及Docker存储相关知识,今天来总结一下Docker单主机网络的相关知识.毋庸置疑,网络绝对是任何系统的核心,他在Docker中也占有重要的作用. 一.Docker默认网络 在新安装docker的主机上执行 docker network ls 便能看到docker默认安装的所有网络,分别是none网络.host网络和bridge网络. 1.1 none 网络 none网络就是什么都没有的网络.挂在这个网络下的容器除了lo,没有其他任何网卡.容器run时,可以通

  • docker中修改镜像容器的存放目录的方法

    最近在学习docker的路上,今天遇到了个问题,在网上查找了一下资料,顺便留个笔记 在默认情况下,Docker镜像和容器的默认存放位置为: /var/lib/docker 一般根下分区我们不会给太大.镜像和容器越存越多一般我们有两种解决方法: 1. 挂载大分区到/var/lib/docker 一般选择建立逻辑分区lvm,方便后期扩展集体. 建立新分区,并格式化 [root@localhost lib]# lvcreate -L 300G lv_docker vg_home [root@local

  • Docker探索namespace详解

    Docker通过namespace实现了资源隔离,通过cgroups实现了资源限制,通过写时复制(copy-on-write)实现了高效的文件操作. 1.namespace资源隔离 namepsace的6项隔离: namespace 系统调用参数 隔离内容 UTS CLONE_NEWUTS 主机名与域名 IPC CLONE_NEWIPC 信号量,消息队列和共享内存 PID CLONE_NEWPID 进程编号 Network CLONE_NEWNET 网络设备,网络栈,端口等 Mount CLON

  • Docker基础命令详解

    docker基本概念 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上. Docker是一个重新定义了程序开发测试.交付和部署过程的开放平台,Docker则可以称为构建一次,到处运行,这就是docker提出的"Build once,Run anywhere" 创建镜像 创建镜像的方法有三种: 基于已有的容器创建 基于本地模板导入 基于dockerfile 基于已有的容器创建 主要使用docker

  • jenkins构建Docker 镜像实例详解

     jenkins构建Docker 镜像实例详解 前言:jenkins有Docker镜像,而之前我们说过使用jenkins打包Docker镜像,那么可否用jenkins的Docker镜像打包Docker镜像呢? 环境: CentOS 7     Docker 1.10.3 1.本机安装docker环境,并配置TCP访问接口 # vi /usr/lib/systemd/system/docker.service 修改ExecStart为: ExecStart=/usr/bin/docker daem

  • Docker基本命令使用详解(推荐)

    因为工作中需要将服务容器化,所以最近开始学习Docker相关的知识,对于Docker入门常用的命令总结如下: 1. 运行容器 $ sudo docker run -i -t ubuntu /bin/bash -i 标志保证容器中的STDIN是开启的 -t 标志告诉Docker为要创建的容器分配一个伪tty终端 ubuntu 表示我们创建容器使用的镜像 /bin/bash 表示当容器创建完成之后,Docker就会执行容器中的/bin/bash命令 2. 给容器命名 $ sudo docker ru

  • Ubuntu下安装配置Docker的教程详解

    获取Docker 1.准备 Docker要求64位Linux且内核版本在3.10以上,在终端里输入uname -r查看,如图: 接下来更新源并查看是否有https方法: sudo apt-get update sudo apt-get install apt-transport-https ca-certificates 2.添加key 输入以下命令添加GPG key: sudo apt-key adv \ --keyserver hkp://ha.pool.sks-keyservers.net

  • 使用TLS加密通讯远程连接Docker的示例详解

    默认情况下,Docker 通过非联网 UNIX 套接字运行.它还可以使用 HTTP 套接字进行可选通信. 如果需要以安全的方式通过网络访问 Docker,可以通过指定标志将 Docker 标志指向受信任的 CA 证书来启用 TLS. 在守护程序模式下,它只允许来自由该 CA 签名的证书验证的客户端的连接.在客户端模式下,它仅连接到具有该 CA 签名的证书的服务器. # 创建CA证书目录 [root@localhost ~]# mkdir tls [root@localhost ~]# cd tl

  • Docker Machine深入详解

    Docker 与 Docker Machine 的区别 Docker 是一个 Client-Server 架构的应用,人家是有官称的:Docker Engine.Docker 只是大家对 Docker Engine 的昵称,当然 Docker 还有其他的意思,比如一家公司的名称.简单起见,本文中的 Docker 等同于 Docker Engine. 提到 Docker 我们必须要知道它包含了三部分内容: Docker daemon 一套与 Docker daemon 交互的 REST API 一

  • C/C++中命名空间(namespace)详解及其作用介绍

    目录 概述 命名空间 命名空间的作用 自定义命名空间 命名空间成员的方法 案例 概述 命名空间 (namespace) 可以帮助我们区分不同库中相同名称的函数, 类, 变量等. 使用了命名空间即定义了上下文. 命名空间就是定义了一个范围. 命名空间 为了解决 C++ 标准库中的标识符与程序中的全局标识符之间以及不同库中的所有标识符之间的命名冲突. 标准 C++ 库的所有标识符都定义在一个名为 std 的命名空间中. 在程序中用到 C++ 标准库时, 使用 std 作为限定. 我们在写 "Hell

  • mysql8.x docker远程访问配置详解

    目录 环境情况 遇到的错误 解决方法 1. 登录 mysql docker 内部 2. 设置root密码 3. 设置 root 远程访问权限 4. 设置普通用户 myuser 的远程访问 环境情况 mysql 8.x 是通过 docker 方式部署的,启动的 docker-compose.yml 如下: version: "3.2" services: mysql: container_name: mysql image: "mysql:8.0" ports: -

  • Docker容器操作方法详解

    目录 一.常用命令 1.创建并启动容器 2.列出所有容器 3.进入容器 4.退出容器 5.停止容器 6.启动/重启一个已停止的容器 7.删除容器 二.使用帮助 一.常用命令 下面按照使用容器中的流程: 创建并启动容器 > 查询容器 > 进入容器 > 退出容器 > 停止容器 > 启动/重启容器 > 删除容器来介绍Dockers常用命令,带领小伙伴快速入门. 1.创建并启动容器 docer run 当操作者执行docker run时,运行的容器进程是隔离的,因为它有自己的文

随机推荐