这是相对于虚拟机而言的对实体计算机的称呼,物理机提供虚拟机以硬件环境,有时候也称为"宿主"或"寄主"。

虚拟机: 指通过软件模拟的具有完整硬件系统功能的、运行在一个 "完全隔离环境" 中的完整计算机系统。

虚拟化:  是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上,同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。

容器化:容器化是一种虚拟化技术,又称操作系统层虚拟化。这种技术将 "操作系统内核" 虚拟化,可以允许用户空间软件实例(instances)被分割成几个独立的单元,在内核中运行,而不是只有一个单一实例运行。

这个软件实例,也被称为是一个容器(containers)。对于每一个容器拥有者都认为他们使用的服务器程序是自己一个人专用、独享的。容器技术是虚拟化的一种,docker 是现今容器技术的事实标准。

简单举例比喻:物理机就好比你的庄园,其中的房子、喷泉、花园都是你独享的,别人访问不到,也享受不到。

相反,虚拟机就像开发商的一块楼盘。一栋栋单元楼对应一户户人家,它们之间是隔离的!但其中的小区设施、花园都是共享的,所有户主都可以使用。

容器就好比 1 个房子里面,开辟出来一个又一个的胶囊公寓共享这套房子的卫生间、共享厨房、共享 WiFi,只有衣服、电脑等私人物品是你自己的。

二、为什么需要虚拟化、容器化?

从上述举的现实生活中的例子来看,虚拟化、容器化的主要目的是资源隔离。那么资源隔离有什么大的收益吗?

① 资源利用率高

将利用率较低的服务器资源进行整合,用更少硬件资源运行更多业务降低 IT 支出和
运维管理成本。

例如: 尽管你的庄园很大,非常得富丽堂皇,可是如果你是一个人住或者几个人住,土地的使用率肯定是不高的,但你付出的维护成本一定大于那栋栋楼盘。

② 环境标准化

一次构建,随处执行。实现执行环境的标准化发布,部署和运维。由于开发环境、测试环境、生产环境不一致,导致有些bug 并未在开发过程中被发现。由此,确保了应用运行环境一致性
后也就会减少这类恼人问题的出现。

③ 资源弹性伸缩

根据业务情况,动态调整计算、存储、网络等硬件及软件资源。例如开售楼盘,你可以一次性开售完,也可以先开售几个观察观察情况,可是你一旦卖出了庄园,就真的再也没有了。

容器化扩展优点:

④ 差异化环境提供

虚拟化技术可以将一台计算机虚拟为多台逻辑计算机,也就是说多台虚拟机可以配备不同的执行环境。

⑤ 沙箱安全

为避免不安全或不稳定软件对系统安全性、稳定性造成影响,可使用虚拟化技术构建虚拟执行环境。因为虚拟化技术构建虚拟执行环境具有隔离性,不会影响别人在该服务器上部署的进程、服务。

⑥ 容器对比虚拟机更轻量,启动更快

传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运
行于宿主内核,无需启动完整的操作系统。大大的节约了开发、测试、部署的时间。

⑦ 维护和扩展容易

Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。

三、 虚拟化实现方式

学过操作系统的友子应该对 应用程序执行环境分层很熟悉:

(1) 虚拟化常见类别

存在于 ”硬件层和操作系统层间” 的虚拟化技术,虚拟机通过“伪造”一个硬件抽象接口,将一个操作系统以及操作系统层以上的层嫁接到硬件上,实现和真实物理机几乎一样的功能。
比如,我这台机器上面有一个VMWare软件,可以在WIndows系统上使用Linux Centos7虚拟机。

存在于 "操作系统层和函数库层" 之间的虚拟化技术。容器通过“伪造”操作系统的接口,将函数库层以上的功能置于操作系统上。

简单来说,如果虚拟机是把整个操作系统封装隔离,从而实现跨平台应用的话。那么容器
则是把一个个应用单独封装隔离,从而实现跨平台应用。所以容器体积比虚拟机小很多,理论上占用资源更少。

JVM 之类的虚拟机:

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

(2) 常见虚拟化实现

主机虚拟化(虚拟机)实现:

主机虚拟化的原理是通过在物理服务器上安装一个虚拟化层来实现。这个虚拟化层可以在物理服务器和客户操作系统之间建立虚拟机,使得它们可以独立运行。

从软件框架的角度上,根据 虚拟化层 "直接位于硬件之上" 还是在 "一个宿主操作系统之
上" ,将虚拟化划分为 Type1 和 Type2。

