【Docker】从技术架构到容器实战{空间隔离/资源控制/LXC容器/mount}
文章目录
- 一、为什么需要空间隔离?
- 为什么需要空间隔离?
- 空间隔离的实现:NameSpace
- 如何通过命令实现空间隔离?
- 1. **PID 隔离**
- 2. **Mount 隔离**
- 3. **UTS 隔离**
- 操作系统底层做了什么?
- 总结
- 二、概况总结
- 1. 技术架构演进之路
- 概述
- 常见概念
- 架构演进
- 2. 空间隔离实战
- NameSpace 隔离实战
- 3. 资源控制实战
- CGroups 资源控制实战
- 实战操作
- 4. LXC 容器实战
- LXC 容器操作实战
- 实战操作
- 总结
- 三、深入理解mount
- 具体实现
- 挂载(Mount)是什么?
- 挂载的文件系统类型
- 挂载的选项
- 总结
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/54039929f2b54503b19490de177d45d6.png)
一、为什么需要空间隔离?
为什么需要空间隔离?
在操作系统中,空间隔离(Namespace Isolation)是一种将系统资源进行逻辑隔离的技术。它的主要目的是为不同的进程或应用提供独立的运行环境,确保它们之间的资源互不干扰。空间隔离的需求主要来自以下几个方面:
-
资源隔离:在多用户或多任务环境中,不同的进程可能需要访问相同的系统资源(如文件系统、网络接口、进程ID等)。如果没有隔离机制,一个进程可能会影响其他进程的运行,甚至导致系统崩溃。
-
安全性:通过隔离,可以限制进程的访问权限,防止恶意进程或错误操作影响系统的其他部分。例如,一个容器中的进程无法访问宿主机的文件系统或其他容器的资源。
-
环境一致性:在开发和测试环境中,空间隔离可以确保每个应用或服务运行在独立的环境中,避免因环境差异导致的问题。
-
资源管理:通过隔离,操作系统可以更好地管理和分配资源(如CPU、内存、网络带宽等),确保每个进程或容器都能获得所需的资源。
空间隔离的实现:NameSpace
Linux 内核通过 NameSpace 机制实现了空间隔离。NameSpace 是一种将全局系统资源进行隔离的技术,每个 NameSpace 中的资源都是独立的,不同 NameSpace 中的进程无法直接访问彼此的资源。
常见的 NameSpace 类型包括:
- PID Namespace:隔离进程ID,每个 NameSpace 中的进程有独立的 PID。
- Mount Namespace:隔离文件系统挂载点,每个 NameSpace 可以有不同的文件系统视图。
- Network Namespace:隔离网络接口、IP 地址、路由表等网络资源。
- UTS Namespace:隔离主机名和域名。
- IPC Namespace:隔离进程间通信(IPC)资源,如消息队列、共享内存等。
- User Namespace:隔离用户和用户组 ID,允许非特权用户在 NameSpace 内拥有特权。
如何通过命令实现空间隔离?
在 Linux 中,可以通过 unshare
命令创建新的 NameSpace,并运行一个进程在该 NameSpace 中。
1. PID 隔离
通过 unshare
命令创建新的 PID NameSpace,隔离进程 ID。
unshare --fork --pid --mount-proc /bin/bash
--fork
:创建一个新的子进程,确保新进程在新的 NameSpace 中运行。--pid
:创建新的 PID NameSpace,隔离进程 ID。--mount-proc
:挂载/proc
文件系统,确保新 NameSpace 中的进程可以看到自己的进程信息。
操作系统做了什么?
- 创建了一个新的 PID NameSpace,新 NameSpace 中的进程 ID 从 1 开始。
- 挂载了
/proc
文件系统,确保新 NameSpace 中的进程可以看到自己的进程信息。 - 新 NameSpace 中的进程无法看到宿主机的进程信息,实现了进程 ID 的隔离。
2. Mount 隔离
通过 unshare
命令创建新的 Mount NameSpace,隔离文件系统挂载点。
unshare --mount --fork /bin/bash
--mount
:创建新的 Mount NameSpace,隔离文件系统挂载点。--fork
:创建一个新的子进程,确保新进程在新的 NameSpace 中运行。
操作系统做了什么?
- 创建了一个新的 Mount NameSpace,新 NameSpace 中的文件系统挂载点是独立的。
- 在新 NameSpace 中挂载的文件系统不会影响宿主机的文件系统。
- 新 NameSpace 中的进程只能看到自己挂载的文件系统,实现了文件系统的隔离。
3. UTS 隔离
通过 unshare
命令创建新的 UTS NameSpace,隔离主机名和域名。
unshare -u /bin/bash
-u
:创建新的 UTS NameSpace,隔离主机名和域名。
操作系统做了什么?
- 创建了一个新的 UTS NameSpace,新 NameSpace 中的主机名和域名是独立的。
- 在新 NameSpace 中修改主机名不会影响宿主机的主机名。
- 新 NameSpace 中的进程只能看到自己设置的主机名和域名,实现了主机名和域名的隔离。
操作系统底层做了什么?
当执行 unshare
命令时,操作系统会进行以下操作:
-
创建新的 NameSpace:根据命令参数,操作系统会创建一个新的 NameSpace(如 PID、Mount、UTS 等),并将该 NameSpace 与当前进程关联。
-
资源隔离:在新的 NameSpace 中,系统资源(如进程 ID、文件系统挂载点、主机名等)会被隔离,确保新 NameSpace 中的资源与宿主机或其他 NameSpace 中的资源互不干扰。
-
挂载文件系统:对于 Mount NameSpace,操作系统会挂载新的
/proc
文件系统,确保新 NameSpace 中的进程可以看到自己的进程信息。 -
启动新进程:在新的 NameSpace 中启动指定的进程(如
/bin/bash
),该进程只能访问新 NameSpace 中的资源。
总结
空间隔离通过 NameSpace 机制实现了系统资源的逻辑隔离,确保不同的进程或应用运行在独立的环境中,互不干扰。通过 unshare
命令,可以创建新的 NameSpace,并运行进程在该 NameSpace 中。操作系统在底层通过创建新的 NameSpace、隔离资源、挂载文件系统等操作,实现了资源的隔离和管理。
空间隔离是容器技术(如 Docker)的基础,它使得容器可以在独立的运行环境中运行,确保容器的安全性和资源管理的灵活性。
二、概况总结
1. 技术架构演进之路
概述
在学习技术的过程中,许多读者缺乏中大型系统的实际经验,导致难以从全局理解一些概念。本文通过一个“电子商务”应用的例子,介绍从一百个到千万级并发情况下服务端的架构演进过程,并列举每个阶段的相关技术,帮助大家对架构演进有一个整体的认知。
常见概念
- 应用(Application)/ 系统(System):为了完成一整套服务的一个程序或一组相互配合的程序群。
- 模块(Module)/ 组件(Component):将应用中具有清晰职责、内聚性强的部分抽象出来,便于理解。
- 分布式(Distributed):系统中的多个模块部署在不同服务器上,通过网络通信完成任务。
- 集群(Cluster):多个服务器上的组件共同完成特定目标,整体称为集群。
- 主(Master)/ 从(Slave):集群中,主节点承担更多职责,从节点承担附属职责。
- 中间件(Middleware):提供不同应用程序之间通信的软件,充当不同技术、工具和数据库之间的桥梁。
- 容器(Docker):开源的应用容器引擎,允许开发者打包应用及其依赖到一个可移植的镜像中。
- 容器编排(K8S):Kubernetes,用于管理云平台中多个主机上的容器化应用。
架构演进
- 单机架构:初期用户访问量少,系统架构简单,适合单机部署。
- 应用数据分离架构:随着访问量增加,将数据库服务独立部署,提升系统承载能力。
- 应用服务集群架构:通过水平扩展,增加应用服务器,引入负载均衡分担流量。
- 读写分离 / 主从分离架构:数据库读写分离,主库负责写操作,从库负责读操作,减轻数据库压力。
- 引入缓存 —— 冷热分离架构:通过缓存热点数据,减少数据库访问压力。
- 垂直分库:按照业务将数据分别存储,提升数据库性能。
- 业务拆分 —— 微服务:将业务拆分为多个微服务,独立维护和部署。
- 容器化引入——容器编排架构:通过 Docker 和 Kubernetes 实现容器的动态扩缩容,提升资源利用率。
2. 空间隔离实战
NameSpace 隔离实战
- 实战目的:了解隔离能力由操作系统内核提供,而非 Docker。
- 基础知识:
- dd 命令:读取、转换和输出数据。它可以对磁盘、分区、文件等进行直接操作。操作系统会分配磁盘空间,并将数据直接写入磁盘,绕过文件系统缓存。
- mkfs 命令:用于在设备上创建 Linux 文件系统。擦除设备上的所有数据,并创建一个新的文件系统,直接操作磁盘分区或设备文件,初始化文件系统的元数据(如 inode 表、超级块等)。
- df 命令:显示文件系统磁盘使用情况。
- mount 命令:加载文件系统到指定挂载点。
- unshare 命令:使用与父程序不共享的名称空间运行程序。
unshare是命令也是系统调用
创建新的 NameSpace,并运行进程在该 NameSpace 中。它是一个底层的系统隔离工具。
unshare 可以隔离系统资源(如进程 ID、文件系统、网络等),如果使用不当,可能会导致进程无法访问系统资源。
当执行 unshare 命令时,操作系统会创建一个新的 NameSpace,并将当前进程移动到该 NameSpace 中。unshare --pid --fork /bin/bash
会创建一个新的 PID NameSpace,并在其中运行一个新的 Bash 进程。
操作系统会隔离指定的资源(如进程 ID、文件系统挂载点等),并确保新 NameSpace 中的进程无法访问其他 NameSpace 的资源。
3. 资源控制实战
CGroups 资源控制实战
- 实战目的:了解操作系统如何通过 CGroups 控制 CPU 和内存资源。
- 基础知识:
- pidstat:监控进程的 CPU、内存、IO 等资源占用情况。
- stress:Linux 压力测试工具,可对 CPU、内存、IO 等进行压力测试。
实战操作
- cgroups 信息查看:查看系统支持的 cgroups 版本和子系统。
- 使用 cgroups 对内存进行控制:通过 cgroups 限制进程的内存使用。
- 使用 cgroups 对 CPU 进行控制:通过 cgroups 限制进程的 CPU 使用率。
4. LXC 容器实战
LXC 容器操作实战
- 实战目的:通过 LXC 创建容器,了解 Docker 并非容器的唯一实现。
- 基础知识:
- lxc-checkconfig:检查系统环境是否满足容器使用要求。
- lxc-create:创建 LXC 容器。
- lxc-start:启动容器。
- lxc-ls:列出所有容器。
- lxc-info:查看容器信息。
- lxc-attach:进入容器执行命令。
- lxc-stop:停止容器。
- lxc-destroy:删除容器。
实战操作
- 检查 LXC 是否运行:通过
systemctl status lxc
检查 LXC 服务状态。 - 创建 LXC 容器:使用
lxc-create
命令创建容器。 - 启动和查看容器:通过
lxc-start
启动容器,并使用lxc-ls
查看容器状态。 - 进入容器:通过
lxc-attach
进入容器执行命令。 - 停止和删除容器:通过
lxc-stop
停止容器,使用lxc-destroy
删除容器。
总结
通过本课程,我们了解了从单机架构到微服务、容器化的技术演进过程,掌握了如何通过 NameSpace 和 CGroups 实现资源隔离和控制,并通过 LXC 容器实战深入理解了容器的基本操作。Docker 和 Kubernetes 的出现极大地简化了容器的管理和部署,使得容器化技术在全球范围内得到了广泛应用。
三、深入理解mount
mount
命令是 Linux 和类 Unix 系统中用于将文件系统(无论是物理的还是虚拟的)挂载到一个目录的操作。挂载是指将一个设备或存储介质(例如磁盘、分区、网络文件系统等)连接到文件系统树中的某个目录,从而使得文件系统中的数据可以通过该目录访问。
具体实现
当你使用 mount
命令时,系统会执行以下操作:
-
设备识别:你指定的设备或分区(例如
/dev/sda1
、/dev/nvme0n1p1
等)会被识别并检查其文件系统类型(如 ext4、xfs、ntfs 等)。 -
挂载点选择:你指定的目录(挂载点)会成为该设备的入口。挂载点是一个目录,挂载后的设备会覆盖该目录,使得所有对该目录的访问都变成对设备中数据的访问。
-
文件系统挂载:
- 如果是一个 物理设备(如磁盘分区),系统会将该设备的文件系统与目录树连接起来。
- 如果是 虚拟文件系统(如
proc
、sysfs
等),系统会将虚拟设备挂载到某个目录,这些虚拟文件系统提供了内核和系统状态的信息。
-
更新系统视图:操作系统的文件系统表(通常是
/etc/mtab
或/proc/mounts
)会被更新,记录挂载信息。 -
资源访问:挂载后,用户可以通过指定的挂载点访问文件系统的内容。例如,挂载一个外部硬盘到
/mnt/usb
目录后,用户可以通过访问/mnt/usb
来读取外部硬盘中的数据。
挂载(Mount)是什么?
挂载是将一个存储设备或一个文件系统(无论是物理的还是虚拟的)与现有的文件系统树连接的过程。在 Linux 中,文件系统是一个树状结构,所有的设备和分区都通过挂载点连接到这个树上。操作系统会通过挂载点来访问和管理文件数据。
例子:
假设你有一个硬盘分区 /dev/sdb1
,你可以通过以下命令将该分区挂载到 /mnt/mydisk
目录上:
sudo mount /dev/sdb1 /mnt/mydisk
这时,/mnt/mydisk
目录就会显示出 /dev/sdb1
分区中的文件内容。当你访问 /mnt/mydisk
目录时,实际上是访问的硬盘分区中的文件。
挂载的文件系统类型
挂载时可以指定文件系统类型(-t
选项),如:
sudo mount -t ext4 /dev/sdb1 /mnt/mydisk
如果没有指定,系统会尝试自动检测文件系统类型。
挂载的选项
mount
命令还可以接受一些其他的选项来控制挂载的行为,例如:
-o loop
:用于挂载 ISO 文件或其他镜像文件。-o ro
:以只读模式挂载设备。-o rw
:以读写模式挂载设备。
sudo mount -o loop myimage.iso /mnt/iso
这将挂载一个 ISO 文件到 /mnt/iso
目录。
总结
挂载的核心概念就是将一个设备或文件系统连接到现有的文件系统树中。这样,你就能够通过一个目录来访问存储设备上的文件,而不需要直接与设备打交道。通过 mount
命令,操作系统允许动态地管理不同的文件系统和设备,而用户可以透明地访问这些存储介质。