什么是容器

对于容器这个词,大部分人第一时间想到的肯定是生活中常见瓶瓶罐罐,用来装水的东西。它给人的第一感觉就是能 “装”。

而在 IT 领域,Container 就被直译为容器,但 Container 本身是集装箱的意思,容器属于中国人的信雅达叫法。

可以想象一下,如果容器技术改为集装箱技术,档次一下就低了。但是为了帮助我们更好的理解容器,集装箱的翻译才能体现它的本质:

规格标准化,层层堆叠,互相隔离,将各类零散的货物分门别类,形成统一的形状,提升运输效率,降低管理成本,保护了货物的完整性。

在早期,IT 领域就是通过借鉴这一思想,研发出了 hypervisor 虚拟化,将不同操作系统的虚拟机通过 hypervisor(KVM、XEN 等)来衍生、运行、销毁。

但随着时间推移,用户也发现了 hypervisor 存在的问题:

每次部署发布都得搞一个完整操作系统和附带的依赖环境,而用户其实更关注自己部署的应用,这导致了任务变重和性能低下。

而容器的目的就在于实现底层操作系统和环境的复用,达到类似以下效果:

将一辆兰博基尼(应用),打包放到一个集装箱里(容器),通过货轮轻而易举的将它从上海码头(CentOS 环境)运送到纽约码头(Ubuntu 环境)。在运输期间,兰博基尼(应用)没有受到任何的损坏,在纽约码头卸货后依然可以完美风骚的飙车(启动正常)。

容器的原理

Linux Container 容器技术,简称 LXC,是一种 轻量级的操作系统层虚拟化技术,它的诞生(2008 年)解决了 IT 世界里的 “集装箱运输” 问题。

为了实现容器进程对外界的隔离,容器底层主要运用了 名称空间(Namespaces)控制组(Control groups)切根(Change to root)

名称空间(Namespaces)

每个运行的容器都有自己的名称空间(诞生于 2002 年),它主要用于实现资源的隔离。

Linux 操作系统默认提供了以下 6 个常用的 Namespace 的 API:

  • PID Namespace:提供进程隔离能力。

    • 在 Linux 系统中,有一个 PID 为 1 的进程(init/systemd)是其他所有进程的父进程。在每个容器内也要有一个父进程来管理其下属的子进程。
    • 不同容器就是通过 PID Namespace 隔离的,不同的名称空间中可以有相同的 pid。
  • MNT Namespace:提供磁盘挂载点和文件系统的隔离能力。
    • 每个容器都要有独立的根文件系统用户空间,以实现在容器里面启动服务并且使用容器的运行环境。
    • 在容器里面不能访问宿主机的资源,宿主机使用了 chroot 技术把容器锁定到一个指的运行目录里面。
    • 例如:宿主机是 ubuntu,里面启动一个 Centos 容器,并在容器里启动一个 Nginx,该 Nginx 运行时使用的运行环境就是 Centos 系统目录的运行环境。
  • IPC Namespace:提供进程间通信的隔离能力。
    • 允许一个容器内的不同进程的(内存,缓存等)数据访问,但是不能跨容器访问其他容器的数据 。
    • 容器中进程交互还是采用 Linux 常见的进程交互方法(interprocess communication,IPC)。
  • Net Namespace:提供网络隔离能力。
    • 每一个容器都类似于虚拟机一样有自己的网络设备,IP地址,路由表,/proc/net 目录等。
    • 以 docker 为例,使用 network namespace 启动一个 vethX 接口,这样你的容器将拥有它自己的桥接 IP 地址,通常是docker0。
  • UTS Namespace:提供主机名隔离能力。
    • UNIX Time-sharing System 允许容器拥有独立的 hostname 和 domain name,使其在网络上能被视作一个独立节点而非主机的一个进程。
  • User Namespace:提供用户隔离能力。
    • 每个容器可以有不同的用户和组 id,也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。

控制组(Control groups)

简称 Cgroups,是 Linux 内核提供的一种可以限制、记录、隔离进程组的物理资源的机制,由 Google 贡献,2007 年合并到 Linux Kernel。

因为 Namespace 只能改变进程的视觉范围,不能真实地对资源做出限制,所以就需要用到 Cgroup 技术。以防止某个容器把宿主机资源全部用完导致其它容器也宕掉。

在 Linux 的 /sys/fs/cgroup 目录中有 cpu、memory、devices、net_cls 等目录,可以按需修改相应的配置文件来设置某个进程 ID 对物理资源的最大使用率。

切根(Change to root)

简称 chroot,用于改变一个程序运行时参考的根目录位置,让不同容器在不同的虚拟根目录下工作,从而相互不直接影响。

容器的特点

想要更好的理解容器的特点,就需要拿跟它跟硬件抽象层虚拟化 hypervisor 技术做对比。

