Docker架构

2022/03/14 Docker

Docker架构

先天下之忧而忧,后天下之乐而乐。——范仲淹《岳阳楼记》

Docker的组件

在Docker体系结构中,最重要的组件有三个,分别是Docker Daemon、Docker Image(镜像)和Docker Container(容器)。

而这三个组件中,Docker Daemon是负责维护Docker运行的守护进程,担负着资源管理、任务调度等多项功能。而Docker Image则属于静态文件系统。最后的Docker Container是基于Image真正提供应用服务的计算单元。

因此这三者的关系可以说是,Container基于Image被Daemon创建和管理,来实现提供服务的功能。也正因为Container负责提供服务,所以处于核心位置。因而当我们谈论到Docker生命周期时,更多的指的是Docker Container的生命周期。

Docker的生命周期

Docker Container的生命周期以创建为起点。Docker创建一个容器有两种途径:Create和Run。这两个命令都会创建一个容器,这两个命令最终的效果有所不同。使用Create创建的容器状态为Stopped,而使用Run创建的容器状态为Running。这是因为Create命令只会创建此容器所需要的文件系统,而不会给其分配运行资源,也就是不会分配CPU、Memory、Network和Process。只有在明确对此容器调用Start命令之后,Docker Daemon才会按照配置参数给其分配相应的运行资源,而这时此容器就会处于Running状态。 Run命令会连续调用Create和Start命令,对目标容器创建文件系统和分配运行资源。

容器会从Running状态转换到Stopped状态。此种状态转移分为两种情况:正常关闭和异常关闭。

  • 正常关闭指的是用户调用Kill命令或者Stop命令,通过Docker Daemon对正在运行的容器进行资源回收。经过Docker Daemon的资源回收之后,此容器所有内存中的数据都会被销毁,但其文件系统仍然存在。此时的状态与使用Create命令之后的效果相比,只是文件系统多了一部分数据。此后仍然可以通过Start再度启动,将状态转换至Running状态。
  • 异常关闭发生的原因有很多,在实际运行当中主要有以下两种情况。
    • OOM(内存溢出) 为了保持主机环境和Docker中各个容器的运行稳定性,Docker在处理OOM事件时采取了“熔断器”和“耐压舱”的处理机制。 如果容器中的应用耗尽了主机系统分配给容器的内存限额,就会触发OOM事件。例如,在容器当中,部署了一个python脚本来统计文本中单词出现的频率。假设主机分配给此容器的内存上限为500MB,当脚本申请的内存大于500MB时,此容器就会触发OOM事件。而在这种情况下,此容器将会被强制关闭。 但需要注意的是,此时关闭容器的并非是Docker Daemon,而是宿主机操作系统。因为一个容器其实就是一组运行在宿主机操作系统当中的进程,宿主机操作系统通过cgroups对这组进程设定资源上限,当这些进程申请的资源到达上限时,触发的是宿主机操作系统的内核OOM事件,因此最终是由宿主机内核来关闭这些进程,这就是“熔断器”机制。只要目标达到一个阀值就销毁它,以免情况恶化。 如果用户不想关闭这个容器,那么可以选择–oom-kill-disable来禁用OOM-Killer。使用此参数时,仍需要注意,如果使用-m设置了此容器内存上限,那么当容器到达内存资源上限时,主机不会关闭容器,但也不会继续向此容器继续分配资源,此时容器将处于hung状态,这种机制就是“耐压舱”。只需要将最坏的情况封闭在一定范围之内,而不至于蔓延出去。 如果用户使用了–oom-kill-disable,但也没有使用-m来设定上限,因而此时此容器将会尽可能多地使用主机内存资源。换言之,主机内存有多大,它就将用多大。
    • 进程意外退出 每个容器内部都存在一个Init进程,容器中其他所有进程都是此进程的子进程。一个容器运行不退出,表现在主机系统上面就是容器当中的Init进程和其子进程处于运行状态。 如果一个子进程因为某种原因造成了退出,那么其父进程也会同步退出,直至Init进程也退出。当Init进程退出时,也就代表着此容器被关闭。 与OOM不同,Docker目前没有任何机制可以监测到此时的进程退出属于正常退出还是异常退出。 但无论是正常关闭还是异常关闭,此容器的状态都会转换到Stopped。当出现容器关闭情况时,Docker Daemon会尝试再次重新将此容器由Stopped状态转为Running状态。当然不是所有的容器出现关闭时,都会有此待遇。只有设置了–restart参数的容器,Docker Daemon才会特别留意。 而在Docker容器的生命周期中,除了Running态和Stopped态之外,还有另外一种状态:Paused状态。 处于此种状态的容器,看似存在却无法做任何事情。究其原因,是Docker“剥夺”了此容器的CPU资源。而其他资源,如Memory资源、Network资源等还保留未动。如此一来,失去了CPU资源的进程,是不会被主机内核系统所调度的,所以此容器就处于“冰封”状态。 而为其解封的方式非常容易,重新赋予其CPU资源就可以。

因此,一个容器完整的生命周期就是在Running→Paused→Stopped三种状态之间相互转换。而是否具有运行资源就是区分容器状态的唯一标准。 归根结底,Docker管理容器的过程就是Docker重新分配主机资源的过程,而主掌资源分配大权的角色就是Docker Daemon。

Search

    微信好友

    博士的沙漏

    Table of Contents