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

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 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容器直接暴露至公网。


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

目录
相关文章
|
27天前
|
监控 Kubernetes 安全
还没搞懂Docker? Docker容器技术实战指南 ! 从入门到企业级应用 !
蒋星熠Jaxonic,技术探索者,以代码为笔,在二进制星河中书写极客诗篇。专注Docker与容器化实践,分享从入门到企业级应用的深度经验,助力开发者乘风破浪,驶向云原生新世界。
还没搞懂Docker? Docker容器技术实战指南 ! 从入门到企业级应用 !
|
10天前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
19天前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
173 5
|
20天前
|
监控 Linux 调度
【赵渝强老师】Docker容器的资源管理机制
本文介绍了Linux CGroup技术及其在Docker资源管理中的应用。通过实例演示了如何利用CGroup限制应用程序的CPU、内存和I/O带宽使用,实现系统资源的精细化控制,帮助理解Docker底层资源限制机制。
107 6
kde
|
23天前
|
存储 关系型数据库 MySQL
MySQL Docker 容器化部署全指南
MySQL是一款开源关系型数据库,广泛用于Web及企业应用。Docker容器化部署可解决环境不一致、依赖冲突问题,实现高效、隔离、轻量的MySQL服务运行,支持数据持久化与快速迁移,适用于开发、测试及生产环境。
kde
218 4
|
关系型数据库 MySQL Linux
docker 实战练习1
docker基础操作11
1934 0
|
1月前
|
缓存 前端开发 Docker
Docker Layer Caching:加速你的容器构建
Docker Layer Caching:加速你的容器构建