主要的区别如下:

  1. 本质上来看,虚拟机是通过 Hypervisor 虚拟化硬件,然后在上安装不同的操作系统,而容器是宿主机上运行的不同进程。
  2. 用户体验上来看,虚拟机是重量级的,系统本身占用的物理资源多,启动时间长。而容器则相反。
  3. 隔离性上来看,虚拟机隔离的更彻底,容器则要差一些。

比较得出容器主要包含以下几个特点:

  1. 极其轻量:只打包了必要的 bin/lib。
  2. 秒级部署:根据镜像的不同,容器的部署大概在毫秒与秒之间。
  3. 易于移植:一次构建,到处运行

容器发展史

虽然现在提到容器,大家就想到 docker,但事实上容器是从 1979 年的 Chroot 开始的。而 docker 是在 2013 年才开始推出第一个版本。具体历程如下:

  • 1979 年,chroot:一套 Unix 操作系统,为每个进程提供一个隔离化的磁盘空间。
  • 2000 年,FreeBSD Jails:与 chroot 类似,增加了进程的沙箱,对制作资源进行隔离。
  • 2001 年,Linux Vserver:每个分区被称为一套安全上下文,其中虚拟化系统被称为一套虚拟私有服务器。
  • 2004 年,Solaris 容器:将系统资源控制与分区提供的边界结合,各分区在单一的操作系统实例之内。
  • 2005 年,OpenVZ:安装有补丁的 Linux 内核实现虚拟化,隔离能力,资源管理以及检查点交付。
  • 2006 年,Process 容器:对整套进程集合中的资源使用量进行限制,分配与隔离。
  • 2007 年,Control Groups:谷歌实现的 Cgroups,后被合并到 Linux 内核中。
  • 2008 年,LXC:通过 liblxc 库交付,提供可与 Python,Lua,Go 等语言对接的 API。
  • 2011 年,Warden:不与 Linux 紧密耦合,以后台进程方式运行,并提供 API 以实现容器管理。
  • 2013 年,Docker:目前最流行的容器引擎,具备完整的生态系统。
  • 2014 年,Rocket:由 CoreOS 开发,专门用于解决 docker 中存在的缺陷。
  • 2016 年,Windows 容器:docker 能够在 Windows 平台上运行。

容器标准化

docker 是容器,但容器并不只有 docker。

任何技术出现都需要一个标准来规范它,不然各搞各的很容易导致技术实现的碎片化,出现大量的冲突和冗余。所以,在 2015 年,由 Google,Docker、CoreOS、IBM、微软、红帽等厂商联合成立了 OCI(Open Container Initiative) 组织,并于 2016 年 4 月推出了第一个开放容器标准。其主要内容包括 runtime 运行时标准image 镜像标准

该标准的推出,保障了市场的稳定性,让企业能放心采用容器技术,用户在打包、部署应用程序后,可以自由选择不同的容器 Runtime。同时,镜像打包、建立、认证、部署、命名也都能按照统一的规范来做。

两种标准主要包含以下内容:

容器运行时标准 (runtime spec)

规定了容器的基本操作规范。

  1. creating:使用 create 命令创建容器,这个过程称为创建中。
  2. created:容器创建出来,但是还没有运行,表示镜像和配置没有错误,容器能够运行在当前平台。
  3. running:容器的运行状态,里面的进程处于 up 状态,正在执行用户设定的任务。
  4. stopped:容器运行完成,或者运行出错,或者 stop 命令之后,容器处于暂停状态。这个状态,容器还有很多信息保存在平台中,并没有完全被删除。

容器镜像标准(image spec)

定义镜像的基本格式。

  1. 文件系统:以 layer 保存的文件系统,每个 layer 保存了和上层之间变化的部分,layer 应该保存哪些文件,怎么表示增加、修改和删除的文件等。
  2. config 文件:保存了文件系统的层级信息,以及容器运行时需要的一些信息,指定了镜像在某个特定平台和系统的配置。
  3. manifest 文件:镜像的 config 文件索引,有哪些 layer,额外的 annotation 信息,还保存了很多和当前平台有关的信息。
  4. index 文件:可选的文件,指向不同平台的 manifest 文件,这个文件能保证一个镜像可以跨平台使用,每个平台拥有不同的 manifest 文件。

