zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Kubernetes 资源限制对Pod调度的影响

Kubernetes资源 限制 影响 调度 Pod
2023-09-14 09:01:47 时间

为容器管理资源


当你定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存(RAM)大小;此外还有其他类型的资源。

当你为 Pod 中的 Container 指定了资源 请求 时,调度器就利用该信息决定将 Pod 调度到哪个节点上。 当你还为 Container 指定了资源 约束 时,kubelet 就可以确保运行的容器不会使用超出所设约束的资源。 kubelet 还会为容器预留所 请求 数量的系统资源,供其使用。

 

请求和约束


如果 Pod 运行所在的节点具有足够的可用资源,容器可能(且可以)使用超出对应资源 request 属性所设置的资源量。不过,容器不可以使用超出其资源 limit 属性所设置的资源量。

例如,如果你将容器的 memory 的请求量设置为 256 MiB,而该容器所处的 Pod 被调度到一个具有 8 GiB 内存的节点上,并且该节点上没有其他 Pods 运行,那么该容器就可以尝试使用更多的内存。

如果你将某容器的 memory 约束设置为 4 GiB,kubelet 就会确保该约束生效。 容器运行时会禁止容器使用超出所设置资源约束的资源。 例如:当容器中进程尝试使用超出所允许内存量的资源时,系统内核会将尝试申请内存的进程终止, 并引发内存不足(OOM)错误。

约束值可以以被动方式来实现(系统会在发现违例时进行干预),或者通过强制生效的方式实现 (系统会避免容器用量超出约束值)。不同的容器运行时采用不同方式来实现相同的限制。

说明:

如果某 Container 设置了自己的内存限制但未设置内存请求,Kubernetes 自动为其设置与内存限制相匹配的请求值。类似的,如果某 Container 设置了 CPU 限制值但未设置 CPU 请求值,则 Kubernetes 自动为其设置 CPU 请求 并使之与 CPU 限制值匹配。

 

Pod 和 容器的资源请求和约束 


Pod 中的每个容器都可以指定以下的一个或者多个值:

  • spec.containers[].resources.limits.cpu
  • spec.containers[].resources.limits.memory
  • spec.containers[].resources.limits.hugepages-<size>
  • spec.containers[].resources.requests.cpu
  • spec.containers[].resources.requests.memory
  • spec.containers[].resources.requests.hugepages-<size>

尽管请求和限制值只能在单个容器上指定,我们仍可方便地计算出 Pod 的资源请求和约束。 Pod 对特定资源类型的请求/约束值是 Pod 中各容器对该类型资源的请求/约束值的总和。

 

Kubernetes 中的资源单位


CPU 的含义

CPU 资源的约束和请求以 cpu 为单位。

Kubernetes 中的一个 cpu 等于云平台上的 1 个 vCPU/核和裸机 Intel 处理器上的 **1 个超线程 **。

你也可以表达带小数 CPU 的请求。spec.containers[].resources.requests.cpu 为 0.5 的 Container 肯定能够获得请求 1 CPU 的容器的一半 CPU 资源。表达式 0.1 等价于表达式 100m, 可以看作 “100 millicpu”。有些人说成是“一百毫 cpu”,其实说的是同样的事情。 具有小数点(如 0.1)的请求由 API 转换为 100m;最大精度是 1m。 因此,或许你应该优先考虑使用 100m 的形式。

CPU 总是按绝对数量来请求的,不可以使用相对数量; 0.1 的 CPU 在单核、双核、48 核的机器上的意义是一样的。

内存的含义

内存的约束和请求以字节为单位。你可以使用以下后缀之一以一般整数或定点数字形式来表示内存: E、P、T、G、M、K。你也可以使用对应的 2 的幂数:Ei、Pi、Ti、Gi、Mi、Ki。 例如,以下表达式所代表的是大致相同的值:

128974848、129e6、129M、123Mi

 

创建一个Pod的工作流程


Kubernetes基于list-watch机制的控制器架构,实现组件间交互的解耦。其他组件监控自己负责的资源,当这些资源发生变化时,kube apiserver会通知这些组件,这个过程类似于发布与订阅。

 

Pod中影响调度的主要属性


 在集群当中创建pod的时候,哪些属性会影响pod的调度呢,有哪些熟悉可以指定pod分布在指定的节点上呢?

[root@k8s-master ~]# kubectl create deployment nginx --image=nginx
[root@k8s-master ~]# kubectl expose deployment nginx --port=80 --type=NodePort
[root@k8s-master ~]# kubectl get deploy nginx -o yaml
dnsPolicy: ClusterFirst
        restartPolicy: Always
        schedulerName: default-scheduler
        securityContext: {}
        terminationGracePeriodSeconds: 30

