概念

物理机:直接在物理服务器(带 CPU、内存、硬盘、网卡的硬件)上安装操作系统(如 CentOS、Windows Server),然后在系统上直接部署应用(如 Java 服务、MySQL),没有任何虚拟化 / 隔离层。

虚拟化:在物理机硬件和操作系统之间,加一层 “虚拟化层(Hypervisor)”,把一台物理机 “分割” 成多个独立的 “虚拟服务器(虚拟机)”,每个虚拟机有自己独立的操作系统、硬件资源(虚拟 CPU / 内存 / 硬盘),应用跑在虚拟机的系统里。

容器化:基于 Linux 内核的 Namespace(隔离)和 cgroups(限制)技术,在同一台物理机 / 虚拟机的操作系统内核上,创建多个 “容器”—— 每个容器是独立的运行环境,但共享宿主机的内核,无需单独安装操作系统,应用和依赖被打包在容器镜像里运行。

三者之间的对比:

维度

物理机

虚拟化(虚拟机)

容器化

隔离粒度

无隔离(整台机器)

操作系统级(虚拟机)

进程级(容器)

资源开销

10%-20%(Hypervisor+OS)

<5%(内核层)

启动速度

系统启动速度(分钟级)

虚拟机启动(分钟级)

秒级

资源分配

固定(整台机器)

预先分配(固定值)

动态分配(弹性)

镜像 / 模板

虚拟机模板(体积大)

容器镜像(体积小)

性能

最高

较高(略低于物理机)

接近物理机

用一个简单的例子来类比:

现在有一块地皮,开发商配置之后搭建了整块宅基地,而搭建的水电以及土地本身就是硬件,那么带上硬件的整块地皮就是物理机

开发商开始为这块地皮进行地块的划分,并打算在这些地块上搭建楼房,开发商搭建了很多楼栋,这些楼栋都分别分配了单独的物业管理人员和水电,此时这里的每一栋楼就是一台虚拟机

而楼栋中会分割出楼层以及独户,这里的独户共享这个楼栋的土地和水电系统,只不过每家每户都是独立的,互不影响,都有单独的门牌号,这里的每一个独户就是一个容器

虚拟化常见类别

虚拟机

存在于硬件层和操作系统层间的虚拟化技术。虚拟机通过“伪造”一个硬件抽象接口, 将一个操作系统以及操作系统层以上的层嫁接到硬件上,实现和真实物理机几乎一样 的功能。比如我们在一台 Windows 系统的电脑上使用 Android 虚拟机,就能够用这台 电脑打开 Android 系统上的应用。

容器

存在于操作系统层和函数库层之间的虚拟化技术。容器通过“伪造”操作系统的接口, 将函数库层以上的功能置于操作系统上。以 Docker 为例,其就是一个基于 Linux 操作 系统的 Namespace 和 Cgroup 功能实现的隔离容器,可以模拟操作系统的功能。简单 来说,如果虚拟机是把整个操作系统封装隔离,从而实现跨平台应用的话,那么容器 则是把一个个应用单独封装隔离,从而实现跨平台应用。所以容器体积比虚拟机小很 比特就业课 多,理论上占用资源更少。容器化就是应用程序级别的虚拟化技术。容器提供了将应 用程序的代码、运行时、系统工具、系统库和配置打包到一个实例中的标准方法。容 器共享一个内核(操作系统),它安装在硬件上。

JVM之类的虚拟机

存在于函数库层和应用程序之间的虚拟化技术。Java 虚拟机同样具有跨平台特性,所 谓跨平台特性实际上也就是虚拟化的功劳。我们知道 Java 语言是调用操作系统函数库 的,JVM 就是在应用层与函数库层之间建立一个抽象层,对下通过不同的版本适应不 同的操作系统函数库,对上提供统一的运行环境交给程序和开发者,使开发者能够调 用不同操作系统的函数库。

容器虚拟化实现

容器虚拟化,有别于主机虚拟化,是操作系统层的虚拟化。通过 namespace 进行各程 序的隔离,加上 cgroups 进行资源的控制,以此来进行虚拟化。

Namespace

namespace 是 Linux 内核用来隔离内核资源的方式。通过 namespace 可以让一些进 程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的 资源,这两拨进程根本就感觉不到对方的存在。具体的实现方式是把一个或多个进程 的相关资源指定在同一个 namespace 中。

