深入解析:Docker 容器如何实现文件系统与资源的多维隔离?

目录

    • 一、RootFs
      • 1. Docker 镜像与文件系统层
      • 2. RootFs 与容器隔离的意义
    • 二、Linux Namespace
      • 1. 进程命名空间
        • 1.1 `lsns` 命令说明
        • 1.2 查看“祖先进程”命名空间
        • 1.3 查看当前用户进程命名空间
      • 2. 容器进程命名空间
        • 2.1 查看容器进程命名空间列表
        • 2.2 容器进程命名空间的具体体现
    • 三、cgroups
      • 1. cpu 子系统
        • 1.1 CFS (Completely Fair Scheduler)
        • 1.2 RT (Real-time Scheduler)
        • 1.3 示例
      • 2. cpuset 子系统
      • 3. cpuacct 子系统
      • 4. memory 子系统
        • 示例
      • 5. blkio 子系统
      • 6. devices 子系统
      • 7. freezer 子系统
      • 8. net_cls 子系统
      • 9. net_prio 子系统
      • 10. perf_event
      • 11. hugetlb
    • 总结

一、RootFs

在传统的 Linux 系统中,rootfs(根文件系统)就是系统的“根”目录,一般位于 /,其下包含 /bin/dev/etc 等常见目录结构。
在容器中,则通过镜像(Image)+**容器层(Container Layer)**的组合来提供容器自身的根文件系统,这个容器的根文件系统就是rootfs,与宿主机的 rootfs 相对隔离。

1. Docker 镜像与文件系统层

  • **镜像(Image)**由多层只读层(read-only layers)构成,利用了 Union FS 或 OverlayFS 等联合文件系统技术。
  • **容器层(Container Layer)**是该镜像之上的可写层(read-write layer)。容器运行时,对文件的修改都会写入到这个容器层中,不会影响只读层的内容。

2. RootFs 与容器隔离的意义

  • 当启动一个容器时,容器看到的“根文件系统”并非与宿主机相同,而是来自镜像 + 容器层组合形成的 rootfs。
  • 对于容器内部的进程来说,/ 就是容器自身的根目录,与宿主机的 / 相互独立(尽管底层还是同一个内核)。
  • 这种文件系统级别的隔离为容器提供了和宿主机隔离的外观,不同容器之间也不会直接污染彼此的文件系统。

二、Linux Namespace

Linux Namespace 是容器隔离的核心机制之一。Namespace 的主要作用是将系统资源进行“分名字空间”隔离,如进程(PID)、网络(NET)、文件系统挂载(MOUNT)、用户(USER)、IPC 等,从而让容器“以为”它拥有自己独立的环境。
在这里插入图片描述

1. 进程命名空间

1.1 lsns 命令说明
  • lsns 是 Linux 提供的一个查看系统中命名空间信息的命令。可以用 lsns 查看当前系统里所有命名空间,如 lsns -t pid 可以查看 PID 命名空间,lsns -t net 查看网络命名空间等。
  • 常见列示信息包含:
    • NS TYPE: 命名空间类型(如 pidnetmntutsipcuser 等)。
    • NSID: 命名空间 ID,一般可以在 /proc/pid/ns 路径中看到相应符号链接。
    • PID: 对应的进程号。
    • Command: 该命名空间对应进程的启动命令。
1.2 查看“祖先进程”命名空间

在 Linux 中,每个进程都有对应的命名空间引用(指针)。如果想要查看某个进程(比如 PID=1 或者宿主机上的某个 PID)的命名空间,可以通过:
列出系统所有命名空间

sudo lsns --output0all

在这里插入图片描述

ls -l /proc/<PID>/ns

这会展示对应的符号链接,比如:

lrwxrwxrwx 1 root root 0 Jan  1 00:00 /proc/1/ns/pid -> pid:[4026531836]

这样就能看到 pid:[4026531836] 对应的命名空间 ID。通常 PID=1(系统的 init 或 systemd)会在宿主机的最初始 namespace 中。

