前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >你真的了解 pod 的 cpu/memory 吗?

你真的了解 pod 的 cpu/memory 吗?

作者头像
Markgogogo
发布2025-01-22 08:17:20
发布2025-01-22 08:17:20
11900
代码可运行
举报
文章被收录于专栏:3分钟云计算3分钟云计算
运行总次数:0
代码可运行

在 K8s/OpenShift 中,requests 和 limits 是 Pod 的资源分配机制,分别用于定义 Pod 的最低资源需求最大资源限制。在这种情况下,如果一个 Pod 只设置了 requests 而没有设置 limits,其最大资源使用量的行为依赖于集群的配置和调度机制。

代码语言:javascript
代码运行次数:0
复制
    resources:
      requests:
        cpu: 100m
        memory: 200Mi

如果只设置了 requests,而没有设置 limits,Pod 的 CPU 使用没有上限。这意味着 Pod 可以根据节点上的 CPU 可用性,尽可能多地使用 CPU。只要节点上有足够的空闲 CPU 资源,Pod 就可以消耗更多的 CPU。

内存的处理与 CPU 不同。如果未设置内存的 limits,Pod 内的进程可以使用的内存上限依然是无限的,只要节点上有足够的内存,Pod 就可以消耗更多的内存。

但需要注意,内存不足时不会像 CPU 那样限速,内存不足可能会触发节点的 Out-Of-Memory (OOM) 机制。如果 Pod 消耗了过多内存,超过了节点的可用内存,系统可能会通过 OOM 杀掉该 Pod 或其他占用过多内存的进程。这种情况下,Pod 的内存使用没有 limits 来加以限制,它有可能因为消耗过多资源导致被系统杀死。

我们知道容器其实是一个进程,而pod 包含一个或几个容器。在K8s/OpenShift 中,pod 是一个逻辑组,包含一个或多个容器,这些容器共享网络命名空间、存储卷以及其他资源。Pod 本身并不是一个单独的进程,但容器运行在该 Pod 中,容器内的进程可以相互通信。

在Linux 中,一个进程的cpu/memory 使用量是由cgroups 控制的。比如,

  • cgroups 通过 cpu 控制器来管理进程的 CPU 使用。
代码语言:javascript
代码运行次数:0
复制
cpu.shares 允许为进程或容器设置相对的 CPU 份额。即使没有明确的 CPU 限制,cgroups 会根据系统负载,按比例为容器分配 CPU 资源。例如,假设一个容器设置了 cpu.shares 为 1024,另一个为 512,那么前者的 CPU 份额将是后者的两倍。
cfs_quota_us(CPU Quota)定义了某个进程组可以在指定的 cfs_period_us 时间内使用的 CPU 时间(以微秒为单位)。
cfs_period_us 是一个固定周期,通常是 100ms。例如,如果一个容器的 cfs_quota_us 设置为 50,000 微秒,cfs_period_us 为 100,000 微秒,意味着该容器在每个 100ms 的时间段内只能使用 50ms 的 CPU 时间(相当于使用一个 CPU 的 50%)。
cpuset 控制器可以限制容器使用特定的 CPU 核心。例如,通过 cpuset.cpus = 0-2,你可以限制某个进程只能在第 0 到第 2 个 CPU 核心上运行。
  • cgroups 通过 memory 控制器限制进程的内存使用
代码语言:javascript
代码运行次数:0
复制
memory.max 用于限制某个进程或容器的最大内存使用量。如果容器超过了这个限制,Linux 内核的 OOM(Out-Of-Memory)管理器可能会杀死该容器中的进程,以释放内存。例如,设置 memory.max = 500M 表示该容器最多可以使用 500MB 的内存。
如果启用了交换内存,可以通过 memory.swap.max 限制容器使用的交换空间。例如,设置 memory.swap.max = 1G 表示该容器最多可以使用 1GB 的交换空间。
memory.anon 用于限制匿名内存(堆和栈)的使用,这是应用程序内存的一部分。
如果容器超出分配的内存限制,cgroups 会触发 OOM 事件,导致系统根据 OOM 策略杀死该容器内的进程。

我们大概了解了cgroups 对cpu/memory 的控制。在K8s/OpenShift 中, 也是通过 cgroups 控制 容器的cpu/memory的。Kubelet 使用 cAdvisor 来收集容器的资源使用数据。cAdvisor 是一个运行在每个节点上的工具,它能自动监控所有容器的 CPU、内存、文件系统和网络使用情况。cAdvisor 通过读取 Linux 系统中的 cgroups(控制组)来获取资源使用的详细信息。

