概要描述
计算资源概述
计算资源分为两种:资源请求(requests)和资源限制(limits)。资源请求表示容器希望被分配到的资源,可以完全保证的资源;资源限制是容器最多能使用到的资源量的上限,这个上限值会影响节点上发生资源竞争时的解决策略。
当前版本计算资源分为CPU和内存;CPU单位为core,内存单位为字节
详细说明
计算资源的参数
参数:()
spec.container[].resources.requests.cpu --> --cpu-shares
spec.container[].resources.limits.cpu --> --cpu-period
spec.container[].resources.requests.memory 没有转换docker run,只给kubernets的调度器
spec.container[].resources.limits.memory --> --memory
spec:
containers:
- args:
- boot.sh
- SEARCH_HEAD
env:
- name: HEAD_PORT
value: "9100"
- name: HEAD_TARGET_HOST
value: ts-mjx-22:9200
- name: HEAD_LOG_DIR
value: /var/log/head
image: ts-mjx-21:5000/transwarp/search-head:transwarp-5.2.3-final
imagePullPolicy: Always
name: search-head-search2
resources:
limits:
cpu: "2"
memory: 1025Mi
requests:
cpu: "2"
memory: 1Gi
- 如果上面几个没配置,会使用默认的,默认值取决于集群
- requests没配置,默认requests值=limits值
- 在任何情况下,limits值>=requests值
如果一个容器在运行过程中使用了超出其内存limits配置的内存限制(oom),那么它可能会被杀掉,如果这个容器是一个可重启的容器,那么之后它会被kubelet重新启动起来。
案例:
在docker1.13.1(tdh6.0之前用)上,当container发生oom时,并不会被重新拉起。
原因:
dockerd 1.13.1 里面存在死锁,或者在内存不足的情况下一些进程会异常退出。导致 dockerd 无法获取 containerd 的最新状态。
kubernetes认为container应该重启, 要重启container的时候. dockerd会发送kill信号给对应container的pid. 但是因为和containerd的链接断掉了. dockerd会认为这个container并没有杀掉. 会继续杀这个pid, 但是实际上pid可能已经是别的进程在使用了.
container里面的进程已经挂掉了. 但是dockerd无法发现. 这样服务的container就不会被重新启动.
现象:
pod状态为0/1 Running
使用kubectl exec 进入container时无法进入:
rpc error : code = 2 desc = containerd: container not found
查看Up的docker进程和实际docker进程发现不一致
解决方案:
升级到docker-monitor 1.0.2,重启docker-monitor和docker。
计算资源常见问题
-
pod状态为Pending,错误信息为FailedScheduling
原因:scheduler 未能找到合适的节点,或选择的节点没有足够的资源来调度,此时会产生一个Events
kubectl describe pod [pod名] | grep -A 3 Events
这个是代表这个节点上的CPU已经不足以调度这个pod,同理memory(PodExceedsFreeMemory)
Events: FirstSeen LastSeen Count From Subobject PathReason Message 36s 5s 6 {scheduler} FailedScheduling Failed for reason PodExceedsFreeCPU and possibly others
解决办法:
- 若是动态pod,且非label固定pod,那么可以增加更多的节点;
- 停止一些不必要的pod,释放资源;
- 检查pod的配置(pod配置cpu require 为2,但是节点上只有1,那么这个pod将永远无法在这个节点上调度)
可以使用kubectl describe nodes [node名]
总资源:
Capacity: cpu: 12 ephemeral-storage: 153525Mi memory: 32781488Ki pods: 200 storage: 1006802Mi
可分配资源:
Allocatable: cpu: 12 ephemeral-storage: 153525Mi memory: 32781488Ki pods: 200 storage: 1006802Mi
已分配资源
Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) CPU Requests CPU Limits Memory Requests Memory Limits ------------ ---------- --------------- ------------- 0 (0%) 0 (0%) 0 (0%) 0 (0%)
ps:TDH没有对container做任何限制,是通过限制进程的内存和CPU来限制资源。
-
pod状态为Terminated
当容器使用的资源超过了它配置的Limits,那么它可能会被强制终止,状态为Terminated。但状态为Terminated的原因不用一定是因为使用的资源超过了它配置的Limits。kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name:"}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' [pod名]
[root@ts-mjx-21 ~]# kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name:"}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' inceptor-server-inceptor1-7b67b546f6-h8q5j Container Name:inceptor-server-inceptor1 LastState: map[terminated:map[finishedAt:2019-09-04T09:07:19Z reason:Error startedAt:2019-09-04T09:07:03Z containerID:docker://b1378a99e33302c2afc1abbae19227c4a59025f157e3908e97dd9c988e615b21 exitCode:1]] [root@ts-mjx-21 ~]#
这个是未能启动docker container,即docker container出现了问题,需要排查container的问题
资源限制
创建namespace
[root@ts-mjx-21 yaml]# kubectl create namespace front
namespace "front" created
[root@ts-mjx-21 yaml]#
创建资源限制文件:limit.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: mylimits
spec:
limits:
- max:
cpu: "4"
memory: 2Gi
min:
cpu: 20m
memory: 6Mi
maxLimitRequestRatio:
cpu: 3 ---limits值:requests值<=3
memory: 2
type: Pod
---------------
- default:
cpu: 300m
memory: 200Mi
defaultRequest:
cpu: 200m
memory: 100Mi
max:
cpu: 2
memory: 1Gi
min:
cpu: 100m
memory: 3Mi
maxLimitRequestRatio:
cpu: 5
memory: 4
type: Container
pod不能设置default request和default limit。
[root@ts-mjx-21 yaml]# kubectl create -f limits.yaml --namespace=front
limitrange "mylimits" created
[root@ts-mjx-21 yaml]# kubectl describe limits mylimit --namespace=front
Name: mylimits
Namespace: front
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Pod cpu 20m 4 - - 3
Pod memory 6Mi 2Gi - - 2
Container cpu 100m 2 200m 300m 5
Container memory 3Mi 1Gi 100Mi 200Mi 4
[root@ts-mjx-21 yaml]#
[root@ts-mjx-21 yaml]# kubectl run zk --image=ts-mjx-21:5000/transwarp/zookeeper:transwarp-6.0.2-final --namespace=front
deployment "zk" created
[root@ts-mjx-21 yaml]# kubectl get pod -n front
NAME READY STATUS RESTARTS AGE
zk-69b8c766c-9xhsx 0/1 ContainerCreating 0 13s
[root@ts-mjx-21 yaml]# kubectl get pod -n front
NAME READY STATUS RESTARTS AGE
zk-69b8c766c-9xhsx 0/1 ContainerCreating 0 32s
[root@ts-mjx-21 yaml]# kubectl get pod zk-69b8c766c-9xhsx -n front -o yaml | grep resources -C 8
resourceVersion: "5418021"
selfLink: /api/v1/namespaces/front/pods/zk-69b8c766c-9xhsx
uid: 59d9615c-cf06-11e9-920b-005056a6098a
spec:
containers:
- image: ts-mjx-21:5000/transwarp/zookeeper:transwarp-6.0.2-final
imagePullPolicy: IfNotPresent
name: zk
resources:
limits:
cpu: 300m
memory: 200Mi
requests:
cpu: 200m
memory: 100Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
[root@ts-mjx-21 yaml]#
失败案例:
[root@ts-mjx-21 yaml]# cat invalid-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: invalid-zk
spec:
containers:
- name: invalid-zk
image: ts-mjx-21:5000/transwarp/zookeeper:transwarp-6.0.2-final
resources:
limits:
cpu: "3"
memory: 100Mi
[root@ts-mjx-21 yaml]# kubectl create -f invalid-pod.yaml --namespace=front
Error from server (Forbidden): error when creating "invalid-pod.yaml": pods "invalid-zk" is forbidden: maximum cpu usage per Container is 2, but limit is 3.
可以看到无法创建pod,资源限制,同样可以调整limits和requets的比例,超过2时会报错
[root@ts-mjx-21 yaml]# cat invalid-pod-limit.yaml
apiVersion: v1
kind: Pod
metadata:
name: invalid-zk
spec:
containers:
- name: invalid-zk
image: ts-mjx-21:5000/transwarp/zookeeper:transwarp-6.0.2-final
resources:
limits:
cpu: "1"
memory: 512Mi
requests:
cpu: "0.8"
memory: 250Mi
[root@ts-mjx-21 yaml]# kubectl create -f invalid-pod-limit.yaml --namespace=front
Error from server (Forbidden): error when creating "invalid-pod-limit.yaml": pods "invalid-zk" is forbidden: memory max limit to request ratio per Pod is 2, but provided ratio is 2.048000.
[root@ts-mjx-21 yaml]#
Resource QoS
requests和limits对不同计算资源类型的限制机制
在配置资源时要确保:
requests requests <= limits
-
可压缩资源
-
可压缩资源只有CPU
-
pod可以得到requests配置的CPU使用量,是否能使用超过Requests的值的部分取决于系统的负载和调度
-
空闲CPU资源按照容器Requests值的比例分配,最大不超过limits值
-
如果pod使用了超过limits值,那么cgroups会对pod中的容器的CPU做限流,如果pod没有配置limits,那么pod会抢占所有空闲的CPU资源(从v1.2版本开始默认是开启--cpu-cfs-quata,因此默认情况必须配置Limits)
-
不可压缩资源
-
不可压缩资源目前有内存
-
如果pod使用了少于requests值的内存,那么这个pod可以正常运行,但是当pod使用超过requests值而小于limits,那么当其他少于requests 内存的pod需要申请requests内的内存资源或者需要部署pod到这个节点上,那么kubernetes可能会杀掉这个pod,来释放内存
-
当pod使用了超过limits值的内存时,kernel会杀掉pod所有容器的所有进程中使用内存最多的一个,直到pod内存使用不超过limits为止。
-
对调度策略的影响
-
kubelet通过计算pod中所有容器的requests的总和来决定对pod的调度
-
不管是CPU和内存,scheduler和kubelet都会确保节点上所有的pod的requests的综合不会超过该节点上可分配给容器使用的资源容量上限
-
QoS Classes
在一个over committed的系统中,由于容器负载的波动可能导致操作系统的资源不足,那么最终可能有部分container被杀掉,有下面几个衡量container重要性的等级。
- Guaranteed(非常可靠)
pod中所有容器都定义了requests和limits,且requests和limits值相等并不为0,或只定义limits,未定义requests(未定义requests时,requests和limits一致) - Burstable(较可靠的),
pod的一部分容器在一种或多种资源类型的资源配置中定义了requests和limits,且requests小于limits(都不为0);pod一部分容器未定义资源配置(requests和limits都未定义) -
Best-Effort(不太可靠)
pod中所有容器都未定义requests和limitsTDH所有pod都是Best-Effort。
查看qosclass等级:
kubectl get pod [pod名] -o yaml | grep -C 5 qosClass
[root@ts-mjx-21 ~]# kubectl get pod inceptor-server-inceptor2-75d98bcb7b-sg579 -o yaml | grep -C 5 qosClass running: startedAt: 2019-08-29T10:49:06Z hostIP: 172.22.21.23 phase: Running podIP: 172.22.21.23 qosClass: BestEffort startTime: 2019-08-29T10:49:05Z [root@ts-mjx-21 ~]#
-
特点
当CPU Requests无法得到满足时,容器得到的CPU会被压缩限流当内存资源不足时
- Best-Effort的pod会被第一优先级杀掉。(由于没有设置limits,这类pod在资源充足情况下可以充分使用所有闲置资源)
- Burstable的Pod,当系统资源不足,且没有Best-Effort pod可以被杀死时,这类pod会被杀掉
- Guaranteed 一般情况下这类pod不会被杀死,但是当资源紧缺,又没有更低等级的pod时,也会被杀掉
-
OOM记分值
oom基础分 = 进程消耗内存百分比 * 100 * 10 (0-1000)
oom最终分 = oom基础分 + oom_score_adj (0-1000)
- Guaranteed pod的最终分一般是0或1
- BestEffort pod的最终分肯定是1000
- Burstable Pod的最终分范围是2-1000
oom_score_adj:
-
QoS | oom_score_adj |
---|---|
Guaranteed | -998 |
Burstable | min(max(2,1000-(1000 * memoryRequestBytes) / machineMenmoryCapacityBytes), 999) |
BestEffort | 1000 |
如果一个Burstable Pod的某个容器中某个进程使用的内存比容器的request值高,那么这个进 程的OOM最终分数会是1000,否则它的OOM最终分会小于1000
OOM的特殊记分规则:
- kubelet和docker的OOM_SCORE_ADJ为-998
- 如果配置进程调整值OOM_SCORE_ADJ为-999,那么这类进程不会被OOM Killer 杀掉