1.3 查看当前用户进程命名空间

直接对你当前 shell 的 PID 进行查看:

echo $$
# 假设输出为 12345
ls -l /proc/12345/ns

就能看到你当前 shell 进程所使用的 namespace。

2. 容器进程命名空间

容器之所以能够让其内部进程彼此隔离,主要原因之一是 Docker(或其他容器运行时)在启动容器进程时,会为该进程创建或加入单独的命名空间(PID/NET/IPC/UTS 等)。

2.1 查看容器进程命名空间列表

假设我们有一个正在运行的容器,可以先找到容器对应的“容器进程”:

docker ps
docker inspect <container_id> | grep "Pid"

然后拿到对应的 PID,比如是 23456。接着:

ls -l /proc/23456/ns

就能看到容器进程使用的所有 namespace 绑定信息。

2.2 容器进程命名空间的具体体现
  • PID Namespace
    容器内部查看到的进程号(PID)从 1 开始,而在宿主机上,这个容器的进程是一个完全不同的 PID 值。容器内部的“PID=1”通常是容器内的 init 进程。
  • Network Namespace
    容器有自己单独的网卡配置(如 eth0),与宿主机是隔离的。通过容器的 network namespace,可以将容器网络与宿主机网络解耦(或进行端口映射)。
  • Mount Namespace
    容器有自己挂载的文件系统视图,比如 / 是容器自己的 rootfs。与宿主机的挂载点不同。
  • IPC Namespace
    容器之间的共享内存、消息队列等 IPC 机制互不影响。
  • UTS Namespace
    容器可以有自己独立的 hostname。容器内 hostname 与宿主机可以不同。

借助这些命名空间,容器可以呈现一个与宿主机几乎隔离的操作系统视图。


三、cgroups

cgroups (control groups) 是 Linux 提供的另一项关键特性,用于对系统资源进行“配额、限制、监控、隔离”。Docker 容器通过将容器进程加入到相应的 cgroup,来限制其对 CPU、内存、IO 等资源的使用或进行统计。

cgroups 是一个可插拔的框架,常见的子系统包括:

  • cpu
  • cpuset
  • cpuacct
  • memory
  • blkio
  • devices
  • freezer
  • net_cls
  • net_prio
  • perf_event
  • hugetlb
    等。

下面分别简要介绍这些子系统在容器隔离中的作用或使用示例。

1. cpu 子系统

cpu 子系统主要用于限制或分配 CPU 时间片给某个 cgroup 内进程。让我们来看看常见的调度器和示例。

1.1 CFS (Completely Fair Scheduler)
  • Linux 默认的 CPU 调度器。可通过 cpu.sharescpu.cfs_period_uscpu.cfs_quota_us 等文件对 CPU 使用进行相对或绝对限额设置。
  • 例如要限制某个 cgroup 的进程只能使用“相当于一个 CPU 核心”的计算量,可以在 cpu.cfs_period_us = 100000(默认100ms)和 cpu.cfs_quota_us = 100000 之间做设置,这样就大致等价于 1 core。
1.2 RT (Real-time Scheduler)
  • RT 调度针对实时任务,可以用来做实时优先级的资源控制。不过容器中常见应用较少直接动用 RT 调度。
1.3 示例

在手动配置 cgroup 时,可能会:

  1. 创建目录:mkdir /sys/fs/cgroup/cpu/test_cgroup
  2. 写入一些限制:
    echo 200000 > /sys/fs/cgroup/cpu/test_cgroup/cpu.cfs_quota_us
    echo 100000 > /sys/fs/cgroup/cpu/test_cgroup/cpu.cfs_period_us
    
    表示此 cgroup 一次调度周期内(100ms),只能用 200ms CPU 时间,相当于可以使用 2 核的 CPU 时间。
  3. 把某个进程写入 tasks:
    echo <pid> > /sys/fs/cgroup/cpu/test_cgroup/tasks
    
    该进程的 CPU 使用就受限于此组的规则。

