Docker 简介
什么是虚拟化、容器化
物理机:实际的服务器或者计算机。相对于虚拟机而言的对实体计算机的称呼。物理 机提供给虚拟机以硬件环境,有时也称为"寄主"或"宿主"。
虚拟化:是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上 同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都 可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。
容器化:容器化是一种虚拟化技术,又称操作系统层虚拟化(Operating system level virtualization),这种技术将操作系统内核虚拟化,可以允许用户空间软件实例 (instances)被分割成几个独立的单元,在内核中运行,而不是只有一个单一实例运 行。这个软件实例,也被称为是一个容器(containers)。对每个实例的拥有者与用户 来说,他们使用的服务器程序,看起来就像是自己专用的。容器技术是虚拟化的一种。 docker 是现今容器技术的事实标准。
举例
物理机,就像一个庄园,独立占用了一块土地,花园都是自己的,其他人无法共 享使用。
虚拟机相当于开发商的一个楼盘,一栋楼一套房子一户人家,共享一块宅基地,共享小区的花园,共享小区的游乐设施。
容器相当于在 1 个房子里面,开辟出来一个又一个的胶囊公寓,共享这套房子的卫生 间、共享厨房、共享 WiFi ,只有衣服、电脑等私人物品是你自己的。
为什么要虚拟化、容器化?
我们从之前的历史发展来看,虚拟化和容器化的最主要目的就是资源隔离,随着资源隔离的实现逐渐也带来了更大的收益。
• 资源利用率高
将利用率较低的服务器资源进行整合,用更少硬件资源运行更多业务,降低 IT 支出和 运维管理成本。
比如我们的土地直接复用,使用这块土地的人多了,但是成本还是庄园那块地。
• 环境标准化
一次构建,随处执行。实现执行环境的标准化发布,部署和运维。开发过程中一个常 见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境, 确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类 问题。
• 资源弹性伸缩
根据业务情况,动态调整计算、存储、网络等硬件及软件资源。比如遇到双 11 了,把 服务扩容 100 个,双 11 过去了, 把扩容的 100 个收回去。
• 差异化环境提供
同时提供多套差异化的执行环境,限制环境使用资源。 比如我的服务一个以来 Ubuntu 操作系统,一个服务依赖 CentOS 操作系统,但是没 有预算购买两个物理机,这个时候容器化就能很好的提供多种不同的环境。

