为容器管理资源


当你定义 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会通知这些组件,这个过程类似于发布与订阅。

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

 

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中影响调度的主要属性


Kubernetes 资源限制对Pod调度的影响_调度程序_02

 

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

 

资源限制对Pod调度的影响


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

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。