操做系统-容器-引擎容器-百科:Docker

ylbtech-操做系统-容器-引擎容器-百科:Docker

Docker 是一个开源的应用容器引擎让开发者能够打包他们的应用以及依赖包到一个可移植的容器中而后发布到任何流行的 Linux 机器上,也能够实现虚拟化容器是彻底使用沙箱机制,相互之间不会有任何接口html

1.返回顶部
一、

简介

Docker 是一个 开源的应用容器引擎,让开发者 能够打包他们的应用以及依赖包到一个可移植的容器中,而后发布到任何流行的 Linux机器上,也能够 实现虚拟化,容器是彻底使用沙箱机制,相互之间不会有任何接口。
一个完整的Docker有如下几个部分组成:
  1. dockerClient客户端
  2. Docker Daemon守护进程
  3. Docker Image镜像
  4. DockerContainer容器
 

起源

Docker 是  PaaS 提供商 dotCloud 开源的一个基于  LXC 的高级容器引擎,源代码托管在  Github 上, 基于 go语言并听从Apache2.0协议开源。
Docker自2013年以来很是火热,不管是从 github 上的代码活跃度,仍是 Redhat在RHEL6.5中集成对Docker的支持, 就连 Google 的 Compute Engine 也支持 docker 在其之上运行。
一款开源软件可否在商业上成功,很大程度上依赖三件事 - 成功的 user case(用例),活跃的社区和一个好故事。 dotCloud 自家的 PaaS 产品创建在 docker之上,长期维护且有大量的用户,社区也十分活跃,接下来咱们看看docker的故事。
  • 环境管理复杂 - 从各类OS到各类中间件到各类app, 一款产品可以成功做为开发者须要关心的东西太多,且难于管理,这个问题几乎在全部现代IT相关行业都须要面对。
  • 云计算时代的到来 - AWS的成功, 引导开发者将应用转移到 cloud 上, 解决了硬件管理的问题,然而中间件相关的问题依然存在 (因此openstack HEAT和 AWS cloudformation 都着力解决这个问题)。开发者思路变化提供了可能性。
  • 虚拟化手段的变化 - cloud 时代采用标配硬件来下降成本,采用虚拟化手段来知足用户按需使用的需求以及保证可用性和隔离性。然而不管是KVM仍是Xen在 docker 看来,都在浪费资源,由于用户须要的是高效运行环境而非OS, GuestOS既浪费资源又难于管理, 更加轻量级的LXC更加灵活和快速
  • LXC的移动性 - LXC在 linux 2.6 的 kernel 里就已经存在了,可是其设计之初并不是为云计算考虑的,缺乏标准化的描述手段和容器的可迁移性,决定其构建出的环境难于迁移和标准化管理(相对于KVM之类image和snapshot的概念)。docker 就在这个问题上作出实质性的革新。这是docker最独特的地方。
 

Docker架构

Docker 使用 客户端-服务器 (C/S) 架构模式使用远程API来管理和建立Docker容器。Docker 容器经过 Docker 镜像来建立。容器与镜像的关系相似于面向对象编程中的对象与类。  
Docker 面向对象
容器 对象
镜像

Docker采用 C/S架构 Docker daemon 做为服务端接受来自客户的请求,并处理这些请求( 建立、运行、分发容器)。 客户端和服务端既能够运行在一个机器上,也可经过 socket 或者RESTful API 来进行通讯。
Docker daemon 通常在宿主主机后台运行,等待接收来自客户端的消息。 Docker 客户端则为用户提供一系列可执行命令,用户用这些命令实现跟 Docker daemon 交互。
 

特性

