Docker简介

Docker简介

Docker的架构介绍

Docker并没有传统虚拟化中的Hypervisor层。因为Docker是基于容器技术的轻量级虚拟化,相对于传统的虚拟化技术,省去了Hypervisor层的开销,而且其虚拟化技术是基于内核的Cgroup和Namespace技术,处理逻辑与内核深度融合,所以在很多方面,它的性能与物理机非常接近。
在通信上,Docker并不会直接与内核交互,它是通过一个更底层的工具Libcontainer与内核交互的。Libcontainer是真正意义上的容器引擎,它通过clone系统调用直接创建容器,通过pivot_root系统调用进入容器,且通过直接操作cgroupfs文件实现对资源的管控,而Docker本身侧重于处理更上层的业务。
Docker的另一个优势是对层级镜像的创新应用,即不同的容器可以共享底层的只读镜像,通过写入自己特定的内容后添加新的镜像层,新增的镜像层和下层的镜像一起又可以作为基础镜像被更上一层的镜像使用。这种特性可以极大地提高磁盘利用率,所以当你地系统上有10个大小为1GB地镜像时,它们总共占用地空间大小可能只有5GB,甚至更少。另外,Docker对Union mount地应用还体现在多个容器使用同一个基础镜像时,可极大地减少内存占用等方面,因为不同地容器访问同一个文件时,只会占用一份内存。当然这需要支持Union mount地文件系统作为存储的Greph Driver,比如AUFS和Overlay。

功能和组件

Docker为了实现其所描述的功能,引入了以下核心概念:
1)Docker客户端
2)Docker daemon
3)Docker 容器
4)Docker 镜像
5)Registry

Docker客户端

Docker是一个典型的C/S架构的应用程序,但在发布上,Docker将客户端和服务器端统一在同一个二进制文件中,不过,这只是对于Linux系统而言的,在其他平台如Mac上,Docker只提供了客户端。
Docker客户端一般通过Docker command来发起请求,另外,也可以通过Docker提供的一整套RESTful API来发起请求,这种方式更多地被应用在应用程序地代码中。

Docker daemon

Docker daemon也可以被理解成Docker Server,另外,人们也常常用Docker Engine来直接描述它,因为这实际上就是驱动整个就是驱动整个Docker功能地核心引擎。
简单地说,Docker daemon实现的功能就是接收客户端发来的请求,并实现请求所要求的功能,同时针对请求返回相应的结果。在功能的实现上,因为涉及了容器、镜像、存储等多方面的内容、daemon内部的机制会复杂很多,涉及了多个模块的实现和交互。

Docker容器

在Docker的功能和概念中,容器是一个核心内容,相对于传统虚拟化,它作为一项基础技术在性能上给Docker带来了极大优势。
在功能上,Docker通过Libcontainer实现对容器生命周期的管理、信息的设置和查询以及监控和通信等功能。而容器也是对镜像的完美诠释,容器以镜像为基础,同时又为镜像提供了一个标准的和隔离的执行环境。
在概念上,容器则很好地诠释了Docker集装箱的理念,集装箱可以存放任何货物,可以通过邮轮将货物运输到世界各地。运输集装箱的邮轮和装载卸载集装箱的码头都不用关心集装心里的货物,这是一种标准的集装和运算方式。类似的,Docker的容器就是"软件界的集装箱",它可以安装任意的软件和库文件,做任意的运行环境配置。开发及运维人员在转移和部署应用的时候,不用关系容器里装了什么软件,也不用了解它们是如何配置的。而管理容器的Docker引擎同样不关心容器里的内容,它只要像码头工人一样让这个容器运行起来就可以了,就像所有其他容器那样。
容器不是一个新的概念,但是Docker在对容器进行封装后,与集装箱的概念对应起来了,它之所以被称为"软件界的创新和革命",是因为它会改变软件的开发、部署形态、降低成本,提高效率。Docker真正把容器推广到了全世界。

Docker镜像

与容器相对应,如果说容器提供了一个完整的、隔离的运行环境,那么镜像则是这个运行环境的静态体现,是一个还没有运行起来的"运行环境"。
相对于传统虚拟化中的ISO镜像,Docker镜像要轻量级很多,它只是一个可定制的rootfs。Docker镜像的另一个创新是它是层级的并且是可复用的,这在实际应用场景中极为有用,多数基于相同发行版的镜像,在大多数文件的内容上都是一样的,基于此,当然会希望可以复用它们,而Docker做到了。在此类应用场景中,利用Unionfs的特性,Docker会极大地减少磁盘和内存地开销。

Registry