基础命令

dd

# 需要注意的是, = 表示的是键值对,不能出现空格
dd [选项] if=输入源 of=输出目标 [bs=块大小] [count=块数]

参数(必选)

含义

if=输入源

输入文件名,默认为标准输入.即指定源文件

of=输出目标

输出文件名,默认为标准输出.即指定目的文件

bs=块大小

同时设置输入和输出的块大小,单位为字节

count=块数

输入和输出的块数量,即只拷贝n个块,文件总大小为:bs*count

其中.img是镜像文件

除了这些还有其他的可选参数

参数(可选)

含义

ibs=块大小

一次读取的字节数(块大小),优先于bs

obs=块大小

一次写入的块大小,优先于bs

skip=N

输入时,先跳过N个块才开始读取

seek=N

输出时,先跳过N个块才开始写入

oflag=direct

直接写入磁盘

iflag=direct

直接读取磁盘

conv=参数

用于数据转换

其中conv参数有以下十一种关键字

关键字

作用

conversion

用指定的参数转换文件

ascii

将ebcdic转为ascii

ebcdic

将ascii转换为ebcdic

ibm

将ascii转换为alternate ebcdic

block

将输入中的换行符(\n)转换为 “回车 + 换行”(\r\n),并按 ibs 对齐块

unblock

将输入中的 “回车 + 换行”(\r\n)转换为换行符(\n),取消块对齐

lcase

将大写字符全部转换为小写字符

ucase

将小写字符全部转换为大写字符

swab

交换每两个字节的顺序(字节序转换)

noerror

读取时遇到错误不终止,继续处理后续数据(仅跳过错误块)

notrunc

写入输出文件时,不截断文件原有内容(仅覆盖对应位置,剩余内容保留)

sync

为输入数据补充空字符(\0),使每个数据块大小对齐 ibs(输入块大小)

mkfs:磁盘分区格式化工具

mkfs [-V] [-t fstype] [fs -options] filesys [blocks]

参数

作用

-t fstype

指定要建立的文件系统类型,默认为ext2

-V

显示详细模式

fs -options

传递给具体的文件系统的参数

filesys

指定要创建的文件系统对应的设备文件名

blocks

指定文件系统的磁盘块数

df:查看磁盘空间使用情况

df [选项] [文件/目录/设备]
  • 无参数:默认显示所有已挂载的文件系统(除特殊伪文件系统如 tmpfs);

  • 指定文件 / 目录:显示该文件 / 目录所在分区的空间信息;

  • 指定设备:显示该设备(分区)的空间信息。

参数

作用

-a,--all

显示所有的文件系统,包含0blocks的

-h,--human-readable

使用人类可读的格式,1024格式

-H

也是人类可读,但是是1000格式

-t,--type=TYPE

限制列出文件系统的TYPE

-T,--print-type

显示文件系统的形式

mount:文件挂载

mount用于将格式化好的文件系统(磁盘分区)关联到 Linux 目录树的某个指定目录(挂载点),让操作系统能通过这个目录访问分区里的文件

Linux不会自动进行挂载,需要手动使用mount命令进行挂载

mount [-l]
mount [-t vfstype] [-o options] device dir

参数

作用

-l

显示已加载的文件系统列表

-t

加载文件系统类型支持常见的系统类型

-o options

主要用来描述设备或者档案的挂载方式

  • loop:用来把一个文件当成硬盘分区挂载上系统

  • ro:采用只读方式挂载设备

  • rw:采用读写方式挂载设备

device

要挂载的设备

dir

挂载点的目录

重新格式化

创建一个新文件,作为目标挂载点

挂载文件

unshare:创建隔离的 Linux 环境

主要是使用与父程序不共享的名称空间运行程序

unshare [option] program [arguments]

参数

作用

-i,--ipc

不共享IPC空间

-m,--mount

不共享mount空间

-n,--net

不共享Net空间

-p,--pid

不共享PID空间

-u,--uts

不共享UTS空间

-U,--user

不共享用户

-V,--version

版本查看

--fork

在创建新 Namespace 后,先 fork 一个子进程,再在这个子进程中执行指定的命令 / 启动 shell,因为新的 PID Namespace 必须由 “子进程” 来承载

--mount-proc

执行子进程之前,先将proc挂载过去

更多推荐