在docker的网站上提到了docker的典型场景:
  • Automating the packaging and deployment of applications( 使应用的打包与部署自动化
  • Creation of lightweight, private PAAS environments( 建立轻量、私密的PAAS环境
  • Automated testing and continuous integration/deployment( 实现自动化测试和持续的集成/部署
  • Deploying and scaling web apps, databases and backend services( 部署与扩展webapp、数据库和后台服务)
因为其 基于LXC的轻量级虚拟化的特色,docker相比KVM之类最明显的特色就是 启动快,资源占用小。所以对于构建隔离的标准化的运行环境,轻量级的PaaS(如dokku), 构建自动化测试和持续集成环境,以及一切能够横向扩展的应用(尤为是须要快速启停来应对峰谷的web应用)。
  1. 构建标准化的运行环境,现有的方案大可能是在一个baseOS上运行一套puppet/chef,或者一个image文件,其缺点是前者须要base OS许多前提条件,后者几乎不能够修改(由于copy on write 的文件格式在运行时rootfs是read only的)。而且后者文件体积大,环境管理和版本控制自己也是一个问题。
  2. PaaS环境是不言而喻的,其设计之初和dotcloud的案例都是将其做为PaaS产品的环境基础
  3. 由于其标准化构建方法(buildfile)和良好的REST API,自动化测试和持续集成/部署可以很好的集成进来
  4. 由于LXC轻量级的特色,其启动快,并且docker可以只加载每一个container变化的部分,这样资源占用小,可以在单机环境下与KVM之类的虚拟化方案相比可以更加快速和占用更少资源
 

局限

Docker并非全能的,设计之初也不是KVM之类虚拟化手段的替代品,简单总结几点:
  1. Docker是基于Linux 64bit的,没法在32bit的linux/Windows/unix环境下使用
  2. LXC是基于cgroup等linux kernel功能的,所以container的guest系统只能是linux base的
  3. 隔离性相比KVM之类的虚拟化方案仍是有些欠缺,全部container公用一部分的运行库
  4. 网络管理相对简单,主要是基于namespace隔离
  5. cgroup的cpu和cpuset提供的cpu功能相比KVM的等虚拟化方案相比难以度量(因此dotcloud主要是按内存收费)
  6. Docker对disk的管理比较有限
  7. container随着用户进程的中止而销毁,container中的log等用户数据不便收集
针对1-2,有windows base应用的需求的基本能够pass了; 3-5主要是看用户的需求,究竟是须要一个container仍是一个VM, 同时也决定了docker做为 IaaS 不太可行。
针对6,7虽然是docker自己不支持的功能,可是能够经过其余手段解决(disk quota, mount --bind)。总之,选用container仍是vm, 就是在隔离性和资源复用性上作权衡。
另外即使docker 0.7可以支持非AUFS的文件系统,可是因为其功能还不稳定,商业应用或许会存在问题,而AUFS的稳定版须要kernel 3.8, 因此若是想复制dotcloud的成功案例,可能须要考虑升级kernel或者换用ubuntu的server版本(后者提供deb更新)。这也是为何开源界更倾向于支持ubuntu的缘由(kernel版本)
Docker并不是适合全部应用场景,Docker只能虚拟基于Linux的服务。Windows Azure 服务可以运行Docker实例,但到目前为止Windows服务还不能被虚拟化。
可能最大的障碍在于管理实例之间的交互。因为全部应用组件被拆分到不一样的容器中,全部的服务器须要以一致的方式彼此通讯。这意味着任何人若是选择复杂的基础设施,那么必须掌握应用编程接口管理以及集群工具,好比Swarm、Mesos或者Kubernets以确保机器按照预期运转并支持故障切换。
Docker在本质上是一个附加系统。使用文件系统的不一样层构建一个应用是有可能的。每一个组件被添加到以前已经建立的组件之上,能够比做为一个文件系统更明智。分层架构带来另外一方面的效率提高,当你重建存在变化的Docker镜像时,不须要重建整个Docker镜像,只须要重建变化的部分。
可能更为重要的是,Docker旨在用于弹性计算。每一个Docker实例的运营生命周期有限,实例数量根据需求增减。在一个管理适度的系统中,这些实例生而平等,再也不须要时便各自消亡了。
针对Docker环境存在的不足,意味着在开始部署Docker前须要考虑以下几个问题。首先,Docker实例是无状态的。这意味着它们不该该承载任何交易数据,全部数据应该保存在数据库服务器中。
其次,开发Docker实例并不像建立一台虚拟机、添加应用而后克隆那样简单。为成功建立并使用Docker基础设施,管理员须要对系统管理的各个方面有一个全面的理解,包括Linux管理、编排及配置工具好比Puppet、Chef以及Salt。这些工具生来就基于命令行以及脚本。
 

原理

Docker核心解决的问题是利用LXC来实现相似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。同VM的方式不一样,  LXC 其并非一套硬件虚拟化方法 - 没法归属到全虚拟化、部分虚拟化和半虚拟化中的任意一个,而是一个操做系统级虚拟化方法, 理解起来可能并不像VM那样直观。因此咱们从虚拟化到docker要解决的问题出发,看看他是怎么知足用户虚拟化需求的。
用户须要考虑虚拟化方法,尤为是硬件虚拟化方法,须要借助其解决的主要是如下4个问题:
  • 隔离性 - 每一个用户实例之间相互隔离, 互不影响。 硬件虚拟化方法给出的方法是VM, LXC给出的方法是container,更细一点是kernel namespace
  • 可配额/可度量 - 每一个用户实例能够按需提供其计算资源,所使用的资源能够被计量。硬件虚拟化方法由于虚拟了CPU, memory能够方便实现, LXC则主要是利用cgroups来控制资源
  • 移动性 - 用户的实例能够很方便地复制、移动和重建。硬件虚拟化方法提供snapshot和image来实现,docker(主要)利用AUFS实现
  • 安全性 - 这个话题比较大,这里强调是host主机的角度尽可能保护container。硬件虚拟化的方法由于虚拟化的水平比较高,用户进程都是在KVM等虚拟机容器中翻译运行的, 然而对于LXC, 用户的进程是lxc-start进程的子进程, 只是在Kernel的namespace中隔离的, 所以须要一些kernel的patch来保证用户的运行环境不会受到来自host主机的恶意入侵, dotcloud(主要是)利用kernel grsec patch解决的.
 

Linux namespace

LXC所实现的隔离性主要是来自kernel的namespace, 其中pid, net, ipc, mnt, uts 等namespace将container的进程, 网络, 消息, 文件系统和hostname 隔离开
pid namespace
以前提到用户的进程是lxc-start进程的子进程, 不一样用户的进程就是经过pidnamespace隔离开的,且不一样 namespace 中能够有相同PID。具备如下特征:
  1. 每一个namespace中的pid是有本身的pid=1的进程(相似/sbin/init进程)
  2. 每一个namespace中的进程只能影响本身的同一个namespace或子namespace中的进程
  3. 由于/proc包含正在运行的进程,所以在container中的pseudo-filesystem的/proc目录只能看到本身namespace中的进程
  4. 由于namespace容许嵌套,父namespace能够影响子namespace的进程,因此子namespace的进程能够在父namespace中看到,可是具备不一样的pid
正是由于以上的特征,全部的LXC进程在docker中的父进程为docker进程,每一个lxc进程具备不一样的namespace。同时因为容许嵌套,所以能够很方便的实现 LXC in LXC
net namespace
有了 pid namespace, 每一个namespace中的pid可以相互隔离,可是网络端口仍是共享host的端口。网络隔离是经过netnamespace实现的,
每一个net namespace有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。这样每一个container的网络就能隔离开来。
LXC在此基础上有5种网络类型,docker默认采用veth的方式将container中的虚拟网卡同host上的一个docker bridge链接在一块儿。
ipc namespace
container中进程交互仍是采用linux常见的进程间交互方法(interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同VM不一样,container 的进程间交互实际上仍是host上具备相同pid namespace中的进程间交互,所以须要在IPC资源申请时加入namespace信息 - 每一个IPC资源有一个惟一的 32bit ID。
mnt namespace
相似chroot,将一个进程放到一个特定的目录执行。mnt namespace容许不一样namespace的进程看到的文件结构不一样,这样每一个 namespace 中的进程所看到的文件目录就被隔离开了。同chroot不一样,每一个namespace中的container在/proc/mounts的信息只包含所在namespace的mount point。
uts namespace
UTS(“UNIX Time-sharing System”) namespace容许每一个container拥有独立的hostname和domain name, 
  使其在网络上能够被视做一个独立的节点而非Host上的一个进程。
user namespace
每一个container能够有不一样的 user 和 group id, 也就是说能够以container内部的用户在container内部执行程序而非Host上的用户。
有了以上6种namespace从进程、网络、IPC、文件系统、UTS和用户角度的隔离,一个container就能够对外展示出一个独立计算机的能力,而且不一样container从OS层面实现了隔离。 
  然而不一样namespace之间资源仍是相互竞争的,仍然须要相似ulimit来管理每一个container所能使用的资源 - LXC 采用的是cgroup。
 

Control Groups

cgroups 实现了对资源的配额和度量。 cgroups 的使用很是简单,提供相似文件的接口,在 /cgroup目录下新建一个文件夹便可新建一个group,在此文件夹中新建task文件,并将pid写入该文件,便可实现对该进程的资源控制。具体的资源配置选项能够在该文件夹中新建子 subsystem ,{子系统前缀}.{资源项} 是典型的配置方法,
如memory.usage_in_bytes 就定义了该group 在subsystem memory中的一个内存限制选项。
另外,cgroups中的 subsystem能够随意组合,一个subsystem能够在不一样的group中,也能够一个group包含多个subsystem - 也就是说一个 subsystem。
关于术语定义
A *cgroup* associates a set of tasks with a set of parameters for one 
  or more subsystems. 
  A *subsystem* is a module that makes use of the task grouping 
  facilities provided by cgroups to treat groups of tasks in 
  particular ways. A subsystem is typically a "resource controller" that 
  schedules a resource or applies per-cgroup limits, but it may be 
  anything that wants to act on a group of processes, e.g. a 
  virtualization subsystem.
咱们主要关心cgroups能够限制哪些资源,即有哪些subsystem是咱们关心。
cpu : 在cgroup中,并不能像硬件虚拟化方案同样可以定义CPU能力,可是可以定义CPU轮转的优先级,所以具备较高CPU优先级的进程会更可能获得CPU运算。 
  经过将参数写入cpu.shares,便可定义改cgroup的CPU优先级 - 这里是一个相对权重,而非绝对值。固然在cpu这个subsystem中还有其余可配置项,手册中有详细说明。
cpusets : cpusets 定义了有几个CPU能够被这个group使用,或者哪几个CPU能够供这个group使用。在某些场景下,单CPU绑定能够防止多核间缓存切换,从而提升效率
memory : 内存相关的限制
blkio : block IO相关的统计和限制,byte/operation统计和限制(IOPS等),读写速度限制等,可是这里主要统计的都是同步IO
net_cls, cpuacct , devices , freezer 等其余可管理项。
 

Linux 容器

借助于namespace的隔离机制和cgroup限额功能, LXC提供了一套统一的API和工具来创建和管理container, LXC利用了以下 kernel 的features:
  • Kernel namespaces (ipc, uts, mount, pid, network and user)
  • Apparmor and SELinux profiles
  • Seccomp policies
  • Chroots (using pivot_root)
  • Kernel capabilities
  • Control groups (cgroups)
LXC 向用户屏蔽了以上 kernel 接口的细节, 提供了以下的组件大大简化了用户的开发和使用工做:
  • The liblxc library
  • Several language bindings (python3, lua and Go)
  • A set of standard tools to control the containers
  • Container templates
LXC 旨在提供一个共享kernel的 OS 级虚拟化方法,在执行时不用重复加载Kernel, 且container的kernel与host共享,所以能够大大加快container的 启动过程,并显著减小内存消耗。在实际测试中,基于LXC的虚拟化方法的IO和CPU性能几乎接近 baremetal 的性能  [9]  , 大多数数据有相比 Xen具备优点。固然对于KVM这种也是经过Kernel进行隔离的方式, 性能优点或许不是那么明显, 主要仍是内存消耗和启动时间上的差别。在参考文献 [10]  中提到了利用iozone进行 Disk IO吞吐量测试KVM反而比LXC要快,并且笔者在device mapping driver下重现一样case的实验中也确实能获得如此结论。参考文献从网络虚拟化中虚拟路由的场景(网络IO和CPU角度)比较了KVM和LXC, 获得结论是KVM在性能和隔离性的平衡上比LXC更优秀 - KVM在吞吐量上略差于LXC, 但CPU的隔离可管理项比LXC更明确。
关于CPU, DiskIO, network IO 和 memory 在KVM和LXC中的比较仍是须要更多的实验才能得出可信服的结论。
 

AUFS

(略)
 

GRSEC

(略)
 

方法

(略)
 

工具实践

Docker推出的一个名为 Docker Content Trust(DCT)的新功能, 它可帮助IT专业人士确保Docker的安全性。DCT使用了 一个公共密钥基础设施(PKI)的方法,它提供了 两个不一样的密钥:一个离线(root)密钥和一个标记(每次入库)密钥,当第一次发布者推出镜像时它可建立和存储客户端。
此举有助于弥补正在使用恶意容器这一最大的漏洞。DCT还生成了一个时间戳密钥,它可保护系统免受重放攻击,即运行过时的标记内容。这解决了上面说起容器具备不一样安全补丁等级的问题。
为了解决针对容器安全性的问题,包括Docker在内的众多公司都为Docker发布了安全基准。这套标准为确保Docker容器的安全性提供了指导。全篇118页的文档囊括了部署Docker容器的84个最佳实践以及一个涉及全部内容的检查清单。
那么,若是你决定自行负责确保Docker容器的安全性,但又不知道从何入手,咱们在这里为你提供了一些建议:
阅读上面说起的Docker安全基准文件。重点关注与如何部署基于容器的应用程序相关的建议和最佳实践。这真的是有助于缓解你的财务压力,认真考虑大部分因糟糕设计而致使的Docker安全性问题。
考虑你的特定安全性需求。这将促使你选择正确的工具和方法。不少使用容器技术的企业对于他们基于容器的应用程序要么安全措施不足,要么安全措施过足。
尽量多地进行测试。容器技术是新技术,所以咱们须要搞清楚哪些是可以发挥做用,哪些是无用的,而要作到这一点的惟一方法就是进行安全性方面的测试,例如渗透测试。
容器安全性的发展趋势可能会与虚拟化安全性同样。虽然安全性从第一台虚拟机部署开始就是一个问题,可是多年以来积累下来的良好安全性实践、架构和工具都证实了其有效性。咱们相信,Docker容器安全性的问题也一样可以获得较好解决。
 

使用案例

(略)
 
二、
2.返回顶部
 
3.返回顶部
 
4.返回顶部
 
5.返回顶部
0、
一、
二、
2.1
2.2
三、
 
6.返回顶部
 
warn 做者:ylbtech
出处:http://ylbtech.cnblogs.com/
本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。
相关文章
相关标签/搜索