前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【容器安全系列Ⅳ】- 深入理解Linux Cgroup

【容器安全系列Ⅳ】- 深入理解Linux Cgroup

原创
作者头像
星尘安全
发布2024-08-25 10:17:04
1870
发布2024-08-25 10:17:04
举报
文章被收录于专栏:linux
图片
图片

     当主机上运行多个进程时,管理系统资源可能是一个挑战。单个行为异常的程序可能会消耗所有可用资源,从而导致整个系统崩溃。为了解决这个问题,Linux 依靠控制组 (cgroups) 来管理每个进程对资源(如 CPU 和内存)的访问。

    Docker 和其他容器化工具使用 cgroups 来限制容器可以使用的资源,这有助于避免相互干扰的问题。这在使用 Kubernetes 时特别有用,因为来自多个应用程序的工作负载经常在同一主机上共享资源。

     在这篇文章中,我们将仔细研究 cgroups,并探讨它们如何确保每个进程都能访问高效运行所需的资源。我们还将介绍 cgroups 的几个安全方面,包括如何使用 cgroups 来降低拒绝服务攻击的风险,并管理容器对主机上特定设备的访问。

cgroups v1 和 v2

     值得注意的是,根据Linux发行版和版本,在给定的主机上可能会使用两个版本的cgroups。与原始实现相比,Cgroup v2 提供了管理优势,并且是某些容器功能(如非root容器)所必需的。

    Cgroup v2 最初是在2016年 4.5 版本的 Linux 内核中引入的,但直到最近才成为某些发行版的默认版本。要确定主机上运行的版本,可以验证挂载的文件系统。例如,如果您在 Ubuntu 20.04 主机上执行该命令 mount | grep cgroup ,您将看到一行展示“cgroup2”,另几行展示“cgroup”,这表示两个系统都已安装。

cgroup 挂载列表 - Ubuntu 20.04
cgroup 挂载列表 - Ubuntu 20.04

     但是,如果您在 Ubuntu 22.04 系统上运行相同的命令,则只会看到 cgroup v2。

cgroup 挂载列表 - Ubuntu 22.04
cgroup 挂载列表 - Ubuntu 22.04

     由于 cgroup v2 是最近 Linux 发行版中使用的版本,因此我们将在示例的其余部分重点介绍 v2。

Cgroups 基础知识

     有几种方法可以检查 Linux 主机上使用的 cgroup。一种选择是使用 /proc 文件系统来查看用于特定进程的 cgroup(例如,正在运行的用户的 bash shell)。

     执行命令 cat /proc/[PID]/cgroup 将显示进程所属的 cgroup “slice” 和 “scope”(slice 和 scopes 用于组织 cgroup 和进程)。在以下示例中,我们首先用 ps -fC bash 获取 shell 的进程 ID。然后,我们使用该进程 ID 来发现它使用的 cgroup 会话。

查找 bash shell 的 cgroup 作用域和切片
查找 bash shell 的 cgroup 作用域和切片

     要查看可以为该进程修改的可用资源,您可以查看 /sys/ 文件系统,它对应于我们从上一个命令中获得的信息(例如:sys/fs/cgroup/user.slice/user-1000.slice/session-4.scope)

显示给定 cgroup 范围的资源
显示给定 cgroup 范围的资源

     此手动过程可能非常耗时,因此您可以利用更便捷的工具,以更有条理的方式显示 cgroup 信息。例如,systemd-cgls 可以显示主机上不同 cgroup 作用域的分层视图。

使用 systemd-cgls 获取 cgroup 信息的分层视图
使用 systemd-cgls 获取 cgroup 信息的分层视图

     此外,cgroup-utils 软件包中的 lscgroup 实用程序可用于检查 cgroup 信息。

使用 lscgroup 显示 cgroup 信息
使用 lscgroup 显示 cgroup 信息

使用 cgroups 限制资源

     现在我们已经了解了如何查看 cgroup 信息,下一步是探索如何使用 cgroups 来限制进程可用的资源,这有助于缓解拒绝服务风险。为了证明这一点,我们将使用 stress 工具来模拟攻击者或行为不端的应用程序消耗我们主机上的所有 CPU。

     在 Docker 容器中,我们可以利用命令 stress -c 2  ,它将启动两个进程,总共消耗 2 个 CPU 内核。然后,通过在另一个窗口中执行命令 top ,我们可以验证对主机 CPU 的影响。