Docker 在启动容器时会自动做这些事情,如 --cpus--cpuset-cpus 等参数。

2. cpuset 子系统

  • cpuset 子系统允许指定某些 CPU 核、某些内存节点给特定的 cgroup。
  • 比如可以指定容器只能在 CPU 0 和 1 上运行,或者只能从 NUMA 节点0分配内存。
  • Docker 对应的参数是 --cpuset-cpus="0-1" 之类。

3. cpuacct 子系统

  • cpuacct 用于统计某个 cgroup 内进程的 CPU 使用情况(用户态、内核态占用总时长),只做统计不做限制。
  • Docker 可以通过这个子系统查看容器的 CPU 使用状态。

4. memory 子系统

memory 子系统用于限制和统计进程的内存使用,包括物理内存和 swap。

  • 常见的控制文件:
    • memory.limit_in_bytes:该 cgroup 最大物理内存限制。
    • memory.memsw.limit_in_bytes:物理内存 + swap 限制(如果启用 swap 记账)。
  • 通过设置这些值,可防止某些进程用光系统所有内存。
示例
  1. 创建 cgroup:mkdir /sys/fs/cgroup/memory/test_mem
  2. 设置限制:
    echo 524288000 > /sys/fs/cgroup/memory/test_mem/memory.limit_in_bytes  # 500MB
    
  3. 将进程加入:
    echo <pid> > /sys/fs/cgroup/memory/test_mem/tasks
    
    这样该进程占用内存在超过 500MB 时可能会触发 OOM(Out Of Memory)动作。

5. blkio 子系统

  • blkio (Block IO) 用于限制进程的块设备 IO 速率,比如磁盘读写速度。
  • 可以设置读取速率、写入速率的限制。对需要在容器层面做 IO QoS 的场景很有帮助。

6. devices 子系统

  • devices 子系统可以控制某个 cgroup 中的进程可以访问哪些设备、只能读或写、或完全禁止访问等。
  • 容器通常为了安全,会只允许访问少数必要设备(比如 /dev/null/dev/random 等)。

7. freezer 子系统

  • freezer 子系统提供了把 cgroup 内进程“冻结/解冻”的功能。
  • 可以把某个 cgroup 的状态设置为 FROZEN,则该组内所有进程都挂起,等到切回 THAWED 才继续运行。

8. net_cls 子系统

  • net_cls 可以为网络数据包打上一个分类标识(classid),配合 tc(traffic control)做网络流量整形或带宽控制。

9. net_prio 子系统

  • net_prio 子系统可以为 cgroup 中的进程设置网络优先级(priority),从而在同一台宿主机上的容器间做网络流量优先级区分。

10. perf_event

  • perf_event 子系统方便对一组进程进行性能计数器(performance counter)的监控,比如 CPU cycle、cache miss 等。

11. hugetlb

  • hugetlb 用于管理大页内存(Huge Pages)。可以限制某个 cgroup 使用多少大页内存。

总结

通过 RootFsLinux Namespacecgroups 的巧妙组合,Docker 容器能够在同一个 Linux 内核上运行,却拥有与宿主机和其他容器相对独立的文件系统、进程空间、网络环境、IPC、以及严格的资源配额/限制。这为容器提供了接近虚拟机的隔离性,同时也保留了“共享同一个内核”的优势(启动速度快、资源开销小等)。

  1. RootFs:让容器拥有独立的文件系统视图,与宿主机的根目录区分开来。
  2. Linux Namespace
    • PID Namespace 让容器内部进程有各自的 PID 视图。
    • Network Namespace 让容器拥有独立的虚拟网卡、网络栈。
    • Mount Namespace 让容器控制自己的挂载点。
    • UTS、IPC、User Namespace 等也实现其他层面的隔离。
  3. cgroups
    • 对 CPU、内存、IO 等进行资源限制和监控。
    • 通过 Docker 参数可很方便地指定容器的资源上限、优先级。

这些机制共同构成了 Docker 容器环境下的核心隔离限制手段,使得容器能够安全、稳定地在生产环境中运行各种应用。


