• Docker技术使用场景主要特性等相关资源整理
  • OpenStack与Docker集成:使用openstack管理docker
  • Docker的隔离性和安全性问题
  • docker使用的技术之Container内核原理介绍
  • Docker详细的应用与实践架构举例说明
  • ​基于Docker的大数据开发实践
  • ​docker之轻量虚拟化技术——docker实战分享
  • 什么是docker?Docker技术详细介绍
  • 基于Docker容器的云计算平台搭建实战
  • docker和VM虚拟机的区别以及如何用docker搭建基础设施
  • ​Docker容器术语以及docker的特点
  • Docker & Docker Hub
  • Introduction to Swarm, a Docker-native clustering system
  • Docker、Kubernetes、Neutron中的网络简介
  • ​James Turnbull:《The Docker Book》
  • Docker on AWS:Running Containers in the Cloud
  • Introduction docker Container Security
  • docker应用之利用Docker构建自动化运维
  • Docker基本原理简介和详细安装步骤介绍
  • Docker 基础用法和常用命令及选项介绍
  • Docker 端口映射,端口绑定操作介绍
  • Docker 四种网络模式及网络配置详细介绍
  • docker下通过Dockerfile指令构建镜像的指令选项介绍
  • ​Docker 容器数据管理,链接容器,构建私有库
  • Docker容器分析----好处和缺点介绍
  • 如何实现 coreos 下Docker 与分布式数据库结合
  • 应对 Docker 网络功能难题的挑战与思考
  • Docker着手将容器部署到私有云与公有云
  • 为现在和未来改善Docker安全
  • Docker容器与企业存储的结合思考
  • Docker监控以及cAdvisor和Prometheus监控工具的对比
  • ​有关Docker的八个令人难以置信的事实
  • ​部署 Docker 前必须问自己的四个问题
  • 程序猿,千万别说你不了解Docker!
  • 将要改变IT世界的的docker技术是什么?
  • Docker支持更深入的容器日志分析
  • Docker宣布支持Windows 10和Azure Windows Server
  • Docker 1.12.0到底有哪些不同之处
  • 云计算之Docker容器技术如何落地?
  • Docker v1.12.0-rc5 普通版实验版本下载,高级容器引擎
  • 针对Docker容器的监控指标
  • ​Docker 的步伐:DevOps 与 OS 化
  • 八个问题帮你快速了解Docker
  • ​什么是Docker以及docker的 诞生技术演进
  • ​Docker v1.12.1-rc1各种版本发布下载,高级容器引擎
  • ​Docker 1.12.0 改进了服务的负载均衡参数
  • Windows下Docker应用部署相关问题详解
  • Docker1.12 引擎使用体验 ​
  • Docker官方镜像将会使用Alpine Linux替换Ubuntu
  • ​Windows Server 2016提供Docker原生运行的企业级支持
  • ​传统应用的docker化迁移
  • Docker携手Windows Server
  • Docker扁平化网络设计与实现
  • Plesk 中操作和设置 Docker 容器
  • 如何通过 Docker 在 Linux 上托管 .NET Core
  • Docker 1.12.4应用容器引擎发布及下载地址
  • Docker v1.13.0 应用容器引擎正式版发布及下载地址
  • docker源码分析之容器日志处理与log-driver实现
  • 如何在win7,win8下面启动docker
  • win7,win8安装Docker具体过程
  • win7, win8安装docker需要了解的概念
  • win7,win8安装docker的依赖条件
  • Docker Toolbox 介绍
  • Arch下面安装启动及删除docker介绍
  • Debian 7(Wheezy)下面如何安装docker
  • Debian 8(Jessie )下面如何安装docker
  • 红帽RHEL下如何删除docker详细步骤介绍
  • 红帽RHEL下面设置docker服务自动启动
  • linux下不使用sudo命令执行docker的操作步骤
  • 红帽redhat下通过脚本和yum安装docker容器引擎的详细步骤
  • 红帽RHEL下安装docker依赖性检查
  • Ubuntu Vivid 15.04 下面安装docker的详细步骤
  • Ubuntu Trusty 14.04 (LTS) 下面安装docker及依赖关系检查
  • Ubuntu Raring 13.04 和 Saucy 13.10 (64 bit)下面安装docker
  • Ubuntu Precise 12.04 (LTS) (64-bit)下面安装docker
  • Docker支持的安装方式
  • 通过docker ps命令检查运行中的docker镜像
  • 关于docker入门教程
  • 通过docker search命令搜索可用docker镜像
  • 在docker容器中运行hello world!
  • 在docker容器中通过apt-get安装新的程序
  • 通过docker commit命令保存对docker容器的修改
  • 通过docker run命令运行新的docker镜像
  • 准备学习docker: docker version命令查看版本
  • 什么是Docker?Docker通常用于如下场景
  •  
    当前位置:  教程>docker中文入门学习手册

    docker使用的技术之Container内核原理介绍

     
    分享到:
        发布时间:2017-2-20  


        本文导语: docker使用的技术之Container内核原理介绍虚拟化技术:VM与Container内容:namespacecgroupaufs两者对比namespace:进程组虚拟化的手段nsproxy相当于运行环境mnt ns提供私有的rootfspid ns映射后的pid空间net ns提供独立的网络栈每一个ns私有的网络...

    docker使用的技术Container内核原理介绍


    虚拟化技术:VM与Container

    内容
    namespace
    cgroup
    aufs
    两者对比


    namespace:进程组虚拟化的手段

    nsproxy相当于运行环境

    mnt ns提供私有rootfs

    pid ns映射后的pid空间

    net ns提供独立的网络

    每一个ns
    私有的网络设备
    lo, veth等虚设备
    物理网卡
    独立的协议
    ipv4, ipv6(含IP地址和路由表)
    tcp, sctp, dccp
    iptables规则
    ipvs等


    其他ns

    uts, ipc
    user ns
    C1的1001 id和C2的1001不是同一
    主要处理uid, gid, capabilities的虚拟化
    3.8版本提交;需要文件系统配合,目前不完善
    还有什么namespace没有实现?
    time, device, security keys, security

    namespace能做到什么?

    虚拟机,但资源无保证
    独立的mnt (chroot
    独立的pid空间
    独立的网络协议栈
    uts
    uid, gid
    ipc

    cgroup: 资源隔离和统计

    cgroup: 内存子系统接口

    cgroup: 内存子系统原理

    cgroup: CPU子系统接口

    cgroup: CPU子系统原理

    cgroup: 其它子系统


    namespace + cgroup能做到?

    aufs overview 

    aufs: 原理

    aufs: 有待完善

    Container VS VM: 内核是运行环境的一部分

    Container VS VM:应用场景

    docker Container内核原理 

    docker的两大核心基础技术是namespace和cgroup,cgroup主要作资源的限制隔离,它可以限制一组进程中能使用的最大资源使用量,相对

    比较好理解;namespace同样可以实现资源隔离,不同的是它是通过使PID,IPC,Network等系统资源不再是全局性的,而是属于特定的

    Namespace实现的。每个Namespace里面的资源对其他Namespace都是透明的,这个概念有点类似于Linux的多用户机制。

    namespace的详细介绍可以参考Introduction to Linux namespaces系列文章国内已经有人对这系列博文进行了翻译:linux namespace

    简介,本文接下来对namepace的介绍主要参考以上两篇博文。

    现在linux内核中支持的namespace主要有:

    Mount namespaces (CLONE_NEWNS)

    isolate the set of filesystem mount points seen by a group of processes. Thus, processes in different mount 

    namespaces can have different views of the filesystem hierarchy. With the addition of mount namespaces, the mount() 

    and umount() system calls ceased operating on a global set of mount points visible to all processes on the system and 

    instead performed operations that affected just the mount namespace associated with the calling process.

    UTS namespaces(CLONE_NEWUTS)

    isolate two system identifiersnodename and domainname—returned by the uname() system call; the names are set using 

    the sethostname() and setdomainname() system calls. In the context of containers, the UTS namespaces feature allows 

    each container to have its own hostname and NIS domain name. This can be useful for initialization and configuration 

    scripts that tailor their actions based on these names. The term “UTS” derives from the name of the structure passed 

    to the uname() system call: struct utsname. The name of that structure in turn derives from “UNIX Time-sharing 

    System”

    IPC namespaces (CLONE_NEWIPC)

    isolate certain interprocess communication (IPC) resources, namely, System V IPC objects and (since Linux 2.6.30) 

    POSIX message queues. The common characteristic of these IPC mechanisms is that IPC objects are identified by 

    mechanisms other than filesystem pathnames. Each IPC namespace has its own set of System V IPC identifiers and its 

    own POSIX message queue filesystem.

    PID namespaces (CLONE_NEWPID, Linux 2.6.24)

    isolate the process ID number space. In other words, processes in different PID namespaces can have the same PID. One 

    of the main benefits of PID namespaces is that containers can be migrated between hosts while keeping the same 

    process IDs for the processes inside the container. PID namespaces also allow each container to have its own init 

    (PID 1), the “ancestor of all processes” that manages various system initialization tasks and reaps orphaned child 

    processes when they terminate.

    Network namespaces (CLONE_NEWNET, started in Linux 2.4.19 2.6.24 and largely completed by about Linux 2.6.29)

    provide isolation of the system resources associated with networking. Thus, each network namespace has its own 

    network devices, ip addresses, ip routing tables, /proc/net directory, port numbers, and so on.network namespaces 

    make containers useful from a networking perspective: each container can have its own (virtual) network device and 

    its own applications that bind to the per-namespace port number space; suitable routing rules in the host system can 

    direct network packets to the network device associated with a specific container. Thus, for example, it is possible 

    to have multiple containerized web servers on the same host system, with each server bound to port 80 in its (per-

    container) network namespace.

    User namespaces (CLONE_NEWUSER, started in Linux 2.6.23 and completed in Linux 3.8)

    isolate the user and group ID number spaces. In other words, a process’s user and group IDs can be different inside 

    and outside a user namespace. The most interesting case here is that a process can have a normal unprivileged user ID 

    outside a user namespace while at the same time having a user ID of 0 inside the namespace. This means that the 

    process has full root privileges for operations inside the user namespace, but is unprivileged for operations outside 

    the namespace.

    在这篇博文中,将主要介绍PID namespace和mount namepace。通过这两个namespace模拟docker在基础文件系统中运行的原理。我们将利

    busybox建立一个可以满足linux系统运行的基础环境,并且通过chroot切换根目录,实现环境隔离。

    利用chroot和busybox实现文件系统隔离

    chroot可以实现根路径的切换,但如果新的根路径环境下没有基础库程序(比如bash),那么chroot将不能正常切换根路径。busybox提

    供了能保证linux系统正常运行的基础工具(如bash、ls等命令工具),我们可以利用chroot+busybox在我们本地系统中建立一个新的沙箱

    系统(当然此时并没有名字空间的隔离,只是根文件系统实现了隔离)。

    首先从官方下载busybox的源码,这里我使用的是1.22版本。解压后直接使用默认配置,然后运行make,make install

    [root@localhost busybox-1.22.1]# make defconfig #使用默认配置

    [root@localhost busybox-1.22.1]# make

    [root@localhost busybox-1.22.1]# make install

    一切顺利的话,系统会在当前路径下生成一个_install文件夹。


    [root@localhost busybox-1.22.1] cd _install

    [root@localhost _install]#ls

    bin  linuxrc  sbin  usr

    _install 文件夹中包含了许多基础工具


    [root@localhost _install]# cd bin

    [root@localhost bin]# ls

    ash      chgrp   cttyhack       dumpkmap  fgrep   hostname  kill     lsattr    more     netstat        printenv   

    rmdir         setserial  sync    usleep

    base64   chmod   date           echo      fsync   hush      linux32  lzop      mount       nice           ps      

    rpm           sh         tar     vi

    busybox  chown   dd             ed        getopt  ionice    linux64  makemime  mountpoint  pidof          pwd       

    run-parts     sleep      touch   watch

    cat      conspy  df             egrep     grep    iostat    ln       mkdir     mpstat      ping           reformime  

    scriptreplay  stat       true    zcat

    catv     cp      dmesg          false     gunzip  ipcalc    login    mknod     mt          ping6          rev        

    sed           stty       umount

    chattr   cpio    dnsdomainname  fdflush   gzip    kbd_mode  ls       mktemp    mv          pipe_progress  rm      

    setarch       su         uname

    返回_install路径,尝试进行chroot

    [root@localhost bin]# cd ..

    [root@localhost _install]# chroot . /bin/ash

    chroot: failed to run command ‘/bin/ash’: No such file or directory

    [root@localhost _install]#

    这里提示没有找到/bin/ash,但实际上bin文件夹的ash是存在的。这里主要原因是切换根路径后,系统无法找到busybox依赖的动态链接

    库,busybox无法正常工作。先看一下busybox依赖的库

    [root@localhost _install]# ldd /bin/busybox 

    linux-vdso.so.1 =>  (0x00007fff415fa000)

    libm.so.6 => /lib64/libm.so.6 (0x00007f53f4926000)

    libc.so.6 => /lib64/libc.so.6 (0x00007f53f4565000)

    /lib64/ld-linux-x86-64.so.2 (0x00007f53f4c3d000)

    [root@localhost _install]# mkdir lib64

    [root@localhost _install]# cp /lib64/libm.so.6 ./lib64/

    [root@localhost _install]# cp /lib64/libc.so.6 ./lib64/

    [root@localhost _install]# cp /lib64/ld-linux-x86-64.so.2 ./lib64

    [root@localhost _install]# chroot . /bin/ash

    / # ls

    bin      lib64    linuxrc  sbin     usr

    / #

    从11行起可以看出chroot已经成功完成根路径切换,现在运行在busybox搭建的根路径环境下。

    但实际上现在根路径并不是完整的,可以看出busybox搭建的根文件系统并没有/proc和/dev等目录,在该环境下允许top指令并不能正常允

    许。接下来是namespace发挥作用的时候了。

    namespace隔离

    以下内容主要来源于linux namespace简介系列文章。这里我们直接使用文中的测试代码。

    //namespace.c

    #define _GNU_SOURCE

    #include <sys/types.h>

    #include <sys/wait.h>

    #include <sys/mount.h>

    #include <stdio.h>

    #include <sched.h>

    #include <signal.h>

    #include <unistd.h>

    #define STACK_SIZE (1024 * 1024)

    // sync primitive

    int checkpoint[2];

    static char child_stack[STACK_SIZE];

    char* const child_args[] = {

      "/bin/bash",

      NULL

    };

    int child_main(void* arg) {

      char c;

      // init sync primitive

      close(checkpoint[1]);

      // setup hostname

      printf(" - [%5d] World ! ", getpid());

      sethostname("In Namespace", 12);

      // wait...

      read(checkpoint[0], &c, 1);

      execv(child_args[0], child_args);

      printf("Ooops ");

      return 1;

    }

    int main() {

      // init sync primitive

      pipe(checkpoint);

      printf(" - [%5d] Hello ? ", getpid());

      int child_pid = clone(child_main, child_stack+STACK_SIZE,

          CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL);

      // further init here (nothing yet)

      // signal "done"

      close(checkpoint[1]);

      waitpid(child_pid, NULL, 0);

      return 0;

    }

    编译namespace.c,建立一个proc的空文件夹

    [root@localhost _install]# mkdir proc

    [root@localhost _install]# gcc namespace.c -o ns

    [root@localhost _install]#

    执行ns进入新的名字空间,chroot将根目录切换到当前目录下。

    [root@localhost _install]# ./ns

     - [14649] Hello ?

     - [    1] World !

    [root@In Namespace _install]# chroot . /bin/ash

    / # 

    / # ps #这个ps没有获得任何进程数据,因为当前/proc为空文件夹

    PID   USER     TIME   COMMAND

    / # mount -t proc proc /proc #将当前名字空间的proc文件系统挂在到/proc

    / # ps #获得当前名字空间的进程数据

    PID   USER     TIME   COMMAND

        1 0          0:00 /bin/bash

       30 0          0:00 /bin/ash

       33 0          0:00 ps

    / #

    现在在当前根路径下已经基本实现了名字空间的隔离和文件系统的隔离,一个沙箱系统的雏形已经实现。docker的运行的基础原理也大致如此,不过现在还没有添加进cgroup。

    busybox 基础镜像制作

    现在考虑将当前的busybox环境打成一个基础镜像。

    [root@localhost _install]# tar --numeric-owner -cvf  ../BusyBox-test.tar ./

    注意,此时的BusyBox-test.tar文件只是一个tar包,里面缺乏docker需要的一些json文件和目录,并不能直接用docker load倒入。


    [root@localhost busybox-1.22.1]# docker load < BusyBox-test.tar

    2015/01/09 13:01:51 Error: open /var/lib/docker/tmp/docker-import-114653123/repo/bin/json: no such file or directory

    [root@localhost busybox-1.22.1]#

    可以使用以下指令导入镜像

    [root@localhost busybox-1.22.1]# cat BusyBox-test.tar | docker import - busyboxtest

    3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a

    [root@localhost busybox-1.22.1]# docker images

    REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

    busyboxtest         latest              3341f4c8d832        19 minutes ago      4.241 MB

    centos              7                   8efe422e6104        3 days ago          224 MB

    centos              centos7             8efe422e6104        3 days ago          224 MB

    centos              latest              8efe422e6104        3 days ago          224 MB

    busybox             buildroot-2014.02   4986bf8c1536        8 days ago          2.433 MB

    busybox             latest              4986bf8c1536        8 days ago          2.433 MB

    运行docker,查看镜像是否能正常运行。

    [root@localhost busybox-1.22.1]# docker run -it  busyboxtest /bin/sh

    / # ls

    bin  dev etc lib64  linuxrc namespace.c  ns  proc   sbin    sys  usr

    / #

    可以看出镜像能正常运行。将busyboxtest镜像导出,看镜像文件和简单的tar文件有何不同。

    [root@localhost _install]# docker save busyboxtest > busyboxtest-img.tar

    [root@localhost _install]# ls

    bin  lib64  linuxrc  busyboxtest-img.tar  namespace.c  ns  proc  sbin  usr

    [root@localhost _install]# mkdir img

    [root@localhost _install]# cp busyboxtest-img.tar img

    [root@localhost _install]# cd img

    [root@localhost img]# ls

    busyboxtest-img.tar

    [root@localhost img]# tar xvf busyboxtest-img.tar 

    3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a/

    3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a/VERSION

    3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a/json

    3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a/layer.tar

    repositories

    在镜像文件夹中,layer实际上就是我们打包的tar文件。docker import进tar文件后对tar文件进行了一些处理,方便docker对镜像文件进行管理

    接下来我们对busyboxtest进行修改,往根目录里添加一个文本文件,并将修改后的镜像命名为busyboxtest:v1,解压镜像文件后看文件夹里的内容

    [root@localhost img2]# tar xvf busyboxtestv1.tar 

    3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a/

    3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a/VERSION

    3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a/json

    3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a/layer.tar

    8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653/

    8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653/VERSION

    8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653/json

    8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653/layer.tar

    repositories

    [root@localhost img2]# tree.

    |-- 3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a

    |   |-- json

    |   |-- layer.tar

    |   `-- VERSION

    |-- 8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653

    |   |-- json

    |   |-- layer.tar

    |   `-- VERSION

    |-- busyboxtestv1.tar

    `-- repositories

    [root@localhost img2]# tree

    .

    |-- 3341f4c8d8326866a15099dd09cff11d3f09c07d50c4d0dec9930b26dfa11b2a

    |   |-- json

    |   |-- layer.tar

    |   `-- VERSION

    |-- 8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653

    |   |-- json

    |   |-- layer.tar

    |   `-- VERSION

    |-- busyboxtestv1.tar

    `-- repositories

    2 directories, 8 files

    [root@localhost img2]#

    3341f…这个文件夹保存的是未修改的镜像信息,8d24…文件保存的是修改信息,它只保存和基础镜像的diff信息,具体存储在该文件夹的layer.tar文件。解压8d24…文件夹的layer.tar文件

    [root@localhost 8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653]# ls

    json  layer.tar  VERSION

    [root@localhost 8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653]# tar xvf layer.tar 

    .ash_history

    img_test_file

    [root@localhost 8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653]# ls

    img_test_file  json  layer.tar  VERSION

    [root@localhost 8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653]#

    可以看出里面多了一个img_test_file文件,这个正是我们在基础镜像里添加的文件。.ash_history保存的是命令执行历史记录:

    [root@localhost 8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653]# cat .ash_history 

    ls

    vi img_test_file

    ls

    exit

    [root@localhost 8d24158476ecbdea530dc210bda9b60970dd809d10a914ae19c83e8359396653]#

    docker可以根据这个diff信息构建出新的工作环境。

    总结

    docker实现资源隔离的两大linux基础技术是:namespace和cgroup。并且通过chroot实现运行的根目录环境切换。在这篇博文中主要简单模拟了docker的namespace和chroot工作流程,并且介绍了制作基础镜像的过程。本篇博文只是很概要的模拟docker工作原理,具体的详细流

    程需要继续分析docker的源码。

      您可能感兴趣的文章:

    • 本站(WWW.169IT.COM)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
      本站(WWW.169IT.COM)站内文章除注明原创外,均为转载,整理或搜集自网络.欢迎任何形式的转载,转载请注明出处.
      转载请注明:文章转载自:[169IT-IT技术资讯]
      本文标题:docker使用的技术之Container内核原理介绍
    相关文章推荐:


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2017,169IT.COM,E-mail:www_169it_com#163.com(请将#改为@)

    浙ICP备11055608号