01. DOCKER - 容器技术的更多相关文章

  1. 【转帖】一文看懂docker容器技术架构及其中的各个模块

    一文看懂docker容器技术架构及其中的各个模块 原创 波波说运维 2019-09-29 00:01:00 https://www.toutiao.com/a6740234030798602763/ ...

  2. docker容器技术基础入门

    目录 docker容器技术基础入门 容器(Container) 传统虚拟化与容器的区别 Linux容器技术 Linux Namespaces CGroups LXC docker基本概念 docker ...

  3. 微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发.部署.运维管理.持续开发持续集成的流程 ...

  4. 新书发布《每天5分钟玩转Docker容器技术》

    后台不时收到关于纸质版教程书籍的询问,今天终于可以给大家一个交代了. <每天5分钟玩转Docker容器技术>现已在各大书城上架. 比较了一下,目前京东上最实惠:https://item.j ...

  5. 如何安装和配置 Rex-Ray?- 每天5分钟玩转 Docker 容器技术(74)

    Rex-Ray 是一个优秀的 Docker volume driver,本节将演示其安装和配置方法. Rex-Ray 以 standalone 进程的方式运行在 Docker 主机上,安装方法很简单, ...

  6. 配置 VirtualBox backend - 每天5分钟玩转 Docker 容器技术(75)

    Rexy-Ray 支持多种 backend,上一节我们已经安装配置了 Rex-Ray,今天演示如何配置 VirtualBox backend. 在 VirtualBox 宿主机,即我的笔记本上启动 v ...

  7. 创建 Rex-Ray volume - 每天5分钟玩转 Docker 容器技术(76)

    前面我们安装部署了 Rex-Ray,并且成功配置 VirtualBox backend,今天演示如何创建和使用 Rex-Ray volume. 在 docker1 或 docker2 上执行如下命令创 ...

  8. 跨主机使用 Rex-Ray volume - 每天5分钟玩转 Docker 容器技术(77)

    上一节我们在 docker1 上的 MySQL 容器中使用了 Rex-Ray volume mysqldata,更新了数据库.现在容器已经删除,今天将演示在 docker2 中重新使用这个卷. 在 d ...

  9. Docker 最常用的监控方案 - 每天5分钟玩转 Docker 容器技术(78)

    当 Docker 部署规模逐步变大后,可视化监控容器环境的性能和健康状态将会变得越来越重要. 在本章中,我们将讨论几个目前比较常用的容器监控工具和方案,为大家构建自己的监控系统提供参考. 首先我们会讨 ...

随机推荐

  1. 微信小程序绑定函数如何携带参数

    一开始以为微信小程序的语法是和VUE的语法一样的,直接@click="click(field)",结果却不是这样的 在微信小程序中我们需要设置一个 data-set ,然后在绑定的 ...

  2. 浅谈stm32的外部中断

    简述 本文简单介绍stm32外部中断的一般操作步骤,后续会补充外部中断的相关内容 stm32的中断控制器支持19个外部中断/事件请求: line0~line15:这16条line分别对应不同GPIO口 ...

  3. Hadoop(四)C#操作Hbase

    Hbase Hbase是一种NoSql模式的数据库,采用了列式存储.而采用了列存储天然具备以下优势: 可只查涉及的列,且列可作为索引,相对高效 针对某一列的聚合及其方便 同一列的数据类型一致,方便压缩 ...

  4. 逆向进阶,利用 AST 技术还原 JavaScript 混淆代码

    什么是 AST AST(Abstract Syntax Tree),中文抽象语法树,简称语法树(Syntax Tree),是源代码的抽象语法结构的树状表现形式,树上的每个节点都表示源代码中的一种结构. ...

  5. golang get process name by pid

    一个很好的问题:How golang to get process name by process id (pid)? 目前看来go api并没有提供通过pid获取进程名称的方法,可以通过 /proc ...

  6. SpringBoot从0到0.7——第二天

    SpringBoot从0到0.7--第二天 今天来搭建一个登陆界面进行跳转,不带有数据库,看似就很简单的一个界面,却让我学习了好长时间去了解学习他的原理,能看懂的话还是尽量去看源码. 首先创建一个项目 ...

  7. 零基础学Java第五节(面向对象一)

    本篇文章是<零基础学Java>专栏的第五篇文章,文章采用通俗易懂的文字.图示及代码实战,从零基础开始带大家走上高薪之路! 本文章首发于公众号[编程攻略] 类与对象 在哲学体系中,可以分为主 ...

  8. 709. To Lower Case - LeetCode

    Question 709. To Lower Case Sollution 题目大意:字符串大写转小写 思路: 直接调用Java API函数 字符串转char数组,遍历数组,判断如果大写就转小写 Ja ...

  9. 缓存&PWA实践

    缓存&PWA 实践 一.背景 从上一篇<前端动画实现与原理分析>,我们从 Performance 进行动画的性能分析,并根据 Performance 分析来优化动画.但,前端不仅仅 ...

  10. 解锁!玩转 HelloGitHub 的新姿势

    本文不会涉及太多技术细节和源码,请放心食用 大家好,我是 HelloGitHub 的老荀,好久不见啊! 我在完成 HelloZooKeeper 系列之后,就很少"露面了".但是我对 ...