Type1 类的虚拟Hypervisor直接运行在硬件之上,没有宿主机操作系统,Hypervisor 直接控制硬件资源和客户机。Type2 类的Hypervisor运行在一个宿主机操作系统之上,作为宿主机操作系统中的一个应用程序,客户机就是在宿主机操作系统上的一个进程。

注: Hypervisor是一种系统软件,它充当 计算机硬件和虚拟机 之间的中介,负责有效地分配和利用由各个 虚拟机使用的硬件资源 ,这些虚拟机在物理主机上单独工作,因此,Hypervisor 也称为虚拟机管理器。

容器虚拟化实现:

容器虚拟化实现原理: 容器虚拟化,有别于主机虚拟化,是 “操作系统层” 的虚拟化。需要通过 namespace(命名空间) 进行各程序的隔离,加上 cgroups 进行资源的控制,以此来进行虚拟化。

三、容器虚拟化基础之NameSpace

到这里我们总算步入正题,以上都是介绍了很多概念性的东西,当然这也是理解Docker技术的基础。

(1) 什么是 Namespace(命名空间)?

你没看错,Linux系统中也有Namespace命名空间。C++中也有命名空间也是以相同的英文单词namespace,只不过它是为了保证类域名不污染的作用。那么Linux中的Namespace是啥的呢?

namespace 是 Linux 内核用来隔离内核资源的方式。通过 namespace 可以让一些 进程只能看到与自己相关的一部分资源 ,而 另外一些进程也只能看到与它们自己相关的资源 ,这两拨进程根本就感觉不到对方的存在。具体的实现方式是把一个或多个进程的相关资源放在同一namespace中。
Linux namespaces 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前namespace里的进程,对其他 namespace 中的进程没有影响。

(2) namepaces参数

Linux 提供了多个 API 用来操作 namespace,它们是 clone()、 setns() 和 unshare() 函
数,为了确定隔离的到底是哪项 namespace,在使用这些 API 时,通常需要指定一些调用参数。

namespace 系统调用给参数 被隔离的全局系统资源
UTS CLONE_NEWUTS 主机名和域名
IPC CLONE_NEWIPC 信号量、消息队列、共享内存
PID CLONE_NEWPID 进程编号
NetWork CLONE_NEWNET 网络设备、网络栈、端口等
Mount CLONE_NEWNS 文件系统挂在点
User CLONE_NEWUSER 用户和用户组

以上命名空间在容器环境下的隔离效果:

● 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。

想想如何进行隔离呢?

首先容器进程与进程之间需要隔离,所以需要 PID 隔离。

② 首先容器 A 进程不能读取容器 B 进程通讯内容需要隔离信号量等,所以需要 IPC隔离。

③ 首先容器 A 进程不能读取容器 B 进程的文件,所以需要 Mount 隔离。

④ Docker 允许用户在主机和容器间共享文件夹,同时不需要限制容器的访问权限,这就容易让容器突破资源限制。 需要借助用户空间来完成用户之间的隔离。

四、空间隔离实战

(1) 基础知识

dd命令详解:

Linux下的dd命令用于读取、转换并输出数据。dd 可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。

dd option

参数 作用
if=文件名;of=文件名

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

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

ibs\obs\bs = bytes 一次读入\输出\读入与输出 bytes 个字节.
cbs=bytes 一次转换 bytes 个字节,即指定转换缓冲区大小.
skip=blocks 从 输入 文件开头跳过 blocks 个块后再开始复制.
seek=blocks 从 输出 文件开头跳过 blocks 个块后再开始复制.
count=blocks 仅拷贝 blocks 个块,块大小等于 ibs 指定的字节数.
conv=<关键字>

关键字可以有以下 11:

▪ conversion:用指定的参数转换文件。
▪ ascii:转换 ebcdic 为 ascii
▪ ebcdic:转换 ascii 为 ebcdic
▪ ibm:转换 ascii 为 alternate ebcdic
▪ block:把每一行转换为长度为 cbs,不足部分用空格填充
▪ unblock:使每一行的长度都为 cbs,不足部分用空格填充
▪ lcase:把大写字符转换为小写字符
▪ ucase:把小写字符转换为大写字符
▪ swap:交换输入的每对字节
▪ noerror:出错时不停止
▪ notrunc:不截短输出文件
▪ sync:将每个输入块填充到 ibs 个字节,不足部分用空(NUL)字符补齐。

示例1: 生成一个镜像文件

/dev/zero:是一个特殊的文件,当你读它的时候,它会提供无限的空字符。