Registry是一个存放镜像的仓库,它通常被部署在互联网服务器或者云端。通常,集装箱是需要通过邮轮经行海洋运输到世界各地的,而互联网时代的运输则要方便很多,在镜像的运输过程中,Registry就是这个传输的重要中转站。假如我们在公司将一个软件的运行环境制作成镜像,并上传到Registry中,这时就可以很方便地在家里地笔记本上,或者在客户地生产环境上直接从Registry上下载并运行了。当然,对Registry的操作也是与Docker完美融合的,用户甚至不需要知道Registry的存在,只需要通过简单的Docker命令就可以实现上面的操作。
Docker公司提供的官方Registry叫Docker Hub,这上面提供了大多数常用软件和发行版的官方镜像,还有无数个人用户提供的个人镜像。其实,Registry本身也是一个单独的开源项目,任何人都可以下载后自己部署一个Registry。因为免费的Docker Hub功能相对简单,所有多数企业会选择自己部署Docker Registry后二次开发,或者购买功能更强大的企业版Docker Hub。

安装和使用

https://blog.youkuaiyun.com/shi_zi_183/article/details/121202041?spm=1001.2014.3001.5501

概念澄清

Docker在LXC基础上做了什么工作

首先我们需要明确LXC的概念,但这常常有不同的认识。LXC目前代表两种含义:
1)LXC用户态工具
2)Linux Container,即内核容器技术的简称
这里通常指第二种,即Docker在内容容器技术的基础上做了什么工作。简单地说,Docker在内核容器技术(Cgroup和Namespace)的基础上,提供了一个更高层的控制工具,该工具包含以下特性。

  • 跨主机部署。Docker定义了镜像格式,该格式会将应用程序和其所依赖的文件打包到同一个镜像文件中,从而使其在转移到任何运行Docker的机器中时都可以运行,并能够保证在任何机器中该应用程序执行的环境都是一样的。LXC实现类"进程沙盒",这一重要特性是跨主机部署的前提条件,但是只有这一点远远不够,比如,在一个特定的LXC配置下执行应用程序,将该应用程序打包并拷贝到另一个LXC环境下,程序很有可能无法正常执行,因为该程序的执行依赖于该机器的特定配置,包括网络、存储、发行版等。而Docker则将上述相关配置进行抽象并与应用程序一同打包,所有可以保证在不同硬件、不同配置的机器上Docker容器中运行的程序和其所依赖的环境即配置是一致的。
  • 以应用为中心。Docker为简化应用程序的部署过程做了很多优化,这一目的在Docker的API、用户接口、设计哲学和用户文档中都有体现,其Dockerfile机制大大简化和规范了应用的部署方法。
  • 自动构建。Docker提供了一套能够从源码自动构建镜像的工具。该工具可以灵活地使用make、maven、chef、puppet、salt、debian包、RPM和源码包等形式,将应用程序的依赖、构建工具和安装包进行打包处理,而且当前机器的配置不会影响镜像的构建过程。
  • 版本管理。Docker提供了类似于Git的版本管理功能,支持追踪镜像版本、检验版本更新、提交新的版本改动和回退版本等功能。镜像的版本信息中包括制作方式和制作者信息,因此可以从生产环境中回溯到上游开发人员。Docker同样实现了镜像的增量上传下载功能,用户可以通过获取新旧版本之间新增的镜像层来更新镜像版本,而不必下载完整镜像,类似Git中的pull命令。
  • 组件重用。任何容器都可以用作生产另一个组件的基础镜像。这一过程可以手动执行,也可以写入自动化构建的脚本。例如,可以创建一个包含python开发环境的镜像,并将其作为基础镜像部署其他使用python环境进行开发的应用程序。
  • 共享。Docker用户可以访问公共的镜像Registry,并向其中上传有用的镜像。Registry中同样包含由Docker公司维护的一些官方标准镜像。Docker Registry本身也是开源的,所以任何人都可以部署自己的Registry来存储并共享私有镜像。
  • 工具生态链。Docker定义了一系列API来定制容器的创建和部署的创建和部署过程并实现自动化。有很多工具能够与Docker集成并扩展Docker的能力,包括类PaaS部署工具(Dokku、Deis和Flynn)、多节点编排工具(Maestro、Salt、Mesos、OpenStack nove)、管理面板(Docker-ui、OpenStack Horizon、Shipyard)、配置管理工具(Chef、Puppet)、持续集成工具(Jenkins、Strider、Travis)等。Docker正在建立以容器为基础的工具集标准。

Docker容器和虚拟机之间有什么不同