这里就能够看到一部分调度策略了,比如使用调度器的名称为default-scheduler

 

Pod中影响调度的主要属性


 

上面这些红框最终都是会影响pod的调度

 

资源限制对Pod调度的影响


2核就2*1000=2000m
2c=2000m
1c=1000m
0.5c=500m

 如果pod不限制的资源的使用,如果其中一个容器出现异常,那么会消耗该宿主机上面的所有资源,因为容器之间是没有任何限制的。这样可能会导致其他容器没有可用的资源去运行,从而无法正常提供服务。

为了防止该事情的发生就会对容器资源做限制。为了实现配置k8s做了两方面的配置

容器资源限制:

容器最大资源限制

• resources.limits.cpu

• resources.limits.memory

容器使用的最小资源需求,作为容器调度时资源分配的依据:(容器最小使用的资源是多少​​​​​​​)

• resources.requests.cpu

• resources.requests.memory

其实在调度的时候只有requests会影响调度,而limit只是一个实际的限制。只不过都在resource字段下完成的。

下面是一个成功调度的例子

[root@k8s-master ~]# cat pod-resource.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-resource 
spec:
  containers:
  - name: web
    image: nginx
    resources:
      requests:   # 容器最小资源配额
        memory: "64Mi"
        cpu: "250m"
      limits:     # 容器最大资源上限
        memory: "128Mi"
        cpu: "500m"
# Limits一定要比request高

[root@k8s-master ~]# kubectl apply -f pod-resource.yaml 
pod/pod-resource created
[root@k8s-master ~]# kubectl get pod -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
pod-resource            1/1     Running   0          75s   10.244.169.143   k8s-node2   <none>           <none>


[root@k8s-master ~]# kubectl describe pod pod-resource 

    Limits:
      cpu:     500m
      memory:  128Mi
    Requests:
      cpu:        250m
      memory:     64Mi

查看k8s-node2节点详细信息 

[root@k8s-master ~]# kubectl describe node k8s-node2
Non-terminated Pods:          (8 in total)
  Namespace                   Name                                     CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                   ----                                     ------------  ----------  ---------------  -------------  ---
  default                     pod-resource                             250m (25%)    500m (50%)  64Mi (4%)        128Mi (9%)     3m56s


# 标识该节点为pod分配的配额
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests    Limits
  --------           --------    ------
  cpu                500m (50%)  500m (50%)
  memory             64Mi (4%)   128Mi (9%)
  ephemeral-storage  0 (0%)      0 (0%)
  hugepages-1Gi      0 (0%)      0 (0%)
  hugepages-2Mi      0 (0%)      0 (0%)

# 这部分为可分配的
Allocatable:
  cpu:                1
  ephemeral-storage:  7717729063
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             1319260Ki
  pods:               110

下面是一个调度失败的例子

[root@k8s-master ~]# cat pod-resource2.yml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-resource2 
spec:
  containers:
  - name: web
    image: nginx
    resources:
      requests: 
        memory: "4Gi"
        cpu: "2000m"


[root@k8s-master ~]# kubectl apply -f pod-resource2.yml 
pod/pod-resource2 created


[root@k8s-master ~]# kubectl get pod -o wide
NAME                    READY   STATUS    RESTARTS   AGE    IP               NODE        NOMINATED NODE   READINESS GATES
pod-resource2           0/1     Pending   0          78s    <none>           <none>      <none>           <none>

[root@k8s-master ~]# kubectl describe pod pod-resource2
Events:
  Type     Reason            Age   From  Message
  ----     ------            ----  ----  -------
  Warning  FailedScheduling  113s        0/3 nodes are available: 3 Insufficient cpu, 3 Insufficient memory.
  Warning  FailedScheduling  113s        0/3 nodes are available: 3 Insufficient cpu, 3 Insufficient memory.

# 可以看出给了三个节点,每个节点的CPU和内存都不足,所以处于pending状态,如果要运行起来到等到有节点的资源可以满足

可以看到资源限制会对pod调度产生影响,K8s会根据Request的值去查找有足够资源的Node来调度此Pod。

资源的配额request只会影响这个Pod请求的最小资源,在节点当中有没有资源可以满足它。如果要将pod调度到某个节点上,这样是满足不了的.

当你创建一个 Pod 时,Kubernetes 调度程序将为 Pod 选择一个节点。 每个节点对每种资源类型都有一个容量上限:可为 Pod 提供的 CPU 和内存量。 调度程序确保对于每种资源类型,所调度的容器的资源请求的总和小于节点的容量。 请注意,尽管节点上的实际内存或 CPU 资源使用量非常低,如果容量检查失败, 调度程序仍会拒绝在该节点上放置 Pod。