• 沙箱安全
为避免不安全或不稳定软件对系统安全性、稳定性造成影响,可使用虚拟化技术构建 虚拟执行环境。
比如我在容器里面执行 rm -rf /* 不会把整个服务器搞死,也不影响其他人部署的程序 使用
• 容器对比虚拟机更轻量,启动更快
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时 间。大大的节约了开发、测试、部署的时间。
docker 不需要虚拟内核,所以启动可以更快,相当于 windows 的开机时间省去了。
• 维护和扩展容易
Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得 应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外, Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接 在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成 本。比如 docker hub 提供了很多镜像,各个系统的一个命令就可以拿到了,研发也可以自己定制镜像分享给各个产品
虚拟化实现方式
应用程序执行环境分层

硬件层:提供硬件抽象,包括指令集架构、硬件设备及硬件访问接口
操作系统层 :提供系统调用接口,管理硬件资源
程序库层:提供数据结构定义及函数调用接口
虚拟化常见类别
虚拟机
存在于硬件层和操作系统层间的虚拟化技术。虚拟机通过"伪造"一个硬件抽象接口, 将一个操作系统以及操作系统层以上的层嫁接到硬件上,实现和真实物理机几乎一样 的功能。比如我们在一台 Windows 系统的电脑上使用 Android 虚拟机,就能够用这台 电脑打开 Android 系统上的应用。
容器
存在于操作系统层和函数库层之间的虚拟化技术。容器通过"伪造"操作系统的接口, 将函数库层以上的功能置于操作系统上。以 Docker 为例,其就是一个基于 Linux 操作 系统的 Namespace 和 Cgroup 功能实现的隔离容器,可以模拟操作系统的功能。简单 来说,如果虚拟机是把整个操作系统封装隔离,从而实现跨平台应用的话,那么容器 则是把一个个应用单独封装隔离,从而实现跨平台应用。所以容器体积比虚拟机小很多,理论上占用资源更少。容器化就是应用程序级别的虚拟化技术。容器提供了将应 用程序的代码、运行时、系统工具、系统库和配置打包到一个实例中的标准方法。容器共享一个内核(操作系统),它安装在硬件上。
JVM 之类的虚拟机
存在于函数库层和应用程序之间的虚拟化技术。Java 虚拟机同样具有跨平台特性,所 谓跨平台特性实际上也就是虚拟化的功劳。我们知道 Java 语言是调用操作系统函数库 的,JVM 就是在应用层与函数库层之间建立一个抽象层,对下通过不同的版本适应不 同的操作系统函数库,对上提供统一的运行环境交给程序和开发者,使开发者能够调用不同操作系统的函数库。
常见虚拟化实现
主机虚拟化(虚拟机)实现
主机虚拟化的原理是通过在物理服务器上安装一个虚拟化层来实现。这个虚拟化层可 以在物理服务器和客户操作系统之间建立虚拟机,使得它们可以独立运行。
从软件框架的角度上,根据虚拟化层是直接位于硬件之上还是在一个宿主操作系统之 上,将虚拟化划分为 Type1 和 Type2.
Type1 类的 Hypervisor(Hypervisor 是一种系统软件,它充当计算机硬件和虚拟机之间 的中介,负责有效地分配和利用由各个虚拟机使用的硬件资源,这些虚拟机在物理主 机上单独工作,因此,Hypervisor 也称为虚拟机管理器。)直接运行在硬件之上,没有 宿主机操作系统,Hypervisor 直接控制硬件资源和客户机。典型框架为 Xen、Vmware ESX。

Type2 类的 Hypervisor 运行在一个宿主机操作系统之上(Vmware Workstation)或者 系统里面,Hypervisor 作为宿主机操作系统中的一个应用程序,客户机就是在宿主机操 作系统上的一个进程
容器虚拟化实现
容器虚拟化实现原理
容器虚拟化,有别于主机虚拟化,是操作系统层的虚拟化。通过 namespace 进行各程 序的隔离,加上 cgroups 进行资源的控制,以此来进行虚拟化。

容器虚拟化基础之 NameSpace
什么是 Namespace(命名空间)
namespace 是 Linux 内核用来隔离内核资源的方式。通过 namespace 可以让一些进程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的 资源,这两拨进程根本就感觉不到对方的存在。具体的实现方式是把一个或多个进程 的相关资源指定在同一个 namespace 中。
Linux namespaces 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的 进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前 namespace 里的进程,对其他 namespace 中的进程没有影响。
Linux 提供了多个 API 用来操作 namespace,它们是 clone()、setns() 和 unshare() 函 数,为了确定隔离的到底是哪项 namespace,在使用这些 API 时,通常需要指定一些
调用参数:CLONE_NEWIPC、CLONE_NEWNET、CLONE_NEWNS、 CLONE_NEWPID、CLONE_NEWUSER、CLONE_NEWUTS 和 CLONE_NEWCGROUP。如果要同时隔离多个 namespace,可以使用 | (按位或)组合 这些参数。
| namespace | 系统调用参数 | 被隔离的全局系统资源 | 引入内核版本 |
|---|---|---|---|
| UTS | CLONE_NEWUTS | 主机名和域名 | 2.6.19 |
| IPC | CLONE_NEWIPC | 信号量、消息队列和共享内存 -- 进程间通信 | 2.6.19 |
| PID | CLONE_NEWPID | 进程编号 | 2.6.24 |
| Network | CLONE_NEWNET | 网络设备、网络栈、端口等 | 2.6.29 |
| Mount | CLONE_NEWNS | 文件系统挂载点 | 2.4.19 |
| User | CLONE_NEWUSER | 用户和用户组 | 3.8 |
以上命名空间在容器环境下的隔离效果:
UTS:每个容器能看到自己的 hostname,拥有独立的主机名和域名。
IPC:同一个 IPC namespace 的进程之间能互相通讯,不同的 IPC namespace 之间 不能通信。
PID:每个 PID namespace 中的进程可以有其独立的 PID,每个容器可以有其 PID 为 1 的 root 进程。
Network:每个容器用有其独立的网络设备,IP 地址,IP 路由表,/proc/net 目录,端口号。
Mount:每个容器能看到不同的文件系统层次结构。
User:每个 container 可以有不同的 user 和 group id。
想想以下如果我们要隔离两个进程需要怎么办?
(1)首先容器进程与进程之间需要隔离,所以需要 PID 隔离
(2)首先容器 A 进程不能读取容器 B 进程通讯内容需要隔离信号量等,所以需要 IPC 隔离
(3)首先容器 A 进程不能读取容器 B 进程的文件,所以需要 Mount 隔离
(4)首先容器 A 进程不能读取容器 B 进程的 socket,所以需要网络隔离、主机隔离
(5)Docker 允许用户在主机和容器间共享文件夹,同时不需要限制容器的访问权限, 这就容易让容器突破资源限制。需要借助用户空间来完成用户之间的隔离。
感谢你的观看,期待我们下次再见!