使用压力工具消耗 CPU 资源
使用压力工具消耗 CPU 资源

     Docker 提供了各种选项来限制容器可以使用的 CPU 时间量,但最简单的是--cpus标志,它允许您指定可以使用的 CPU 的十进制数。在幕后,Docker 利用 cgroups 来强制执行此限制。

     例如,执行 docker run --name stress --cpus 0.5 -it stressimage /bin/bash 会将容器限制为 0.5 个 CPU。使用上一个容器中的相同 stress 命令后,我们可以在 top 中观察到此限制的结果。 

CPU 资源使用率受 cgroups 限制
CPU 资源使用率受 cgroups 限制

     现在,stress 进程不再能够利用两个 CPU 内核,而是限制为 0.5 个 CPU(每个进程占内核的 25%)。

     我们还可以通过检查底层文件系统来观察 Docker 实现的 cgroup 限制的细节。为此,我们首先使用 docker inspect -f '{{.State.Pid}}' stress 获取 Docker 容器的进程 ID。然后我们可以查找此过程的 cgroup 信息。容器的 cgroup 目录包含一个 cpu.max 文件,其值为 50000 100000 ,相当于 0.5 个 CPU。默认情况下,Docker 不限制进程的 CPU 使用率,因此文件将显示值 max 100000 。如果攻击者有权访问此容器,则可以使用主机上的所有 CPU 资源(例如,挖掘加密货币)。

使用 cgroups 限制fork炸弹

     Linux 系统上常见的拒绝服务攻击称为frok炸弹,当攻击者生成大量进程,最终耗尽系统资源时,就会发生这种攻击。默认情况下,容器(和其他 Linux 进程)在它们可以生成多少个新进程方面不受限制,这意味着任何进程都可以创建fork炸弹。

    Cgroup 能够限制可以生成的进程数量,从而有效地保护主机免受fork炸弹攻击。我们可以使用 docker run 的--pids-limit 参数来演示这一点,这实质上将设置适当的 cgroup。

     要了解其工作原理,我们可以使用 docker run -it --pids-limit 10 ubuntu:22.04 /bin/bash 命令启动容器,这会将容器限制为最多 10 个进程。然后我们可以使用命令执行 bash fork 炸弹 :(){ :|: & };: 

Docker PID 限制在fork炸弹中生效
Docker PID 限制在fork炸弹中生效

     很快,容器达到 10 个进程的限制,并显示错误。但是,底层主机将保持响应,从而防止拒绝服务攻击。

使用 cgroups 控制设备访问

    cgroups 的另一个与安全相关的方面是,它们可用于控制对设备的访问。容器提供对主机上一系列设备的访问,详见 runc 的允许设备列表,并且可以利用 Docker 的功能(使用 cgroups)将其他设备添加到该列表中。这允许您向特定容器授予对硬件(例如音频设备)的访问权限。

     您可以将 --device 选项添加到命令 docker run 中以授予对设备的访问权限。例如,执行 docker run -d --rm --device /dev/dm-0 --name webdevice nginx 会生成一个有权访问/dev/dm-0设备的容器。

     与 CPU 或内存等其他资源相比,Linux 工具没有提供那么多的功能来检查 cgroup 对设备的访问。在 cgroup v2 中,一般使用 eBPF 程序用于管理对设备的访问,因此标准工具将不起作用。所以, bpftool 是必需的。您可以使用此程序列出与任何给定 cgroup 关联的 eBPF 程序,从而提供容器对主机访问的一些可见性,尽管不是很详细。

结论

     控制共享资源是确保多个容器可以有效地共享单个服务器的关键。在这篇文章中,我们介绍了 cgroup,这是 Linux 系统用于实现此控制的主要机制。我们还演示了如何利用 cgroup 来帮助缓解常见的拒绝服务攻击,并管理对连接到主机的特定设备的访问。

     到目前为止,我们检查的所有安全机制都在系统上的 root 用户的控制之下。但是,有时我们想要限制 root 用户的操作,那又该怎么办呢?在下一篇文章中,我们将探讨 SELinux 和 AppArmor 等强制访问控制(MAC)系统如何实现这一目标。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • cgroups v1 和 v2
  • Cgroups 基础知识
    • 使用 cgroups 限制fork炸弹
      • 使用 cgroups 控制设备访问
        • 结论
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档