bs: 8k = 8 * 1024

count: 块数 该文件的最终大小为 count * bs ≈ 80M

示例2: 将一个文件里的字符转为大写字符

mkfs命令详解:

用于在设备上创建 Linux 文件系统,俗称格式化,比如我们使用 U 盘的时候可以格式化。
语法:

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

参数 作用
-V 详细显示模式
-t fstype 指定要建立何种文件系统,例如ext3,ext4
fs -options 传递给具体文件系统的参数
filesys 指定创建文件系统的文件名
blocks 指定文件系统的磁盘块数

示例: 格式化镜像文件为ext4

df命令详解:

df 命令用于显示目前在 Linux 系统上的文件系统磁盘使用情况统计。

df [option] ... [file] ...

常见参数 作用

-a\--all

包含所有的具有 0 Blocks 的文件系统.
-h, --human-readable 使用人类可读的格式(预设值是不加这个选项的...).
-H, --si 同-h相像 但是用 1000 为单位而不是用 1024.
-t, --type=TYPE 限制列出文件系统的 TYPE.
-T, --print-type 显示文件系统的形式.

示例:查看磁盘使用情况\磁盘的系统类型

mount 命令详解:

mount 命令用于加载文件系统到指定的加载点,此命令的也常用于 "挂载光盘" ,使我们可以访问光盘中的数据,因为你将光盘插入光驱中, Linux 并不会自动挂载 ,必须使用 mount 命令来手动完成挂载。

Linux 系统下不同目录可以 ”挂载不同分区和磁盘设备” ,它的目录和磁盘分区是分离的,可以自由组合(通过挂载)。不同的目录数据可以跨越不同的磁盘分区或者不同的磁盘设备。

挂载的实质是为磁盘添加入口。

mount [-l]

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

常见参数 作用
-l 显示已加载的文件系统列表
-t 加载文件系统类型支持常见系统类型的 ext3,ext4,iso9660,tmpfs,xfs 等,大部分情况可以不指定, mount 可以自己识别
-o options

主要用来描述设备或档案的挂接方式:

loop:用来把一个文件当成硬盘分区挂接上系统
ro:采用只读方式挂接设备

rw:采用读写方式挂接设备

device 要挂接(mount)的设备
dir 挂载点的目录

示例: 将镜像文件挂载到 /mnt/目录下,需要确保挂载的目录是存在的

unshare 命令详解:

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

unshare [options] program [arguements]

参数 作用
i,--ipc 不共享ipc空间
-m,--mount 不共享Mount空间
-n,--net 不共享Net空间
-p,--pid 不共享PID空间
-u,--uts 不共享UTS空间
-U,--user 不共享用户
-V,--version 版本查看
--fork 执行unshare的进程fork一个子进程,在子进程中执行unshare传入的参数

--mount-porc

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

示例: 实现hostname隔离

(2) 实战一 PID隔离

在主机上执行 ps -ef,可以看到进程列表如下,其中启动进程 PID 1 为 init 进程.

当我们查看该Namespace下的 /proc目录文件是这样的:

其中记录着大量与当前进程相关进程的信息。

如何实现PID隔离呢?

我们打开另外一个 shell ,执行下面命令创建一个 bash 进程并且,新建一个 PID Namespace。

unshare --fork --pid --mount-proc /bin/bash

● --fork:新建了一个 bash 进程。如果不建新进程,新的 namespace 会用 unshare的 PID 作为新的空间的父进程(pid=1),但unshare进程并不在新的namespace当中,而是在当前的namespace当中。

● --pid:表示我们的进程隔离的是 pid,而其他命名空间没有隔离。

● mount-proc:Linux 下的每个进程都有一个对应的 /proc/PID,创建一个新的 PID namespace 后,如果想让子进程中的 top、 ps 等依赖 "/proc 文件系统" 的命令工作,就需要挂载 /proc 文件系统。而文件系统隔离是 mount namespace 管理的,所以 linux特意提供了一个选项--mount-proc 来解决这个问题。如果不带这个我们看到的进程还是系统的进程信息。

执行 ps -ef 查看进程信息,我们可以看到此时进程空间内的内容已经变,而且启动进程也变成了我们的 bash 进程。说明我们已经看不到主机上的进程空间了,我们的进程空间发生了隔离。

执行 exit 退出进程。


(3) 实战二Mount 隔离

打开一个shell 窗口 A,执行命令, df -h ,查看主机默认命名空间的磁盘挂载情况。



