Docker的进程和Cgroup概念详解

 更新时间:2025年02月07日 14:29:33   作者:AquaPluto  
文章主要介绍了容器内的进程组织和关系,包括containerd-shim和容器内1号进程的角色和特点,以及信号处理机制,同时,文章还讨论了Cgroup在Linux系统中用于资源管理和控制的机制,包括CFS调度算法和Kubernetes中的资源管理,感兴趣的朋友跟随小编一起看看吧

容器里的进程组织或关系

0号进程:containerd-shim

角色:

  • containerd-shim 是容器的父进程,负责管理容器的生命周期,接收容器内的执行的指令。
  • 它通过调用 runc 创建容器,并处理容器内的指令。

特点:

  • 容器依赖:
    • containerd-shim 是容器的祖宗进程,如果它挂掉,整个容器也会退出。
  • 进程管理:
    • 如果容器的1号进程结束,containerd-shim 会回收容器命名空间中的所有进程。
    • 如果1号进程未结束,但其子进程结束,子进程会成为僵尸进程,需要由1号进程回收。
  • 信号处理:
    • docker stop 会向容器的1号进程发送 SIGTERM(-15)信号。
      • 如果1号进程没有信号转发能力,它会向容器内的所有进程发送 SIGKILL(-9)信号。
      • 如果1号进程有信号转发能力,它会向容器内的所有进程转发 SIGTERM(-15) 信号。

1号进程:容器内的第一个进程

角色:

  • 1号进程是容器内的第一个进程,代表容器的生命周期。
  • 它通常是用户指定的应用程序进程。

特点:

  • 生命周期:
    • 1号进程结束,容器也会结束。
    • 1号进程必须在前台运行,否则容器会退出。
  • 功能缺陷(与操作系统进程的区别):
    • 容器内的1号进程不一定是所有用户进程的祖先。
    • 如果1号进程成为孤儿进程,它会被init进程(0号进程)收养。
    • 用户开发的1号进程可能缺乏回收僵尸进程和转发信号的能力。

应具备的能力:

  • 回收僵尸进程::定期调用 wait 或 waitpid 回收僵尸子进程。
  • 信号转发:将接收到的信号(如 SIGTERM)转发给子进程。
~# docker container inspect text | grep -i pid
pid:41404---------对应的就是容器内的1号进程
~# ps -elf | grep 41404
pid:41404 ppid:41382---------对应的就是容器内的0号进程

进程收到信号后的三种反应

信号是操作系统向进程发送的一种通知,用于通知进程发生了某种事件。可以用于进程间通信或控制进程行为。

  • 忽略(Ignore):
    • 进程对信号不做任何处理。
    • 示例:忽略 SIGTERM 信号,进程不会被终止。
  • 捕获(Catch):
    • 进程可以注册自定义的处理函数(handler)来处理捕获的信号。
    • 当信号到达时,触发 handler 执行。
    • 示例:trap 'echo "signal received"' SIGTERM
  • 默认行为(Default):
    • 每个信号都有默认行为,由操作系统定义。
    • 示例:
      • SIGTERM 的默认行为是终止进程。
      • SIGKILL 的默认行为是强制终止进程。

两个特权信号

SIGKILL (-9)

  • 作用: 强制终止进程。
  • 特点:
    • 无法被忽略。
    • 无法被捕获。
  • 使用场景: 当进程无响应时,强制终止进程。

SIGSTOP (-19):

  • 作用: 暂停进程的运行
  • 特点:
    • 无法被忽略。
    • 无法被捕获。
  • 恢复运行: 发送 SIGCONT (-18) 信号。

SIGTERM(-15)信号是可以被进程忽略或者捕获的

在容器内执行 kill 命令的行为

kill -9 1

  • 无法杀死容器内的1号进程。
  • 原因: 容器内的1号进程被打上了 SIGNAL_UNKILLABLE 标签。

kill -19 1

  • 无法暂停容器内的1号进程。
  • 原因: 容器内的1号进程被打上了 SIGNAL_UNKILLABLE 标签。

kill -15 1

  • 有可能杀死容器内的1号进程。
  • 如果1号进程没有注册 SIGTERM 信号的处理函数,它会忽略该信号。
  • 如果1号进程注册了 SIGTERM 信号的处理函数,它会执行该函数。

Cgroup 介绍

Cgroup(Control Group)是 Linux 内核提供的一种机制,用于限制、控制和监控进程组的资源使用。它允许系统管理员对一组进程的资源使用进行精细化管理,包括 CPU、内存、磁盘 I/O 等。Cgroup 是容器技术(如 Docker、Kubernetes)中实现资源隔离和管理的基础。

为何要用 Cgroup?Cgroup 的主要作用是限制容器或进程组对宿主机资源的使用,防止某个容器或进程过度占用资源,从而影响其他容器或进程的正常运行。通过 Cgroup,可以确保宿主机上的多个容器或进程能够公平、稳定地共享系统资源。

在 Linux 系统中,可以通过以下命令查看和管理 Cgroup

# 查看当前的 Cgroup 控制层级
cat /proc/cgroups
# 创建一个新的 Cgroup
mkdir /sys/fs/cgroup/cpu/my_cgroup
# 将一个进程加入到 Cgroup 中
echo "PID" > /sys/fs/cgroup/cpu/my_cgroup/tasks
# 设置 CPU 限制
echo "2" > /sys/fs/cgroup/cpu/my_cgroup/cpu.cfs_quota_us

CPU Cgroup 中与 CFS 相关的参数

