Docker从精通到入门(一)----Docker的大致架构

########本系列无运维实践########
####想看运维相关建议直接划走####
##系列是基于Go源码浅层分析,不涉及进一步的编译##


#####Docker 1.2
(docker-ce集成了Client和Daemon,因为暂时找不到基于docker-ce的完整分析,所以文章夹带了大量作者的个人理解)
(最新版本的Docker-ce 不再将Client和Daemon集合到一个项目中,而是分散在了两个项目)
(最新版本的Clinent:https://github.com/docker/cli)
(最新版本的Daemon/engine:https://github.com/moby/moby)


一、Docker的模块
    · Docker Client
        用户通过Client与Daemon建立连接。
    · Docker Daemon
        1. 具备服务端的功能,有能力接收Docker Client发起的请求;
        2. 具备Docer Client请求的处理能力;
        3. Docker Daemon内部的所有任务都由Engine来完成,每一项工作都以一个Job的形式存在。
    · Docker Registry
    · Graph
    · Driver
    · libcontainer
    · Docker Container


二、Docker Client   (用户端)
    1. 是Docker架构中用户与Docker Daemon建立通信的客户端;
        在一台安装有Docker的机器上用户可以使用可执行文件 docker 作为Client,向众多容器发起请求。
    
    2. Docker Client可以通过三种方法和Daemon建立通信,分别为:
        tcp: //host:port 、unix: //path_to_socket 和fd: //socketfd。
        通信方式确定后,Client与Daemon建立连接并传输请求时,
        可以通过命令行flag参数的形式,设置TLS的有关参数,保证传输的安全性
    
    3. Client发送容器管理请求后,请求由Docker Daemon接收并处理,
        当Docker Client接收返回的请求响应并做简单处理后,Docker Client一次完整的生命周期就此结束。
        若需要继续发送容器管理的请求,用户必须再次通过 docker创建Client


三、Docker Daemon   (server端?)
    1. Daemon是Docker架构中一个常驻在后台的系统进程;运行Docker就是运行Docker Daemon建立通信的客户端;
        Daemon的作用主要有:
            a. 接收并处理Docker Client发送的请求;
            b. 管理所有的Docker容器。
    
    2. Daemon运行时,会在后台启动一个server,server负责接收Client发送的请求;
        接受请求后,Sever通过路由和方法调度,找到相应的Handler来处理请求。
    
    3. 启动Daemon所使用的可执行文件也是docker。
        通过传入的参数可以辨别Client还是Daemon,如docker -d代表Daemon的启动,docker ps则代表创建Client并发送ps请求;

    4. Daemon的架构大致可以分为 Sever、Engine、Job/Api:
        · Docker Sever:
            a. Docker Sever在Docker架构中专门服务Docker Client,
                它的功能是接收并调度分发Docker Client发送的请求。

            b. 在Daemon的启动过程中,Server第一个完成。
                Server通过gorilla/mux创建了一个mux.Router路由,提供请求的路由功能。
                  (gorilla/mux 是一个强大的URL路由器以及调度分发器)
                创建Router之后,Sever为mux.Router中添加有效的的路由项,
                每一个路由项由HTTP请求方法(PUT、POST、GET或DELETE)、URL和Handle三部分组成
            
            c. 由于Client通过HTTP协议访问Daemon,所以Server创建完mux.Router之后,
                将Server的监听地址以及mux.Router作为参数,创建一个httpSrv=http.Server{}开始服务外部请求。
            
            d. 在服务过程中,Server在listener上接收Client的访问请求。
                对于每一个请求Server都会创建一个全新的goroutine来服务;
                在goroutine中,Docker Server首先读取请求内容,然后做请求解析工作,
                接着匹配相应的路由项,随后调用相应的Handle来处理,随后Handle处理完请求之后给Client恢复响应。
            
            注意点:Docker Server在Docker的启动过程中运行,通过一个名为 "serveapi"的Job来实现。
                Docker Server实际上只是众多Job的一个,但是为了强调server的重要性以及它为后续Job服务的重要特性,把"serveapi"拿出来单独作为Docker Server来讲;
                (components\engine\api\server\server.go)
        
        · Docker Engine:
            a. Engine是Docker架构中的运行引擎,同时也是Docker运行的核心模块。
                Engine存储着大量的容器信息,同时管理着Docker的大部分Job的执行。
                Docker中的大部分任务执行都需要Engine协助,并且通过Engine匹配相应的Job完成Job的执行。
            
            b. 在Docker源码中,Engine的数据结构里有一个名为handles的字段;
                该字段存储的是关于众多特定Job各自处理的方式handle。     (在docker-ce 18.09中叫做customHTTPHeaders,找半天。。。)
                即用一个map结构存储string结构的handlename和handle的对应关系。
            
            c. 除了容器之外,Engine还接管Docker Daemon中的某些特定任务;
                当Docker Daemon遭遇到滋生进程需要退出的情况,Engine还负责完成Docker Daemon的退出善后工作。
        
        · Job:
            a. Job可以认为是Docker架构中Engine内部最基本的工作单元;
                Docker Daemon可以完成的每一项任务都可以认为是一个Job;
                例如,在Docker容器中运行一个进程,这是一个Job;/
                      创建一个新的容器,这是一个Job;/
                      在网络上下载一个文档,这是一个Job;/
                      包括之前Docker Server,创建Sever服务于HTTP协议的API也是一个Job
                (个人认为,Job是为了抽象化Engine的工作设置的一个概念,方便管理和调用)

            b. 有关于Job接口的设计,与UNIX进程非常相仿;
                比如说Job有一个名称,运行时有参数,有环境变量,有标准输入和标准输出还有返回状态 
                (从这里可以看出容器技术和操作系统的相似性,希望可以从中获得操作系统的相关知识,discovery learning)
            
            c. 对于Job而言,定义完毕之后,运行才能完成Job自身真正的使命;
                Job的运行函数Run()则用以执行Job本身


四、Docker Registry (镜像库)
    1. Dokcer Registry是以一个存储容器镜像(Docker Image)的仓库;
        Image是容器创建时用来初始化容器rootfs的文件系统内容;
        Registry将大量的容器汇集在一起,并为分散的Docker Daemon提供镜像服务;
        (根据Image和容器的描述,感觉就像 Class和Object之间的关系一样)
    
    2. Docker的运行过程,有三种情况可能会与Registry通信,分别为搜索镜像、下载镜像、上传镜像;
        这三种情况所对应的Job名称分别为search、pull和push。     (使用过docker的人应该很熟悉吧hahah)
    
    3. 不同场景下,Daemon可以使用不同的Registry下载Image。
        公有Registry:Docker Hub    (公用云平台呗....说这么高深)
        私有Registry:构建本地私有Registry,使容器获取可以在内网完成    (不用我说也应该知道吧..)


五、Graph   (存储镜像)
    1. Graph在Docker架构中扮演的角色是Image的保管者;不管是Docker创建的Image还是下载的Image,都由Graph统一保管;

    2. Docker支持多种不同的Image存储方式,如aufs、device mapper、btrfs等,所以Graph把同一种类型的Image成为一个repository;
        一个repository下的Image按照不同的tag区分。


六、Driver  (驱动)
    1. Driver是Docker架构中的驱动模块;
        通过Driver驱动,Docker可以实现对Docker容器运行环境的定制,定制的维度有网络环境、存储方式、执行方式等等;
        在Docker运行的生命周期中,并非用户所有的操作都是正对Docker容器的管理,包括user堆Docker运行信息的获取、对Graph的存储、记录等;
        为了将仅与Docker容器相关的管理从Dokcer Daemon的所有逻辑中区分开,设计了Driver来抽象不同类比各自的功能范畴。

    2. Docker Driver的实现可以分为 graphdriver、networkdriver、execdriver三类驱动:
        · graphdriver:
            a. graphdriver用于完成容器存储的管理,包括从远程Docker Registry下载镜像并存储,也包括本地镜像构建后的存储。
                当user下载只当的Image,graphdrive将Image分层存储在本地的指定目录下;
                当user需要使用指定的Image来创建容器时,graphdrive从本地Image存储目录中获取指定的Image,并按照特定的规则准备rootfs;
                当user需要通过Dockerfile构建新的Image,graphdrive会负责newImage的存储管理。
            
            b. 当graphdrive的初始化过程之前,有4种文件系统或类文件系统的驱动在Docker Daemon中注册,分别为aufs、btrfs、devicemapper、vfs;
                其中aufs、btrfd以及devicemapper用于Image的管理,vfs用于volume(文件系统)的管理;
                Docker在初始化时,优先通过获取系统环境变量"DOCKER_DRVICE"来提取所使用driver的指定类型。
                因此,之后所有的Graph操作,都使用该driver来执行。
            
        · networkdriver:
            networkdriver的作用是完成Docker容器网络环境的配置,其中包括Docker Daemon启动时为Docker环境创建网桥;
            Docker容器创建前为其分配相应的网络接口资源,以及为Docker容器分配IP、端口并与宿主机做NAT端口映射,设置容器防火墙策略等;
        
        · execdrvice:
            execdrvice作为Docker容器的执行驱动,负责创建容器运行时的命名空间,负责容器资源使用的统计和限制,负责容器内部进程的真正运行;
            

七、libcontainer    (调用操作系统API,个人认为是容器开发的核心)
    1. libcontainer是Docker架构中一个使用Go语言设计实现的库,
        设计初衷是希望库可以不依靠任何依赖,直接访问内核中容器相关的系统调用;

    2. 正是因为libcontainer的存在,Driver可以直接调用libcontainer,
        而最终操作容器的namespace、cgroup、apparmor、网络设备以及防火墙规则等;
        这一系列操作在libcontainer的支持下,都不需要LXC或者其他包;

    3. libcontainer提供了一整套标准的接口来满足上层对容器管理的需求;
        或者说,容器屏蔽了Docker上层对容器的直接管理;
        libcontainer承接Linux内核和Docker Daemon。
    

八、Docker Container    (Docker 容器)
    1. Docker container是Docker架构中服务交付的最后体现形式;
    
    2. Docker通过Docker Deamon的管理,libcontainer的执行,最终创建Docker容器;
    
    3. Docker容器,功能类似于虚拟机,具备资源受限、环境与外界隔离的特点;
        但是手段和KVM、Xen等传统虚拟化技术大相径庭。
    
    4. Docker容器可以根据用户自己的需求,通过Client向Daemon发送容器的创建与启动请求;
        请求中携带容器的配置信息,从而达到定制相应的Docker容器的目的。
    
    5. user对Docker Containner的配置有以下几点:
        · 通过指定容器镜像,使Docker容器可以自定义rootfs等文件系统;                (graphdriver)
        · 通过指定物理资源分配,如CPU、内存等,使得Docker容器使用受限的物理资源;  (execdrvice)
        · 通过配置容器网络及其安全策略,使得Docke容器拥有独立且安全的网络环境;     (networkdriver)
        · 通过执行容器运行命令,使得Docker容器执行指定的任务                        (execdrvice)


九、Docker常见指令分析
    1. Docker pull  (获取镜像)  
        docker pull 的作用是 Docker Daemon从Docker Registry中下载指定的Image;
          并将Image存储到Graph中
        
        · CLient处理docker pull命令,解析完请求和参数之后,
          向Docker Sever发起一个POST请求获取对应的Image
        
        · Docker Sever收到请求,将请求交给mux.Router,mux.Router根据请求方式和URL来确定执行的handle

        · mux.Router将请求路由发给相应的handle  (PostImageCreate)
        
        · PostImageCreate创建一个pull的Job,之后触发这个Job

        · pull在执行过程中从Docker Registry中下载指定的Image;
        
        · pull将Image交给graphdrive存储在Graph;

    
    2. Docker run   (创建容器)
        docker run 的作用是创建一个新的docker容器;
            创建Docker Container对象,并为容器准备rootfs;
            创建Docker Container的运行环境;

        · CLient处理docker run命令,解析完请求语言与参数之后,向Docker Server发送一个HTTP请求,
            HTTP请求方法为POST,希望创建一个Docker容器对象;
        
        · Docker Server接收以上的请求,交给mux.Router,mux.Router通过URL以及请求方法找到对应的handle;

        · mux.Router将请求路由分发给对应的handle    (PostContainerCreate)

        · PostContainCreate创建并初始化了一个create的Job,之后执行这个Job

        · create执行过程中通过graphdevice找到创建容器rootfs需要的Images;

        · graphdriver将Images加载到Docker容器对应的文件目录下

        · Client收到Server成功执行的返回后,发起第二次POST请求,创建容器对象;
        
        · Docker Server接收以上的请求,交给mux.Router,mux.Router通过URL以及请求方法找到对应的handle;

        · mux.Router将请求路由分发给对应的handle    (PostContainerStart)

        · PostContainerStart创建并初始化了一个start的Job,之后执行这个Job;

        · start执行之前调用networkdevice为容器配置网络资源  (设置IP、Port、设置防火墙规则...)
        
        · start开始执行用户指令 调用execdriver;
        
        · execdriver被调用,开始初始化Docker Container内部的运行环境,如命名空间、资源控制、用户命令执行,转交给libcontainer来完成;

        · libcontainer被调用,执行结束

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值