https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/上的Kubernetes文档状态:
调度程序确保对于每种资源类型,已调度容器的资源请求总数小于节点的容量。
Kubernetes在计算容量时是否考虑节点的当前状态?为了突出我的意思,下面是一个具体示例:
假设我有一个具有10Gi RAM的节点,每个节点运行10个Pod,每个请求具有500Mi的资源请求,并且没有限制。假设它们是“突发”的,每个Pod实际上使用的是1Gi RAM。在这种情况下,节点被充分利用(10 x 1Gi = 10Gi
),但是资源请求仅为10 x 500Mi = 5Gi
。 Kubernetes是否会考虑在此节点上调度另一个Pod,因为该节点上只有50%的内存容量已被requested
使用,还是会利用以下事实:当前正在使用100%的内存,并且该节点位于满容量?
答案 0 :(得分:0)
是的,Kubernetes在调度Pod(而不只是requests
)时会考虑当前的内存使用情况,因此不会在整个节点上调度新的Pod。当然,也有许多other factors。
(FWIW,当涉及resources
时,request
通过声明基准值来帮助调度程序,而limit
在资源超过该值时杀死Pod,这有助于容量规划/估算。
答案 1 :(得分:0)
肯定是,Kubernetes在pod调度过程中会考虑内存使用情况。
调度程序确保对于每种资源类型,已调度容器的资源请求之和小于节点的容量。请注意,尽管节点上的实际内存或CPU资源使用率非常低,但是如果容量检查失败,调度程序仍会拒绝将Pod放置在节点上。这样可以防止以后资源使用量增加时(例如,在请求率的每日峰值期间)节点上的资源短缺。
调度中有两个关键概念。首先,调度程序尝试根据资源请求和其他调度要求来筛选能够运行给定Pod的节点。其次,调度程序根据节点的绝对和相对资源利用率以及其他因素来衡量合格的节点。选择权重最高的合格节点来安排Pod。
您可以在kubernetes-scheduling
中找到有关Kuberneres中调度的详细说明。
简单示例:您的广告连播通常使用100 Mi的ram,但您会以50 Mi的请求运行它。如果您的节点有75 Mi的空闲空间,那么调度程序可以选择在其中运行pod。当pod内存消耗后来扩展到100 Mi时,这会使节点承受压力,此时内核可能选择终止进程。因此,正确获得内存请求和内存限制非常重要。有关内存使用情况,请求和限制,您可以在这里了解更多信息:memory-resource
。
如果节点有可用的内存,则容器可以超出其内存请求。但是容器不能使用超出其内存限制的内存。如果容器分配的内存超出其限制,则该容器将成为终止的候选对象。如果容器继续消耗超出其限制的内存,则终止该容器。如果终止的容器可以重新启动,则kubelet会将其重新启动,就像其他任何类型的运行时失败一样。
希望它能对您有所帮助。
答案 2 :(得分:0)
默认情况下,kubernetes将使用cgroup来管理和监视节点上Pod的“可分配”内存,但也有可能完全依赖静态预订和pod 请求。因此,这取决于您的群集部署。
在任何一种情况下,节点本身都会跟踪“内存压力”,该压力会监视节点现有的整体内存使用情况。如果节点处于内存压力下,则不会安排新的Pod,也不会驱逐现有Pod。
最好为所有工作负载设置合理的内存请求和限制,以尽可能地帮助调度程序。 如果kubernetes部署未配置cgroup内存监视,则这是所有工作负载的要求。 如果部署使用cgroup内存监视,则 requests 会为调度程序提供更多有关要调度的Pod是否适合节点的详细信息。
Kubernetes Reserve Compute Resources docco很好地概述了如何在节点上查看内存。
Node Capacity
---------------------------
| kube-reserved |
|-------------------------|
| system-reserved |
|-------------------------|
| eviction-threshold |
|-------------------------|
| |
| allocatable |
| (available for pods) |
| |
| |
---------------------------
默认调度程序检查节点是否没有内存压力,然后查看节点上可用的可分配内存以及新的pod requests 是否适合该内存。
可用的可分配内存是total-available-memory - kube-reserved - system-reserved - eviction-threshold - scheduled-pods
。
scheduled-pods
的值可以通过动态cgroup或通过pod 资源请求来静态计算。
默认为--cgroups-per-qos
的kubelet true
选项启用cgroup跟踪计划的Pod。 kubernetes运行的豆荚将位于
如果--cgroups-per-qos=false
,则只能通过在节点上计划的资源请求减少可分配的内存。
eviction-threshold
是Kubernetes开始驱逐Pod时的可用内存级别。默认值为100MB,但可以通过kubelet命令行设置。该设置既适用于节点的 allocatable 值,也适用于下一部分中节点的内存压力状态。
kubelets system-reserved
的值可以配置为静态值(--system-reserved=
),也可以通过cgroup(--system-reserved-cgroup=
)动态监视。
这适用于在kubernetes(sshd
,systemd
等)之外运行的所有系统守护程序。如果配置cgroup,则所有进程都需要放置在该cgroup中。
kubelets kube-reserved
值可以配置为静态值(通过--kube-reserved=
),也可以通过cgroup(--kube-reserved-cgroup=
)动态监视。
这适用于在kubernetes之外运行的任何kubernetes服务,通常是kubelet
和容器运行时。
容量存储在Node对象中。
$ kubectl get node node01 -o json | jq '.status.capacity'
{
"cpu": "2",
"ephemeral-storage": "61252420Ki",
"hugepages-1Gi": "0",
"hugepages-2Mi": "0",
"memory": "4042284Ki",
"pods": "110"
}
可分配的值可以在节点上找到,您可以注意到现有用法不会更改此值。只有带有资源请求的预定pod才会占用allocatable
值。
$ kubectl get node node01 -o json | jq '.status.allocatable'
{
"cpu": "2",
"ephemeral-storage": "56450230179",
"hugepages-1Gi": "0",
"hugepages-2Mi": "0",
"memory": "3939884Ki",
"pods": "110"
}
一个kube节点也可能发生“内存压力”事件。此检查是在上述 allocatable 资源检查之外进行的,它更多地是系统级的。内存压力着眼于当前根cgroup内存使用量减去不活动的文件缓存/缓冲区,类似于计算free
删除文件缓存的计算。
处于内存压力下的节点将不会安排Pod,并且将积极尝试驱逐现有的Pod,直到解决内存压力状态为止。
您可以通过--eviction-hard=[memory.available<500Mi]
标志来设置内存kubelet的驱逐阈值量将保持可用。吊舱的内存请求和使用情况可以帮助告知收回过程。
kubectl top node
将为您提供每个节点的现有内存统计信息(如果您正在运行度量服务)。
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
node01 141m 7% 865Mi 22%
如果您没有使用cgroups-per-qos
且有许多没有资源限制的Pod,或者有许多系统守护程序,那么集群可能会在以 allocateable 的形式在内存受限的系统上调度某些问题。 em>会很高,但实际值可能会很低。
Kubernetes Out Of Resource Handling docco包括一个script,它模拟kubelet内存监视过程:
# This script reproduces what the kubelet does
# to calculate memory.available relative to root cgroup.
# current memory usage
memory_capacity_in_kb=$(cat /proc/meminfo | grep MemTotal | awk '{print $2}')
memory_capacity_in_bytes=$((memory_capacity_in_kb * 1024))
memory_usage_in_bytes=$(cat /sys/fs/cgroup/memory/memory.usage_in_bytes)
memory_total_inactive_file=$(cat /sys/fs/cgroup/memory/memory.stat | grep total_inactive_file | awk '{print $2}')
memory_working_set=${memory_usage_in_bytes}
if [ "$memory_working_set" -lt "$memory_total_inactive_file" ];
then
memory_working_set=0
else
memory_working_set=$((memory_usage_in_bytes - memory_total_inactive_file))
fi
memory_available_in_bytes=$((memory_capacity_in_bytes - memory_working_set))
memory_available_in_kb=$((memory_available_in_bytes / 1024))
memory_available_in_mb=$((memory_available_in_kb / 1024))
echo "memory.capacity_in_bytes $memory_capacity_in_bytes"
echo "memory.usage_in_bytes $memory_usage_in_bytes"
echo "memory.total_inactive_file $memory_total_inactive_file"
echo "memory.working_set $memory_working_set"
echo "memory.available_in_bytes $memory_available_in_bytes"
echo "memory.available_in_kb $memory_available_in_kb"
echo "memory.available_in_mb $memory_available_in_mb"