K8s/OpenShift 通过 cgroups 来限制和隔离容器的资源使用。每个容器在启动时会被分配一个 cgroup,cgroups 会监控容器的 CPU 和内存等资源的使用情况。cAdvisor 通过访问这些 cgroups,收集每个 Pod 以及其容器的资源使用数据。

例如,你可以登录pod 所在的节点 查看某个pod 的cpu/memory 的使用情况,

代码语言:javascript
代码运行次数:0
复制
sh-5.1# cat /sys/fs/cgroup/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podfc25f4bb_ba3a_4dfe_b464_e9ecb59fed5f.slice/cpu.stat
usage_usec 23099
user_usec 9486
system_usec 13612
core_sched.force_idle_usec 0
nr_periods 0
nr_throttled 0
throttled_usec 0
nr_bursts 0
burst_usec 0
sh-5.1# cat /sys/fs/cgroup/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podfc25f4bb_ba3a_4dfe_b464_e9ecb59fed5f.slice/memory.stat 
anon 516096
file 24576
...
jiazha-mac:~ jiazha$ oc get pod --all-namespaces -o json | grep -B 10 fc25f4bb-ba3a-4dfe-b464-e9ecb59fed5f
                    "k8s.v1.cni.cncf.io/network-status": "[{\n    \"name\": \"ovn-kubernetes\",\n    \"interface\": \"eth0\",\n    \"ips\": [\n        \"10.130.0.13\"\n    ],\n    \"mac\": \"0a:58:0a:82:00:0d\",\n    \"default\": true,\n    \"dns\": {}\n}]",
                    "target.workload.openshift.io/management": "{\"effect\": \"PreferredDuringScheduling\"}"
                },
                "creationTimestamp": "2024-09-10T01:13:08Z",
                "labels": {
                    "app": "guard"
                },
                "name": "kube-controller-manager-guard-ip-10-0-92-158.us-east-2.compute.internal",
                "namespace": "openshift-kube-controller-manager",
                "resourceVersion": "71607",
                "uid": "fc25f4bb-ba3a-4dfe-b464-e9ecb59fed5f"
                

那么为什么进程会随着时间的推移消耗的cpu/memory 越来越多呢?

  • 如果应用执行的任务是计算密集型(如图像处理、大数据分析、加密计算等),则随着时间的推移,计算任务的增加会导致 CPU 使用增加。一些服务在处理越来越多的请求时需要更多的计算资源,因此 CPU 使用率会逐渐增长。
  • 多线程应用可能会随着时间启动更多的线程,处理更多的任务。这会导致 CPU 使用上升,因为每个新线程都需要额外的计算资源。一些进程在运行时可能会生成新的子进程或线程来处理任务,而这些进程也会消耗更多的 CPU。
  • 应用中可能存在繁忙轮询(busy waiting)或无限循环,这种情况会导致 CPU 长时间处于高负载状态。错误设计的算法或不良优化可能会导致 CPU 过度使用。
  • 使用垃圾回收(GC)机制的语言(如 Java、Go 等),在处理大量内存分配和释放时,垃圾回收器的工作量会增加,从而导致 CPU 使用上升。
  • 内存泄漏 是导致进程内存使用随着时间增长的常见原因。内存泄漏发生在程序没有正确释放已分配的内存。例如,应用程序在处理某些请求或任务时分配了内存,但未能在任务完成后释放这些内存。随着时间的推移,未释放的内存会越来越多,导致进程的内存消耗持续增加,最终可能导致 Out-Of-Memory (OOM) 错误
  • 应用程序可能会缓存大量数据来提高性能,但如果缓存数据没有有效管理或清理,内存使用会不断增加。例如,Web 服务器或数据库应用程序可能会缓存请求、会话信息或数据块。如果缓存不定期清理或设置了不合理的缓存策略,内存会被占满。
  • 一些进程在长时间运行后,内部的数据结构或状态信息(如日志、缓冲区)不断累积,导致内存使用逐渐增加。如果这些数据结构没有定期清理或复用,内存消耗会不断增加。
  • 进程的内存分配和释放可能导致内存碎片化。随着进程运行时间的增加,分配和释放不均衡的内存块可能会导致系统无法充分利用内存,进而导致内存占用看似不断增加。这种问题在使用语言如 C 或 C++ 时更为常见。
  • 进程创建的每个线程都有自己的堆栈空间。随着线程数量的增加,堆栈内存的需求也会增大。如果进程在运行过程中频繁创建新线程,但未能及时终止不需要的线程,则每个新线程的堆栈空间将消耗额外的内存。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-09-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 3分钟云计算 微信公众号,前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档