容器和Docker

一、容器

1、虚拟机和容器的区别

(1)为什么要用docker

服务器端开发/部署:

 实现更轻量级的虚拟化,方便快速部署, 对于部署来说可以极大的减少部署的时间成本和人力成本

 Docker支持将应用打包进一个可以移植的容器中,重新定义了应用开发,测试,部署上线的过程,核心理念就是 Build once, Run anywhere。典型应用场景是开发运维上提供持续集成和持续部署的服务

1)标准化应用发布,docker容器包含了运行环境和可执行程序,可以跨平台和主机使用;

2)节约时间,快速部署和启动,VM启动一般是分钟级,docker容器启动是秒级;

3)方便构建基于SOA架构或微服务架构的系统,通过服务编排,更好的松耦合;

4)节约成本,以前一个虚拟机至少需要几个G的磁盘空间,docker容器可以减少到MB级;

5)方便持续集成,通过与代码进行关联使持续集成非常方便;

6)可以作为集群系统的轻量主机或节点,在IaaS平台上,已经出现了CaaS,通过容器替代原来的主机。

docker 优势:

1)交付物标准化

Docker是软件工程领域的“标准化”交付组件,最恰到好处的类比是“集装箱”。

集装箱将零散、不易搬运的大量物品封装成一个整体,集装箱更重要的意义在于它提供了一种通用的封装货物的标准,卡车、火车、货轮、桥吊等运输或搬运工具采用此标准,隧道、桥梁等也采用此标准。以集装箱为中心的标准化设计大大提高了物流体系的运行效率。

传统的软件交付物包括:应用程序、依赖软件安装包、配置说明文档、安装文档、上线文档等非标准化组件。Docker的标准化交付物称为“镜像”,它包含了应用程序及其所依赖的运行环境,大大简化了应用交付的模式。


2)一次构建,多次交付

类似于集装箱的“一次装箱,多次运输”,Docker镜像可以做到“一次构建,多次交付”。当涉及到应用程序多副本部署或者应用程序迁移时,更能体现Docker的价值。


3)应用隔离

沙盒技术:集装箱可以有效做到货物之间的隔离,使化学物品和食品可以堆砌在一起运输。Docker可以隔离不同应用程序之间的相互影响,但是比虚拟机成本更小。

(2)物理机、虚拟机以及容器的通俗定义

物理机:一栋楼一户人家、有自己独立的地基、还有自己独立的花园

虚拟机:一栋楼包含多套房(多户人家)、但是地基是共享、花园也是共享的,只有独立的卫生间、厨房、宽带;

容器:一套房隔成多个小隔间(比如:胶囊式公寓)、每个小隔间一位租户、共享的地基、共享的花园、还共享卫生间、厨房以及宽带。

容器虚拟化的是操作系统而不是硬件,容器之间是共享同一套操作系统资源的;虚拟机技术是虚拟一套硬件后,在其上运行一个完整的操作系统。因此容器的隔离级别会稍低一些。

(3)虚拟机和容器的区别

容器和虚拟机具有相似的资源隔离和分配优势,但功能有所不同,因为容器虚拟化的是操作系统,而不是硬件,因此容器更容易移植,效率也更高。

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。

 

  • 容器是一个应用层抽象,用于将代码和依赖资源打包在一起。多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行 。与虚拟机相比, 容器占用的空间较少(容器镜像大小通常只有几十兆),瞬间就能完成启动 。
  • 虚拟机 (VM) 是一个物理硬件层抽象,用于将一台服务器变成多台服务器。 管理程序允许多个 VM 在一台机器上运行。每个VM都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此 占用大量空间 。而且 VM 启动也十分缓慢 。
  • 虚拟机更擅长于彻底隔离整个运行环境。例如,云服务提供商通常采用虚拟机技术隔离不同的用户。而 Docker通常用于隔离不同的应用 ,例如前端,后端以及数据库。

(4)容器与虚拟机(VM)两者是可以共存的

(5)生态概览

  1)OCI

OCI(Open Container Initiative)致力于建立一个容器运行时和镜像格式的规范,其核心目的在于避免容器生态的分化,确保在不同容器引擎上构建的容器可以相互兼容。这是容器可移植性的根本保证。

OCI的runtime spec标准中对于容器的状态描述,以及对于容器的创建、删除、查看等操作进行了定义。

  • runtime spec

OCI Runtime Specification,主要定义如何container配置、执行环境以及container生命周期。

  • image spec

OCI Image Format Specification,主要定义一个OCI image由一个manifest, 一个image index (optional), 一组filesystem layers, 以及一个configuration组成。该规范的目的在于确保能构建一套不同容器引擎间可互操作的工具,用于镜像的构建、传输,以及镜像运行准备工作。

  2)runC  

在早期的Docker Engine中,主要用LXC工具来运行和管理容器;后来采用自研的libcontainer来做这类事情,libcontainer直接使用Linux内核提供的相关隔离技术,比如cgroups、namespace等等。

runC是一个轻量级的工具,做且只做一件事情,那就是运行一个容器。由libcontainer演变而来,并且由Docker捐献给Linux基金会,作为OCI的参考实现,可以用于创建和运行容器的CLI(command-line interface)工具。

runc直接与容器所依赖的cgroup/linux kernel等进行交互,负责为容器配置cgroup/namespace等启动容器所需的环境,创建启动容器的相关进程。runC基本上就是一个命令行小工具,它可以不用通过Docker引擎,直接就可以创建容器。这是一个独立的二进制文件,使用OCI容器就可以运行它。
 
 3)containerd

