在 K8s/OpenShift 中,requests 和 limits 是 Pod 的资源分配机制,分别用于定义 Pod 的最低资源需求和最大资源限制。在这种情况下,如果一个 Pod 只设置了 requests 而没有设置 limits,其最大资源使用量的行为依赖于集群的配置和调度机制。
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 控制的。比如,
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 核心上运行。
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 的使用情况,
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 越来越多呢?