再打开一个新的 shell 窗口 B,执行 Mount 隔离命令:

unshare --mount --fork /bin/bash

注:--fork\--mount不解释

在窗口 B 中添加新的磁盘挂载.

dd if=/dev/zero of=fdimage.img bs=8k count=1024

mkfs -t ext4 ./fdimage.img

文章目录一、什么是 Kubernetes ?二、Kubernetes 基本概念1、集群 Cluster2、节点 Node3、命名空间 Namespace 4、 容器 Container5、调度单位 Pod6、标签 Label/Selector7、副本集 ReplicaSet8、服务 Service9、发布 Deployment10、配置管理 ConfigMap/Secret11、守护进程 DaemonSet12、数据卷 Volume13、PersistentVolume/PersistentVolumeClai 基于 Linux 内核的 Namespace (命名空间)机制 namespace linux 自带的功能,用来隔离内核资源的机制,如进程pid,主机名与域名,网络设备端口等。 什么是 容器 容器 其实就是一个 虚拟化 的独立的沙箱环境,和宿主机或者其他的 容器 之间是独立隔离的,他有自己的网络环境,用户权限,进程pid等。 容器 是依托于一个物理机或者一个虚拟机的,在此之上可以有多个 容器 容器 之间是感受不到彼此的存在的,在网络中可以被看做是一个独立的个体存在 而 namespace 起到的作用就是让资源之间互相隔离,成为 [test@localhost ~]$ sudo unshare -u /bin/bash [sudo] password for test: [root@localhost test]# hostname localhost.localdomain [root@localhost test]# hostname test.localdomain [root@localhost test]# hostname Linux Namespace 是内核的一个特性,它可以隔离一部分系统资源,使得一个进程及其子进程在 Namespace 内部有一个独立的全局视图,看到的资源与外部系统的全局资源是隔离的。这使得在 Namespace 内的进程能够运行在一个被隔离和安全的环境中,就像在一个独立的系统中一样。 Linux Namespace 是一种强大而灵活的轻量级 虚拟化 技术,它使得我们可以在同一台机器上运行多个隔离的进程或应用程序,而无需额外的 虚拟化 开销。 在操作系统中命名空间命名空间提供的是系统资源的隔离,其中系统资源包括了:进程、网络、文件系统等等实际上 linux 系统实现命名空间主要目的之一就是为了实现轻量级 虚拟化 服务,也就是我们说的 容器 ,在同一个命名空间下的进程可以感知彼此的变化,而对其他命名空间的进程一无所知,这样就可以让 容器 中的进程产生一个错觉,仿佛它自己置身于一个独立的系统环境当中,以此达到独立和隔离的目的。 Linux namespace (名字空间)的作用就是“隔离内核资源”。在 Linux 的世界里,文件系统挂载点、主机名、 Namespace (命名空间)技术是一种内核级别的特性,它允许将全局系统资源隔离成独立的视图,使得在不同 Namespace 中运行的进程看到的资源是不同的。这为 容器 化技术提供了 基础 ,使得多个进程或 容器 可以在同一台主机上独立运行而不会相互干扰。 容器 中的命名空间( Namespace )是一种用于隔离和分割不同 容器 之间和 容器 与主机操作系统之间资源的技术。命名空间是 Linux 内核提供的一种特性, 容器 技术(如Docker和Kubernetes)利用这些命名空间来实现 容器 的隔离和资源管理。 由于2016年年中调换工作的原因,对 容器 网络的研究中断过一段时间。随着当前项目对Kubernetes应用的深入,我感觉之前对于 容器 网络的粗浅理解已经不够了, 容器 网络成了摆在前面的“一道坎”。继续深入理解K8s网络、 容器 网络已经势在必行。而这篇文章就算是一个重新开始,也... Bridge 桥接模式的实现步骤主要如下: (1) Docker Daemon 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备,假设为 veth0 和 veth1。而... 5 容器 网络命名空间ubuntu@ubuntu:~$ docker network ls NETWORK ID NAME DRIVER 0343830c6572 bridge bridge de6616e5b5e4 host host 一般来说, 容器 技术主要包括Cgroup和 Namespace 这两个内核特性。 CgroupCgroup是control group,又称为控制组,它主要是做资源控制。原理是将一组进程放在放在一个控制组里,通过给这个控制组分配指定的可用资源,达到控制这一组进程可用资源的目的。 Namespace Namespace 又称为命名空间,它主要做访问隔离。其原理是针对一类资源进行抽象,并将其封装在一起提供给一