Docker容器实战(六) - Docker是如何实现隔离的?(上)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: Docker容器实战(六) - Docker是如何实现隔离的?(上)

1 Namespace

1.1 容器为何需要进程隔离

  • 被其他容器修改文件,导致安全问题
  • 资源的并发写入导致不一致性
  • 资源的抢占,导致其他容器被影响
docker run -it --name demo_docker busybox /bin/sh
/ # ps -ef

image.png

在宿主机查看进程ID

ps -ef|grep busybox

真实的 docker 容器 pid

image.png

这就是进程资源隔离表象:

  • 对于宿主机 docker run 启动的只是一个进程,它的pid是44451
  • 而容器程序本身被隔离了,容器的内部都只能看到自己内部的进程
  • 这其实是基于Linux的Namespace技术(即使是 Windows 版本的 Docker 也是依托于 Windows 实现的类似Namespace的技术)

1.2 Linux Namespace

Linux 命名空间对全局操作系统资源进行了抽象,对于命名空间内的进程来说,他们拥有独立的资源实例,在命名空间内部的进程可以实现资源可见。

对于命名空间外部的进程,则不可见,实现了资源的隔离。这种技术广泛的应用于容器技术里。


Namespace实际上修改了应用进程看待整个计算机“视图”,即它的“视线”被操作系统做了限制,只能“看到”某些指定的内容。对于宿主机来说,这些被“隔离”了的进程跟其他进程并没有区别。

1.3 Docker Engine 使用了如下 Linux 的隔离技术

  • The pid namespace:管理 PID namespace (PID: Process ID)
  • The net namespace: 管理网络namespace(NET: Networking)
  • The ipc namespace: 管理进程间通信命名空间(IPC: InterProcess Communication)
  • The mnt namespace:管理文件系统挂载点命名空间(MNT: Mount).
  • The uts namespace: Unix 时间系统隔离(UTS: Unix Timesharing
    System).

1.4 进程资源隔离原理

Linux Namespaces是Linux创建新进程时的一个可选参数,在Linux系统中创建进程的系统调用是clone()方法。

int clone(int (*fn) (void *),void *child stack,
int flags, void *arg, . . .
/* pid_ t *ptid, void *newtls, pid_ t *ctid */ ) ;

通过调用该方法,这个进程会获得一个独立的进程空间,它的pid是1 ,并且看不到宿主机上的其他进程,也就是在容器内执行PS命令的结果。


不应该把Docker Engine或者任何容器管理工具放在跟Hypervisor相同的位置,因为它们并不像Hypervisor那样对应用进程的隔离环境负责,也不会创建任何实体的“容器”,真正对隔离环境负责的是宿主机os:


1.png

image.png

该对比图应该把Docker画在跟应用同级别并且靠边的位置。

用户运行在容器里的应用进程,跟宿主机上的其他进程一样,都由宿主机操作系统统一管理,只不过这些被隔离的进程拥有额外设置过的Namespace参数,Docker在这里更多的是辅助和管理工作。

这也解释了


为何Docker项目比虚拟机更好?

使用虚拟化技术作为应用沙盒,就必须由Hypervisor负责创建虚拟机,这个虚拟机是真实存在的,它里面必须运行一个完整的Guest OS才能执行用户的应用进程。这就不可避免地带来额外的资源消耗和占用。


据实验,一个运行着CentOS的KVM虚拟机启动后,在不做优化的情况下,虚拟机自己就需要占用100~200 MB内存。此外,用户应用运行在虚拟机里面,它对宿主机操作系统的调用就不可避免地要经过虚拟化软件的拦截和处理,这本身又是一层性能损耗,尤其对计算资源、网络和磁盘I/O的损耗非常大。


而容器化后的用户应用,依然还是宿主机上的一个普通进程,这就意味着这些因为虚拟化而带来的性能损耗都不存在。

使用Namespace作为隔离手段的容器无需单独的Guest OS,使得容器额外的资源占用可忽略不计。


“敏捷”和“高性能”是容器相较于虚拟机最大的优势。


有利必有弊,基于 Namespace 的隔离机制相比虚拟化技术也有很多不足。