CFS(Completely Fair Scheduler)是 Linux 内核中的一种调度算法,用于公平地分配 CPU 时间给各个进程。Cgroup 中与 CFS 相关的参数决定了进程组对 CPU 的使用率。

  • cpu.cfs_period_us:表示 CPU 的时间周期,单位为微秒 (μs)。例如,设置为 100ms (100,000 μs),表示一个周期为 100 毫秒。
  • cpu.cfs_quota_us:表示在该时间周期内,控制组内的进程最多可以使用的 CPU 时间。例如,设置为 50ms (50,000 μs),表示在 100ms 的周期内,进程最多可以使用 50ms 的 CPU 时间。此时,CPU 使用率为 50ms / 100ms = 0.5,即 50%。
  • cpu.shares:用于控制同一层级下的多个控制组之间的 CPU 资源分配。当宿主机上的 CPU 资源不足时,cpu.shares 会生效,决定各个控制组之间的 CPU 资源分配比例。cpu.shares 的值越大,分配的 CPU 资源越多。

总结:

  • cpu.cfs_quota_us与cpu.cfs_period_us这两个值决定了每个控制组所有进程可使用cpu资源的最大值
  • cpu.shares这个值决定了cpu cgroup子系统下控制组可用cpu的相对比例,不过只有当系统上cpu被占满时,这个比例才会在各个控制组间起作用

Kubernetes 中的资源管理

在 Kubernetes 中,Pod 的资源请求和限制可以通过 requests 和 limits 来设置。

  • requests:表示 Pod 对资源的最低需求。Kubernetes 会根据 requests 来调度 Pod,确保节点上有足够的资源。requests 对应 Cgroup 中的 cpu.shares,表示初始的 CPU 资源申请量。实际使用量可以超过 requests,但不会低于它。
  • limits:表示 Pod 对资源使用的上限。Kubernetes 会通过 Cgroup 限制 Pod 的资源使用,确保不会超过 limits 设置的值。limits 对应 Cgroup 中的 cpu.cfs_quota_us 和 cpu.cfs_period_us,表示 CPU 使用的硬性上限。

但是要注意,limits 设置的上限是否能达到,还取决于宿主机的实际资源情况。如果宿主机资源不足,Pod 可能无法达到 limits 设置的上限。

memory cgroup

每个容器都有对应的 memory cgroup 控制组,位于 /sys/fs/cgroup/memory/system.slice/docker - xxx,用于管理容器内存。

主要参数:

  • memory.limit_in_bytes:设置容器内所有进程可占用的物理内存上限,子 group 最多只能设置到父级 group 的该值。
  • memory.oom_control:默认为 0,表示开启 OOM 机制;可设为 1 关闭,通过 echo 1 > memory.oom_control 实现。
  • memory.usage_in_bytes:只读参数,显示容器内所有进程占用的物理内存总量。

示例: 容器启动时,rss 为 100 M,page cache 为 899 M,内存总使用量为 999 M;随着进程运行,申请更多内存后,rss 增至 200 M,page cache 减至 699 M,内存总使用量仍为 899 M,但实际进程占用的物理内存增大。

容器的可用磁盘进行配额

默认情况,容器内的可用磁盘空间是没有限制的。

容器内的文件系统 = lowerdir + upperdir

写入操作

  • 在容器内写容器文件系统里写东西(任何目录都没有挂载任何外部存储卷)
    • 那此时写入的数据,都写到了upperdir层,也就是写到的宿主机上。
    • 所以如果不加以限制,很有可能会导致宿主机磁盘空间写满。

如何解决问题?有两种方式:

  • 对容器的可用磁盘进行配额
  • 对容器写操作的目录,应该挂载一个专门的外部存储卷(推荐)

到此这篇关于Docker的进程和Cgroup概念的文章就介绍到这了,更多相关Docker Cgroup概念内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Jenkins+Docker实现自动化部署

    Jenkins+Docker实现自动化部署

    本文介绍了在CentOS7和Git(Gitee)环境下如何使用Jenkins进行自动化部署,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-09-09
  • Deepin使用docker安装mysql数据库过程详解

    Deepin使用docker安装mysql数据库过程详解

    这篇文章主要介绍了Deepin使用docker安装mysql数据库过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • Docker 网络模式及配置方式

    Docker 网络模式及配置方式

    这篇文章主要介绍了Docker 网络模式及配置方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • Docker容器没有权限写入宿主机目录的解决方案

    Docker容器没有权限写入宿主机目录的解决方案

    这篇文章主要介绍了Docker容器没有权限写入宿主机目录的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • 在 docker 之间导出导入镜像的方法

    在 docker 之间导出导入镜像的方法

    本篇文章主要介绍了在 docker 之间导出导入镜像的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • docker运行nginx绑定配置文件失败原因以及问题解决

    docker运行nginx绑定配置文件失败原因以及问题解决

    最近工作中在使用docker运行nginx的时候遇到了些问题,下面分享给大家,这篇文章主要给大家介绍了关于docker运行nginx绑定配置文件失败原因以及问题解决的相关资料,需要的朋友可以参考下
    2023-02-02
  • docker启动elasticsearch时内存不足问题及解决方法

    docker启动elasticsearch时内存不足问题及解决方法

    这篇文章主要介绍了docker启动elasticsearch时内存不足问题,本文给大家分享安装过程及解决方法,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • docker安装elastic search的详细过程

    docker安装elastic search的详细过程

    这篇文章主要介绍了docker安装elastic search的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • docker容器中如何修改时间

    docker容器中如何修改时间

    这篇文章主要介绍了docker容器中如何修改时间问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • docker安装包冲突问题解决办法

    docker安装包冲突问题解决办法

    这篇文章主要给大家介绍了关于docker安装包冲突问题解决办法, docker是现在比较流行的一款虚拟化平台了,文中通过图文以及代码示例介绍的非常详细,需要的朋友可以参考下
    2023-08-08

最新评论