容器与虚拟机是互补的。虚拟机是用来进行硬件资源划分的完美解决方案,它利用了硬件虚拟化技术,例如VT-x、AMD-v或者privilege level(权限等级)会同时通过一个hypervisor层来实现对资源的彻底隔离;而容器则是操作系统级别的虚拟化,利用的是内核的Cgroup和Namespace特性,此功能完全通过软件来实现,仅仅是进程本身就可以与其他进程隔离开,不需要任何辅助。
Docker容器与主机共享操作系统内核,不同的容器之间可以共享部分系统资源,因此容器更加轻量级,消耗的资源也更少。而虚拟机会独占分配给自己的资源,几乎不存在资源共享,各个虚拟机实例之间近乎完全隔离,因此虚拟机更加重量级,也会消耗更多的资源。我们可以很轻松地在一台普通的Linux机器上运行100个或者更多的Docker容器,而且不会占用太多系统资源(如果容器中没有执行运算任务或I/O操作);而在单台机器上不可能创建100台虚拟机,因为每个虚拟机实例都会占用一个完整的操作系统所需要的所有资源。另外,Docker容器启动很快,通常是秒级甚至是毫秒级启动。而虚拟机的启动虽然会快于物理机器,但是启动时间也是在数秒甚至数十秒的量级。
因此,可以根据需求的不同选择相应的隔离方式。如果需要资源完全隔离并且不考虑资源消耗,可以选择使用虚拟机;而若是想隔离进程并且需要运行大量进程实例,则应该选择Docker容器。

容器的组成

容器的核心技术是Cgroup+Namespace,但光有这两个抽象的技术概念是无法组成一个完整的容器的。
对于Linux容器的最小组成,可以由以下公式来表示:
容器 = cgroup + namespace + rootfs + 容器引擎(用户态工具)

  • cgroup:资源控制
  • Namespace:访问隔离
  • rootft:文件系统隔离
  • 容器引擎:生命周期控制

Cgroup介绍

Cgroup是什么

Cgroup是control group的简写,属于Linux内核提供的一个特性,用于限制和隔离一组进程对系统资源的使用,也就是做资源QoS,这些资源主要包括CPU、内存、block I/O和网络宽带。Cgroup从2.6.24开始进入内核主线,目前各大发行版都默认打开了Cgroup特性。
从实现的角度来看,Cgroup实现了一个通用的进程分组的框架,而不同资源的具体管理则是由各个Cgroup子系统实现的。截止到内核4.1版本,Cgroup中实现的子系统及其作用

  • devices:设备权限控制。
  • cpuset:分配指定的CPU和内存节点。
  • cpu:控制CPU占用率
  • cpuacct:统计CPU使用情况
  • memory:限制内存的使用上限
  • freezer:冻结(暂停)Cgroup中的进程
  • net_cls:配合tc限制网络宽带。
  • net_prio:设置进程的网络流量优先级。
  • huge_tlb:限制HugeTLB的使用
  • perf_event:允许Perf工具基于Cgroup分组做性能监测
    在Cgroup出现之前,只能对一个进程做一些资源控制,例如通过sched_setaffinity系统调用限制一个进程的CPU亲和性,或者用ulimit限制一个进程的打开文件上限、栈大小等。另外,使用ulimit可以对进程进行任意的分组,如何分组是用户自定义的,例如安卓的应用分为前台应用和后台应用,前台应用是直接跟用户交互的,需要响应速度快,因此前台应用对资源的申请需要得到更多的保证。为此安卓将前台应用和后台应用划分到不同的Cgroup中,并且对防止前台应用的Cgroup配置了较高的系统资源限额。

Cgroup子系统介绍