1.5 Namespace的缺点

隔离不彻底

多容器间使用的还是同一宿主机os内核

尽管可在容器里通过 Mount Namespace 单独挂载其他不同版本的os文件,比如 CentOS 或者 Ubuntu,但这并不能改变共享宿主机内核的事实!

所以不可能在Windows宿主机运行Linux容器或在低版本Linux宿主机运行高版本Linux容器。

而拥有硬件虚拟化技术和独立Guest OS的虚拟机,比如Microsoft的云计算平台Azure,就是运行于Windows服务器集群,但可在其上面创建各种Linux虚拟机。


Linux内核很多资源无法被Namespace

最典型的比如时间。

若你的容器中的程序使用settimeofday(2)系统调用修改时间,整个宿主机的时间都会被随之修改,这并不符合用户预期。

而相比于在虚拟机里可自己随便折腾,在容器里部署应用时,“什么能做,什么不能做”,用户都必须考虑。


尤其是共享宿主机内核:


容器给应用暴露出来的攻击面是相当大的

应用“越狱”难度也比虚拟机低得多。

尽管可使用Seccomp等技术,过滤和甄别容器内部发起的所有系统调用来进行安全加固,但这就多了一层对系统调用的过滤,一定会拖累容器性能。默认情况下,也不知道到底该开启哪些系统调用,禁止哪些系统调用。

所以,在生产环境中,无人敢把运行在物理机上的Linux容器直接暴露至公网。


基于虚拟化或者独立内核技术的容器实现,则可以比较好地在隔离与性能之间做出平衡。

目录
相关文章
|
2天前
|
存储 Docker 容器
docker中挂载数据卷到容器
【10月更文挑战第12天】
15 5
|
7天前
|
存储 运维 云计算
探索Docker容器化:从入门到实践
在这个快速发展的云计算时代,Docker容器化技术正在改变应用的开发、部署和管理方式。本文旨在为初学者提供一个关于Docker的全面入门指南,并通过实践案例展示Docker在实际开发中的应用。我们将一起了解Docker的核心概念、基本操作、网络和存储,以及如何构建和部署一个简单的Web应用。无论你是开发者还是运维人员,本文都会帮助你快速掌握Docker的核心技能。
|
4天前
|
存储 测试技术 开发者
docker中将数据卷挂载到容器
【10月更文挑战第11天】
15 3
|
4天前
|
缓存 运维 Docker
容器化运维:Docker Desktop 占用磁盘空间过大?教你轻松解决!
Windows Docker Desktop 使用过程中,因镜像、容器数据及构建缓存的累积,可能导致磁盘空间占用过高。通过删除无用镜像与容器、压缩磁盘以及清理构建缓存等方法,可有效释放空间。具体步骤包括关闭WSL、使用`diskpart`工具压缩虚拟磁盘、执行`docker buildx prune -f`清理缓存等。这些操作能显著减少磁盘占用,提升系统性能。
|
3天前
|
存储 应用服务中间件 云计算
深入解析:云计算中的容器化技术——Docker实战指南
【10月更文挑战第14天】深入解析:云计算中的容器化技术——Docker实战指南
16 1
|
2天前
|
存储 Kubernetes 监控
深入探索Docker容器化技术的奥秘
【10月更文挑战第15天】深入探索Docker容器化技术的奥秘
12 0
|
3天前
|
运维 Kubernetes 监控
掌握Docker容器化技术:构建、部署与管理的高效实践
【10月更文挑战第14天】掌握Docker容器化技术:构建、部署与管理的高效实践
12 0
|
3天前
|
前端开发 Docker 容器
主机host服务器和Docker容器之间的文件互传方法汇总
Docker 成为前端工具,可实现跨设备兼容。本文介绍主机与 Docker 容器/镜像间文件传输的三种方法:1. 构建镜像时使用 `COPY` 或 `ADD` 指令;2. 启动容器时使用 `-v` 挂载卷;3. 运行时使用 `docker cp` 命令。每种方法适用于不同场景,如静态文件打包、开发时文件同步及临时文件传输。注意权限问题、容器停止后的文件传输及性能影响。
|
5天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
17 0