Docker 1.11的Docker Engine里就包含了containerd,而现在则是把containerd从Docker Engine里彻底剥离出来,作为一个独立的开源项目独立发展,目标是提供一个更加开放、稳定的容器运行基础设施。和原先包含在Docker Engine里containerd相比,独立的containerd将具有更多的功能,可以涵盖整个容器运行时管理的所有需求。

containerd并不是直接面向最终用户的,而是主要用于集成到更上层的系统里,比如Swarm, Kubernetes, Mesos等容器编排系统。containerd以Daemon的形式运行在系统上,通过unix domain docket暴露很低层的gRPC API,上层系统可以通过这些API管理机器上的容器。每个containerd只负责一台机器,Pull镜像,对容器的操作(启动、停止等),网络,存储都是由containerd完成。具体运行容器由runC负责,实际上只要是符合OCI规范的容器都可以支持。

containerd 是一个守护进程,它可以使用runC管理容器,并使用gRPC暴露容器的其他功能。相比较Docker引擎,使用 gRPC ,containerd暴露出针对容器的增删改查的接口,Docker engine调用这些接口完成对于容器的操作。
  
  4)CRI(容器运行时的接口)

CRI中定义了容器和镜像的服务的接口,因为容器运行时与镜像的生命周期是彼此隔离的,因此需要定义两个服务,该接口使用Protocol Buffer,基于gRPC。

Container Runtime实现了CRI gRPC Server,包括RuntimeService和ImageService。该gRPC Server需要监听本地的Unix socket,而kubelet则作为gRPC Client运行


2、概念

官方版:

容器就是将软件打包成标准化单元,以用于开发、交付和部署。

容器镜像是轻量的、可执行的独立软件包,包含软件运行所需的所有内容(包括代码、运行时环境、系统工具、 系统库和设置)

通俗版:

容器是一种沙盒技术,又像集装箱,把应用整体封装起来的技术;封装后,应用于应用之间,在各自的边界内运行,不会相互干扰;而被装进集装箱的应用,也可以被方便搬来搬去。

集装箱的作用:比如在一艘船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化,集装箱和集装箱之间不会互相影响。那么我就不需要专门运送水果的船和专门运送化学品的船了。只需要这些货物在集装箱里封装的好好的,那么我就可以用一艘大船把它们都运走。

本质版:

一组受到资源限制,彼此间相互隔离的进程;就是将所有软件整合成一个应用,一个应用。

3、实现原理

技术核心:

约束、修改进程的动态表现,从而创造一个“边界”,所以,容器只是运行在宿主机上的一种特殊的进程,使用的还是同一个宿主机的LINUX操作系统的内核。

4、容器的主要技术

namespace:

用来修改进程视图的主要方法,做访问隔离(每个容器进程都有自己独立的进程空间,看不到其他进程),是LINUX提供的一种内核级别环境隔离方法。

cgroups:用来制造约束的主要手段;主要做资源限制(CPU、内存、存储、网络的使用限制);

二、Docker

1、定义

基于 Linux 内核 的cgroup,namespace,以及AUFS类的UnionFS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。 由于隔离的进程独立于宿主和其它的隔离的进 程,因此也称其为容器。Docke最初实现是基于 LXC.

 

2、基本概念

 

(1)镜像(IMAGE):一个特殊的文件系统

   

  操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而Docker 镜像(Image),就相当于是一个 root 文件系统。

 

  Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建之后也不会被改变。

 

  Docker 设计时,就充分利用 Union FS的技术,将其设计为 分层存储的架构 。 镜像实际是由多层文件系统联合组成。

 

  镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。 比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

 

  分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

(2)容器(Container):镜像运行时的实体

   

  镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。

  

  容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。前面讲过镜像使用的是分层存储,容器也是如此。

 

  容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。

 

 

 

  按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据 ,容器存储层要保持无状态化。所有的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此, 使用数据卷后,容器可以随意删除、重新 run ,数据却不会丢失。

 

 

(3)仓库(Repository):集中存放镜像文件的地方

   

  镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry就是这样的服务。

 

  一个 Docker Registry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。所以说:镜像仓库是Docker用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。

 

  通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过 <仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签.。

 

  这里补充一下Docker Registry 公开服务和私有 Docker Registry的概念:

 

  Docker Registry 公开服务 是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。

 

  最常使用的 Registry 公开服务是官方的 Docker Hub ,这也是默认的 Registry,并拥有大量的高质量的官方镜像,网址为:https://hub.docker.com/ 。在国内访问Docker Hub 可能会比较慢国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 时速云镜像库、网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库等。

 

  除了使用公开服务外,用户还可以在 本地搭建私有 Docker Registry 。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 docker 命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。

 

3、Docker的架构

(1)Docker Engine用来管理镜像

(2)Containerd向docker提供运行容器的API,二者通过grpc进行交互。

(3)containerd最后会通过runc来实际运行容器

(4)containerd-shim称之为垫片,它使用runC命令行工具完成容器的启动、停止以及容器运行状态的监控。containerd-shim进程由containerd进程拉起,并持续存在到容器实例进程退出为止(和容器进程同生命周期)。只要是符合OCI规范的容器,都可以通过containerd-shim来进行调用(比如kata-runtime);

 
原文地址:https://www.cnblogs.com/yfacesclub/p/12013025.html