cpuset子系统
cpuset可以为一组进程分配指定的CPU和内存节点。cpuset一开始是用在高性能计算上的,在NUMA架构的服务器上,通过将进程绑定到固定的CPU和内存节点上,来避免进程在运行时因跨节点内存访问而导致的性能下降。当然,现在cpuset也广泛用在了kvm和容器等场景上。
cpuset的主要接口

  • cpuset.cpus:允许进程使用的CPU列表。
  • cpuset.mems:允许进程使用的内存节点列表。
    cpu子系统
    cpu子系统用于限制进程的CPU占用率。实际上它有三个功能,分别通过不同的接口来提供。
  • CPU比重分配。这个特性使用的接口是cpu.shares。假如在cgroup的根目录下创建了两个Cgroup,并且将cpu.shares分别配置为512和1024,那么当C1和C2争用CPU时,C2将会比C1得到多一倍的CPU占用率。要注意的是,只有当它们争用CPU时cpu share才会起作用,如果C2是空闲的,那么C1可以得到全部的CPU资源。
  • CPU带宽限制。这个特性使用的接口是cpu.cfs_period_us和cpu.cfs_quota_us,这两个接口的单位是微秒。可以将period设置为1秒,将quota设置为0.5秒,那么Cgroup中的进程在1秒内最多只能运行0.5秒,然后就会被强制睡眠,直到进入下一个1秒才能继续运行。
  • 实时进程的CPU带宽限制。以下两个特性都只能限制普通进程,若要限制实时进程,就要使用cpu.rt_period_us和cpu.rt_runtime_us这两个接口了。
    cpuacct子系统
    cpuacct子系统用来统计各个Cgroup的CPU使用情况,有如下接口。
  • cpuacct.stat:报告这个Cgroup分别在用户态和内核态消耗的CPU时间,单位是USER_HZ。USER_HZ在x86上一般是100,即1USER_HZ等于0.01秒。
  • cpuacct.usage:报告这个Cgroup消耗的总CPU时间,单位是纳秒。
  • cpuacct.usage_percpu:报告这个Cgroup在各个CPU上消耗的CPU时间,总和也就是cpuacct.usage的值。
    memory子系统
    memory子系统用来限制Cgroup所能使用的内存上限。
  • memory.limit_in_bytes:设定内存上限,单位是字节,也可以使用k/K、m/M或者g/G表示要设置数值的单位
    默认情况下,如果Cgroup使用的内存超过上限,Linux会尝试回收内存,如果仍然无法将内存使用量控制在上限之内,系统将会触发OOM,选择并"杀死"该Cgroup中的某个进程。
  • memory.memsw.limit_in_bytes:设定内存加上交换分区的使用总量。通过设置这个值,可以防止进程分区用光。
  • memory.oom_control:如果设置为0,那么在内存使用量超过上限时,系统不会"杀死"进程,而是阻塞进程直到有内存被释放可供使用时;另一方面,系统会向用户态发送事件通知,用户态的监控程序可根据该事件来做相应的处理,例如提高内存上限等。
  • memory.stat:汇报内存使用信息。
    blkio子系统
    blkio子系统用来限制Cgroup的block I/O带宽。
  • bIkio.weight:设置权重值,范围在100到1000之间。这跟cpu.shares类似,是比重分配,而不是绝对带宽的限制,因此只有当不同的Cgroup在争用同一个块设备的带宽时才会起作用。
  • bIkio.weight_device:对具体的设备设置权重值,这个值会覆盖上述的bIkio.weight。例如将Cgroup对/dev/sda的权重设为最小值
  • bIkio.throttle.read_bps_device:对具体的设备,设置每秒读磁盘的带宽上限。例如对/dev/sda的读带宽限制在1MB/秒:
  • bikio.throttle.write_bps_device:设置每秒写磁盘的带宽上限。同样需要指定设备。
  • bIkio.throttle.read_iops_device:设置每秒读磁盘的IOPS上限。同样需要指定设备
  • bIkio.throttle.write_iops_device:设置每秒读写磁盘的IOPS上限。同样需要指定设备。
    device子系统
    devices子系统用来控制Cgroup的进程对哪些设备有访问权限
  • device.list。只读文件,显示目前运行被访问的设备列表。每个条目都有3个域,分别为:类型:可以是a、c或b,反别表示所有设备、字符设备和块设备。设备号:格式为magjor:minor的设备号。权限:r、w和m的组合,分别表示可读、可写、可创建设备结点(mknod)。
  • devices.allow。只写文件,以上面的格式写入该文件,就可以运行相应的设备访问权限。
  • devices.deny。只写文件,以上面的描述的格式写入该文件,就可以禁止相应的设备访问权限。

Namespace介绍

Namespace是什么

Namespace是将内核的全局资源做封装,使得每个Namespace都有一份独立的资源,因此不同的进程在各自的Namespace内对同一种资源的使用不会相互干扰。
例如,执行sethostname这个系统调用时,可以改变系统的主机名,这个主机名就是一个内核的全局资源。内核通过实现UTS Namespace,可以将不同的进程分隔在不同的UTS Namespace中,在某个Namespace修改主机名时,另一个Namespace的主机名还是保持不变。
Linux内核总共实现了6种Namespace:

  • IPC:隔离System V IPC和POSIX消息队列
  • Network:隔离网络资源。
  • Mount:隔离文件系统挂载点
  • PID:隔离进程ID
  • UTS:隔离主机名或域名
  • User:隔离用户ID和组ID
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值