参考:
0voice · GitHub

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/893504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习|表示学习|卷积神经网络|由参数共享引出的特征图|08

如是我闻&#xff1a; Feature Map&#xff08;特征图&#xff09;的概念与 Parameter Sharing&#xff08;参数共享&#xff09;密切相关。换句话说&#xff0c;参数共享是生成 Feature Map 的基础。Feature Map 是卷积操作的核心产物&#xff0c;而卷积操作的高效性正是由参数…

【Linux网络编程】传输层协议

目录 一&#xff0c;传输层的介绍 二&#xff0c;UDP协议 2-1&#xff0c;UDP的特点 2-2&#xff0c;UDP协议端格式 三&#xff0c;TCP协议 3-1&#xff0c;TCP报文格式 3-2&#xff0c;TCP三次握手 3-3&#xff0c;TCP四次挥手 3-4&#xff0c;滑动窗口 3-5&#xf…

ARP 表、MAC 表、路由表、跨网段 ARP

文章目录 一、ARP 表1、PC2、路由器 - AR22203、交换机 - S57004、什么样的设备会有 ARP 表&#xff1f; 二、MAC 表什么样的设备会有 MAC 表&#xff1f; 三、路由表什么样的设备会有路由表&#xff1f; 四、抓取跨网段 ARP 包 所谓 “透明” 就是指不用做任何配置 一、ARP 表…

算法10(力扣20)-有效的括号

1、问题 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有一个对应的相同类…

每日一题——二叉树的前序遍历和中序遍历和后序遍历

文章目录 二叉树的前序、中序与后序遍历题目描述数据范围&#xff1a;示例&#xff1a;示例 1&#xff1a; 解题思路1. 递归法2. 迭代法 代码实现&#xff08;递归法&#xff09;代码解析示例输出复杂度分析 中序遍历后序遍历 二叉树的前序、中序与后序遍历 题目描述 给定一棵…

【优选算法】8----四数之和

有看过我上篇算法博客并且去做过的铁子们&#xff0c;对这道题的话应该就不会那么陌生了&#xff0c;因为这两道题 的解题思路有着异曲同工之妙~ -----------------------------------------begin------------------------------------- 题目解析&#xff1a; 跟三数之和就多了…

【开源免费】基于SpringBoot+Vue.JS校园失物招领系统(JAVA毕业设计)

本文项目编号 T 150 &#xff0c;文末自助获取源码 \color{red}{T150&#xff0c;文末自助获取源码} T150&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

2025美赛倒计时,数学建模五类模型40+常用算法及算法手册汇总

数学建模美赛倒计时&#xff0c;对于第一次参加竞赛且没有相关基础知识的同学来讲&#xff0c;掌握数学建模常用经典的模型算法知识&#xff0c;并熟练使用相关软件进行建模是关键。本文将介绍一些常用的模型算法&#xff0c;以及软件操作教程。 数学建模常用模型包括&#xf…

【深度学习】常见模型-循环神经网络(Recurrent Neural Network, RNN)

循环神经网络&#xff08;RNN&#xff09; 概念简介 循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一种用于处理序列数据&#xff08;如时间序列、文本序列等&#xff09;的神经网络模型。与传统神经网络不同&#xff0c;RNN 的结构具有记忆能力&…

Matlab总提示内存不够用,明明小于电脑内存

目录 前言情况1&#xff08;改matlab最大内存限制&#xff09;情况2&#xff08;重启电脑&#xff09;情况3 前言 在使用matlab中&#xff0c;有时候需要占用的内存并没有超过电脑内存依旧会报错&#xff0c;提示内存不够用&#xff0c;可以尝试下面几种方法&#xff0c;总有一…

数据结构(Java)——二叉树

1.概念 二叉树是一种树形数据结构&#xff0c;其中每个节点最多有两个子节点&#xff0c;通常被称为左子节点和右子节点。二叉树可以是空的&#xff08;即没有节点&#xff09;&#xff0c;或者由一个根节点以及零个或多个左子树和右子树组成&#xff0c;其中左子树和右子树也分…

