Kubernetes--资源需求

285 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

在kubernetes上,可由容器或Pod请求或消费的“计算资源”是指CPU和内存(RAM),这也是目前仅有的受支持的两种类型。相比较来说,CPU属于可压缩(compressible)型资源,即资源额度可按需收缩,而内存(当前)则是不可压缩型资源,对其执行收缩操作可能会导致某种程度的问题。

目前来说,资源隔离尚且属于容器级别,CPU和内存资源的配置需要在Pod中的容器上进行,每种资源均可由“requests”属性定义其请求的确保可用值,即容器运行可能用不到这些额度的资源,但用到时必须要确保有如此多的资源可用,而“limits”属性则用于限制资源可用的最大值,即硬限制。不过,为了表述方便,通常仍然把资源配置称作Pod资源的请求和限制,只不过它是指Pod内所有容器上某种类型资源的请求和限制的总和。

在Kubernetes系统上,1个单位的CPU相当于虚拟机上的1颗虚拟CPU(vCPU)或物理机上的一个超线程(Hypertbread,或称为一个逻辑CPU),它支持分数计量方式,一个核心(1 core)相当于1000个微核心(millicores),因此500m相当于是0.5个核心,即二分之一个核心。内存的计量方式与日常使用方式相同,默认单位是字节,也可以使用E、P、T、G、M 和 K 作为单位后缀,或Ei、Pi、Ti、Gi、Mi 和 Ki形式的单位后缀。

下面的示例中,自主式Pod要求为stress容器确保128Mi的内存及五分之一个CPU核心(200m)资源可用,它运行stress-ng镜像启动一个进程(-m 1)进行内存性能压力测试,满载测试时它也会尽可能多地占用CPU资源,另外再启动一个专用的CPU压力测试进程(-c 1)。Stress-ng是一个多功能系统压力测试具,master/worker模型,Master为主进程,负责生成和控制子进程,worker是负责执行各类特定测试的子进程,例如测试CPU的子进程,以及测试RAM的子进程等:

apiVersion: v1
kind: Pod
metadata:
  name: stress-pod
spec
  containers:
  - name: stress
    image: ikubernetes/ stress-ng
    command:[“/usr/bin/stress-ng”, “-m 1”,“-c 1”,“-metrics-brief”]
    resources
      requests:
        memory:“128Mi”
        cpu:“200,m”

上面的配置清单中,其请求使用的CPU资源大小为200m,这意味着一个CPU核心足以确保其以期望的最快方式运行。另外,配置清单中期望使用的内存大小为128Mi,不过其运行时未必真的会用到这么多。考虑到内存为非压缩型资源,其超出指定的大小在运行时存在被OOM Killer杀死的可能性,于是请求值也应该就是其理想中使用的内存空间上限。

找下来创建并运行此Pod对其资源限制效果进行检查。需要特别说明的是,当前使用的系统环境中,每个节点的可用CPU核心数均为8,物理内存空间为16GB:

kubectl create -f pod-resouces-test.yaml

而后在Pod资源的容器内运行top命令观察其CPU及内存资源的占用状态,如下所示,其中{stress-ng vm}是执行内存压测的子进程,它默认使用256m的内存空间,{stress-ng-cpu}是执行CPU压测的专用子进程:

kubectl exec stress-pod -- top
Mem:2884676K used,13531796K free27700K shrd,2108K buff,1701456K cached
CPU:25% usr    0% sys   0% nic  74% idle   0% io   0% irq  0% sirq
Load average:0.57 0.60 0.71 3/435 15
PID   PPID USER  STAT VSZ    %VSZ CPU %CPU COMMAND
9     8 root     R    262m    2%   6  13%  {stress-ng-vm} /usr/bin/stress-ng
7     1 root     R    6888    0%   3  13%  {stress-ng-cpu} /usr/bin/stress-ng
1     0 root     S    6244    0%   1  0%   /usr/bin/stress-ng -c 1 -m 1 --met
······

top命令的输出结果显示,每个测试进程的CPU占用率为13%(实际为12.5%),{stress-ng-vn}的内存占用量为262m(VSZ),此两项资源占用量都远超其请求的用量,原因是stress-ng会在可用的范围内尽量多地占用相关的资源。两个测试线程分布于两个CPU核心以满载的方式运行,系统共有8个核心,因此其使用率为25%(2/8)。另外,节点上的内存资源充裕,虽然容器的内存用量远超128M,但它依然可运行。一旦资源紧张时,节点仅保证容器有五分之一个CPU核心可用,对于有着8个核心的节点来说,它的占用率为2.5%,于是每个进程为1.25%,多占用的资源会被压缩。内存为非可压缩型资源,所以此Pod在内存资源紧张时可能会因OOM被杀死(killed)。

对于压缩型的资源CPU来说,未定义其请求用量以确保其最小的可用资源时,它可能会成其他的Pod资源压缩至极低的水平,甚至会达到Pod不能够被调度运行的境地。而对于非压缩型资源来说,内存资源在任何原因导致的紧缺情形下都有可能导致相关的进程被杀死。因此,在Kubernetes系统上运行关键型业务相关的Pod时必须使用requests属性为容器定义资源的确保可用量。

集群中的每个节点都拥有定量的CPU和内存资源,调度Pod时,仅那些被请求资源的余量可容纳当前被调度的Pod的请求量的节点才可作为目标节点。也就是说,Kubernetes的调度器会根据容器的requests属性中定义的资源需求量来判定仅哪些节点可接收运行相关的Pod资源,而对于一个节点的资源来说,每运行一个Pod对象,其requests中定义的请求量都要被预留,直到被所有Pod对象瓜分完毕为止。