Windows电脑上记录工作待办清单的工具用哪个?

在Windows电脑上记录日常工作待办清单的工具用哪一个比较好呢&#xff1f;想要工作效率高&#xff0c;借助Windows电脑上的待办清单工具&#xff0c;可以帮助大家快速完成各项任务&#xff0c;今天给大家盘点几款工作待办清单工具。 Windows自带的便笺Stickynotes Windows自…

H266/VVC 量化编码中 JCCR 技术

色度联合编码 JCCR VVC 支持色度分量联合编码(Joint Coding of Chroma Residual&#xff0c;JCCR)&#xff0c; 两个色度残差联合编码。通过 TU 的标志位 tu_joint_cbcr_residual_flag 指定该工 具&#xff0c;并通过 CBF 来隐式传输所选的模式。仅当 TU 的至少一个色度分量的 …

云原生时代,如何构建高效分布式监控系统

文章目录 一.监控现状二.Thanos原理分析SidecarQuerierStoreCompactor 三.Sidecar or ReceiverThanos Receiver工作原理 四.分布式运维架构 一.监控现状 Prometheus是CNCF基金会管理的一个开源监控项目&#xff0c;由于其良好的架构设计和完善的生态&#xff0c;迅速成为了监控…

DAY3,模拟终端

题目 实现一个终端的功能&#xff0c;注意需要带有cd功能 思路 如何 C语言执行shell命令&#xff1f; 使用进程替换exec函数&#xff1b;&#xff1b;使用system函数。 如何 切换工作目录&#xff1f; 使用chdir函数切换工作目录。 其…

一键视频转文字/音频转文字,浏览器右键提取B站视频文案,不限时长免费无限次可用

上篇文章阿虚分享了自己的「短视频」笔记方案 短视频文件小&#xff0c;易存储&#xff0c;所以阿虚建议是直接将原视频插入到笔记当中 而长视频文件大&#xff0c;很难像短视频一样操作。阿虚之前的建议是提取重要部分视频转长截图&#xff0c;或者视频转GIF 但上述方案仔细…

【C++】详细讲解继承(上)

C面向对象的三大特性&#xff1a;封装&#xff0c;继承&#xff0c;多态。现在我们就介绍一下继承。 1.继承的概念及定义 1.1 继承的概念 继承机制是⾯向对象程序设计使代码可以 复⽤ 的最重要的⼿段。我们前面接触到的都是 函数 层次的复用&#xff0c;遇到过的 类 层次的复…

AIGC专栏18——EasyAnimateV5.1版本详解 应用Qwen2 VL作为文本编码器,支持轨迹控制与相机镜头控制

AIGC专栏18——EasyAnimateV5.1版本详解 应用Qwen2 VL作为文本编码器&#xff0c;支持轨迹控制与相机镜头控制 学习前言相关地址汇总源码下载地址HF测试链接MS测试链接 测试效果Image to VideoText to Video轨迹控制镜头控制 EasyAnimate详解技术储备Qwen2 VLStable Diffusion …

1905电影网中国地区电影数据分析(一) - 数据采集、清洗与存储

文章目录 前言一、数据采集步骤及python库使用版本1. python库使用版本2. 数据采集步骤 二、数据采集网页分析1. 分析采集的字段和URL1.1 分析要爬取的数据字段1.2 分析每部电影的URL1.2 分析每页的URL 2. 字段元素标签定位 三、数据采集代码实现1. 爬取1905电影网分类信息2. 爬…

【25】Word:林涵-科普文章❗

目录 题目​ NO1.2.3 NO4.5.6 NO7.8 NO9.10 NO11.12 不连续选择&#xff1a;按住ctrl按键&#xff0c;不连续选择连续选择&#xff1a;按住shift按键&#xff0c;选择第一个&#xff0c;选择最后一个。中间部分全部被选择 题目 NO1.2.3 布局→纸张方向&#xff1a;横向…