Managing Compute Resources for Containers(管理容器的计算资源)

译者按:本节中,笔者将request翻译成最小需求,limit翻译成最大限制。由于出现的次数太多,故而绝大多数地方直接不翻译了,大家可以当做术语来阅读。

指定 Pod 时,可选择指定每个容器需要多少CPU和内存(RAM)。当容器指定了最小资源需求时,Scheduler可对Pod调度到哪个Node上进行更好的决策。当容器具有指定的资源限制时,可以指定的方式,处理Node上资源的争抢。有关资源的最小需求和最大限制之间的差异的更多信息,请参阅 Resource QoS

Resource types(资源类型)

CPU内存都是资源类型 。资源类型有基本单元。CPU以核心为单位指定,内存以字节为单位指定。

CPU和内存统称为计算资源 ,也可称为资源 。 计算资源是可以请求、分配和消费的,可测量的数量。它们与 API resources 。 API资源(如Pods和 Services 是可通过Kubernetes API Server读取和修改的对象。

Resource requests and limits of Pod and Container(Pod和容器资源的最小需求与最大限制)

Pod的每个容器可指定以下一个或多个:

  • spec.containers[].resources.limits.cpu
  • spec.containers[].resources.limits.memory
  • spec.containers[].resources.requests.cpu
  • spec.containers[].resources.requests.memory

尽管只能在每个容器上指定request和limit,但这样既可方便地算出Pod资源的request和limit。特定资源类型的Pod resource request/limit是Pod中每个容器该类型资源的request/limit的总和。

Meaning of CPU(CPU的含义)

CPU资源的request和limit以cpu为单位。在Kubernetes中,一个cpu相当于:

  • 1 AWS vCPU
  • 1 GCP Core
  • 1 Azure vCore
  • 1 Hyperthread on a bare-metal Intel processor with Hyperthreading

允许小数。具有 spec.containers[].resources.requests.cpu=0.5 的容器,保证其所需的CPU资源是需要1cpu 容器资源的一半。表达式 0.1 等价于表达式 100m ,可看作“100millicpu”。有些人说“100 millicore”,表达的也是一个意思。具有小数点的请求(如 0.1 ,会由API转换为 100m ,精度不超过 1m

CPU始终被要求作为绝对数量,从不作为相对数量;0.1在单核、双核或48核机器中,表示的是相同数量的CPU。

Meaning of memory(内存的含义)

memory 的request和limit以字节为单位。可使用整数或定点整数来表示内存,并使用如下后缀之一:E、P、T、G、M、K;也可使用:Ei,Pi,Ti ,Gi,Mi,Ki。 例如,以下代表大致相同的值:

  1. 128974848, 129e6, 129M, 123Mi

如下是一个例子。如下Pod有两个容器。每个容器都有0.25 cpu和64MiB(226字节)内存的request。 每个容器的内存限制为0.5 cpu和128MiB。你可以说Pod有0.5 cpu和128 MiB内存的request,有1 cpu和256MiB内存的limit。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: frontend
  5. spec:
  6. containers:
  7. - name: db
  8. image: mysql
  9. resources:
  10. requests:
  11. memory: "64Mi"
  12. cpu: "250m"
  13. limits:
  14. memory: "128Mi"
  15. cpu: "500m"
  16. - name: wp
  17. image: wordpress
  18. resources:
  19. requests:
  20. memory: "64Mi"
  21. cpu: "250m"
  22. limits:
  23. memory: "128Mi"
  24. cpu: "500m"

How Pods with resource requests are scheduled(如何调度带有request的Pods)

当您创建一个Pod时,Kubernetes Scheduler将为Pod选择一个Node。对于各种资源类型,每个Node都有最大容量:可为Pod提供的CPU和内存量。Scheduler确保对于每种资源类型,调度到该Node的所有容器的request之和小于该Node的容量。请注意,尽管Node上的实际内存或CPU资源使用量非常低,但如果容量检查失败,那么Scheduler仍会拒绝在该Node上放置一个Pod。这样可在资源使用稍后增加时,例如在请求的高峰期,防止Node上的资源短缺。

How Pods with resource limits are run(带有资源limit的Pod是如何运行的)

当kubelet启动Pod的容器时,它将CPU和内存限制传递到容器运行时。

使用Docker时:

  • spec.containers[].resources.requests.cpu 转换为其核心值,该值可能是小数,乘以1024。该数字中的较大值或2用作 docker run 命令中 --cpu-shares 的值。

  • spec.containers[].resources.limits.cpu 转换为其millicore值并乘以100。结果值是容器每100ms可以使用的CPU时间总量。 在此间隔期间,容器不能占用超过其CPU时间的份额。

    注意 :默认配额期限为100ms。 CPU配额的最小分辨率为1ms。

  • spec.containers[].resources.limits.memory 会被转换为一个整数,并用作 docker run命令中 --memory 标志的值。

如果容器超出其内存limit,则可能会被终止。如果容器能够重新启动,则与所有其他类型的运行时故障一样,kubelet将重新启动它。

如果一个容器超出其内存request,那么当Node内存不满足要求时,Pod可能会被逐出。

容器可能被允许或不允许长时间超过其CPU limit。 然而,即使CPU使用量过大,容器也不会被杀死。

要确定容器是否由于资源limit而无法调度或被杀死,请参阅 Troubleshooting 部分。

监控计算资源使用情况(Monitoring compute resource usage)

Pod的资源使用情况被报告为Pod status的一部分。

如果为集群配置了 optional monitoring ,那么即可从监控系统查询Pod资源的使用情况。

Troubleshooting(故障排查)

My Pods are pending with event message failedScheduling

如果Scheduler找不到任何Pod能够匹配的Node,则Pod将保持unscheduled状态。每当调度程序找不到地方调度Pod时,会产生一个事件,如下所示:

  1. $ kubectl describe pod frontend | grep -A 3 Events
  2. Events:
  3. FirstSeen LastSeen Count From Subobject PathReason Message
  4. 36s 5s 6 {scheduler } FailedScheduling Failed for reason PodExceedsFreeCPU and possibly others

在上述示例中,由于Node上的CPU资源不足,名为“frontend”的Pod无法调度。 如果内存不足,也可能会导致失败,并提示类似的错误消息(PodExceedsFreeMemory)。一般来说,如果一个Pod处于pending状态,并带有这种类型的消息,有几件事情要尝试:

  • 向集群添加更多Node。
  • 终止不需要的Pod,为处于pending的Pod腾出空间。
  • 检查Pod是否不大于所有Node。例如,如果所有Node的容量为 cpu: 1 ,那么request = cpu: 1.1 的Pod将永远不会被调度。

可使用 kubectl describe nodes 命令检查Node的容量和数量。 例如:

  1. $ kubectl describe nodes e2e-test-minion-group-4lw4
  2. Name: e2e-test-minion-group-4lw4
  3. [ ... lines removed for clarity ...]
  4. Capacity:
  5. alpha.kubernetes.io/nvidia-gpu: 0
  6. cpu: 2
  7. memory: 7679792Ki
  8. pods: 110
  9. Allocatable:
  10. alpha.kubernetes.io/nvidia-gpu: 0
  11. cpu: 1800m
  12. memory: 7474992Ki
  13. pods: 110
  14. [ ... lines removed for clarity ...]
  15. Non-terminated Pods: (5 in total)
  16. Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
  17. --------- ---- ------------ ---------- --------------- -------------
  18. kube-system fluentd-gcp-v1.38-28bv1 100m (5%) 0 (0%) 200Mi (2%) 200Mi (2%)
  19. kube-system kube-dns-3297075139-61lj3 260m (13%) 0 (0%) 100Mi (1%) 170Mi (2%)
  20. kube-system kube-proxy-e2e-test-... 100m (5%) 0 (0%) 0 (0%) 0 (0%)
  21. kube-system monitoring-influxdb-grafana-v4-z1m12 200m (10%) 200m (10%) 600Mi (8%) 600Mi (8%)
  22. kube-system node-problem-detector-v0.1-fj7m3 20m (1%) 200m (10%) 20Mi (0%) 100Mi (1%)
  23. Allocated resources:
  24. (Total limits may be over 100 percent, i.e., overcommitted.)
  25. CPU Requests CPU Limits Memory Requests Memory Limits
  26. ------------ ---------- --------------- -------------
  27. 680m (34%) 400m (20%) 920Mi (12%) 1070Mi (14%)

由如上输出可知,如果一个Pod的request超过1120mCPU或6.23Gi内存,它将不适合该Node。

通过查看 Pods 部分,可查看哪些Pod占用Node上的空间。

译者按:CPU 1120m是这么算的:1800m(Allocatable) - 680m(Allocated)。同理,内存是7474992Ki - 1070Mi

Pods所用的资源量必须小于Node容量,因为系统守护程序需要使用一部分资源。 allocatable 字段 NodeStatus 给出了Pod可用的资源量。有关更多信息,请参阅 Node Allocatable Resources

可配置 resource quota 功能,从而限制能够使用的资源总量。 如果与Namespace一起使用,则可防止一个团队占用所有资源。

My Container is terminated

由于资源不足,容器可能会被终止。要查看容器是否因为资源限制而被杀死,请在感兴趣的Pod上调用 kubectl describe pod

  1. [12:54:41] $ kubectl describe pod simmemleak-hra99
  2. Name: simmemleak-hra99
  3. Namespace: default
  4. Image(s): saadali/simmemleak
  5. Node: kubernetes-node-tf0f/10.240.216.66
  6. Labels: name=simmemleak
  7. Status: Running
  8. Reason:
  9. Message:
  10. IP: 10.244.2.75
  11. Replication Controllers: simmemleak (1/1 replicas created)
  12. Containers:
  13. simmemleak:
  14. Image: saadali/simmemleak
  15. Limits:
  16. cpu: 100m
  17. memory: 50Mi
  18. State: Running
  19. Started: Tue, 07 Jul 2015 12:54:41 -0700
  20. Last Termination State: Terminated
  21. Exit Code: 1
  22. Started: Fri, 07 Jul 2015 12:54:30 -0700
  23. Finished: Fri, 07 Jul 2015 12:54:33 -0700
  24. Ready: False
  25. Restart Count: 5
  26. Conditions:
  27. Type Status
  28. Ready False
  29. Events:
  30. FirstSeen LastSeen Count From SubobjectPath Reason Message
  31. Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {scheduler } scheduled Successfully assigned simmemleak-hra99 to kubernetes-node-tf0f
  32. Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} implicitly required container POD pulled Pod container image "gcr.io/google_containers/pause:0.8.0" already present on machine
  33. Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} implicitly required container POD created Created with docker id 6a41280f516d
  34. Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} implicitly required container POD started Started with docker id 6a41280f516d
  35. Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} spec.containers{simmemleak} created Created with docker id 87348f12526a

在上述示例中, Restart Count: 5 表示Pod中的 simmemleak 容器已终止并重启了5次。

可使用 kubectl get pod-o go-template=... 选项来获取先前终止的Containers的状态:

  1. [13:59:01] $ kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-hra99
  2. Container Name: simmemleak
  3. LastState: map[terminated:map[exitCode:137 reason:OOM Killed startedAt:2015-07-07T20:58:43Z finishedAt:2015-07-07T20:58:43Z containerID:docker://0e4095bba1feccdfe7ef9fb6ebffe972b4b14285d5acdec6f0d3ae8a22fad8b2]]

您可以看到容器由于 reason:OOM Killed 而终止,其中OOM代表Out Of Memory。

Local ephemeral storage (alpha feature)(ephemeral-storage,本地临时存储(Alpha功能))

Kubernetes 1.8版本引入了一种新的资源,用于管理本地临时存储的ephemeral-storage。 在每个Kubernetes Node中,kubelet的根目录(默认 /var/lib/kubelet )和日志目录( /var/log )存储在Node的根分区上。 此分区也可由Pod通过EmptyDir Volume、容器日志、镜像层以及容器可写层等进行共享和使用。

该分区是“短暂的”,应用程序不能对此分区的性能SLA(例如磁盘IOPS)有期望。 Local ephemeral storage管理仅适用于根分区;镜像层和可写层的可选分区超出了Local ephemeral storage的范围。

注意:如果使用可选的运行时分区,根分区将不会保存任何镜像层或可写层。

译者按:

SLA:https://baike.baidu.com/item/SLA/2957862

IOPS:https://baike.baidu.com/item/IOPS/3105194

系统SLA和监控流程:http://www.doc88.com/p-9082091179407.html

Requests and limits setting for local ephemeral storage(local ephemeral storage的request和limit设置)

Pod的每个容器可指定以下一个或多个:

  • spec.containers[].resources.limits.ephemeral-storage
  • spec.containers[].resources.requests.ephemeral-storage

ephemeral-storage 的request和limit以字节为单位。可使用整数或定点整数来表示内存,并使用如下后缀之一:E、P、T、G、M、K。也可使用:Ei,Pi,Ti ,Gi,Mi,Ki。 例如,以下代表大致相同的值:

  1. 128974848, 129e6, 129M, 123Mi

例如,以下Pod有两个容器。每个容器有一个2GiB的local ephemeral storage的request。每个容器的local ephemeral storage的limit是4GiB。因此,Pod有4GiB的local ephemeral storage的request,limit为8GiB。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: frontend
  5. spec:
  6. containers:
  7. - name: db
  8. image: mysql
  9. resources:
  10. requests:
  11. ephemeral-storage: "2Gi"
  12. limits:
  13. ephemeral-storage: "4Gi"
  14. - name: wp
  15. image: wordpress
  16. resources:
  17. requests:
  18. ephemeral-storage: "2Gi"
  19. limits:
  20. ephemeral-storage: "4Gi"

How Pods with ephemeral-storage requests are scheduled(如何调度设置了ephemeral-storage request的Pod)

当您创建一个Pod时,Kubernetes Scheduler将为Pod选择一个Node。每个Node具有能够为Pod提供的local ephemeral storage最大量值。(有关详细信息,请参见 “Node Allocatable” 。Scheduler确保调度的容器的资源需求总和小于Node的容量。

How Pods with ephemeral-storage limits run(如何运行设置了ephemeral-storage limit的Pod)

对于容器级别的隔离,如果容器可写层和日志的使用超出其存储限制,则该Pod将被驱逐。对于Pod级别的隔离,如果所有容器的local ephemeral storage使用量的综合超过限制,则Pod将被驱逐,同理,Pod的EmptyDir也是如此。

Opaque integer resources (alpha feature) (不透明的整数资源(alpha特征))

废弃通知:Kubernetes v1.8 开始,该特性已被 deprecated

既已废弃,就没有翻译的必要了。多抱半小时老婆吧。该功能的替代品是Extended Resources。

Extended Resources(扩展资源)

Kubernetes 1.8版引入了Extended Resources。Extended Resources是 kubernetes.io 域名之外的完全资格的资源名称。Extended Resources允许集群运营商发布新的Node级别的资源,否则系统将无法识别这些资源。 Extended Resources数量必须是整数,不能过大。

用户可像CPU和内存一样使用Pod spec中的Extended Resources。 Scheduler负责资源计算,以便分配给Pod的资源部超过可用的资源量。

API Server将Extended Resources的数量限制为整数,例如 3Ki3Ki 是有效的,0.51500m 是无效的。

注意:扩展资源替代 Opaque Integer Resources 。 用户可使用 kubernetes.io/ 域名之外的任何域名前缀,而非以前的 pod.alpha.kubernetes.io/opaque-int-resource- 前缀。

使用Extended Resources需要两步。首先,集群操作员必须在一个或多个Node上发布per-node Extended Resource。第二,用户必须在Pod中请求Extended Resource。

要发布新的Extended Resource,集群操作员应向API Server提交 PATCH HTTP请求,从而指定集群中Node的 status.capacity 。在此操作之后,Node的 status.capacity 将包含一个新的资源。 status.allocatable 字段由kubelet异步地使用新资源自动更新。请注意,由于Scheduler在评估Pod适应度时,会使用Node的status.allocatable值,所以在 使用新资源PATCH到Node容量 和 第一个Pod请求该Node上资源 之间可能会有短暂的延迟。

示例:

如下是一个示例,显示如何使用 curl 构建一个HTTP请求,该请求在Node k8s-node-1 (Master是k8s-master )上发布了5个“example.com/foo”资源。

  1. curl --header "Content-Type: application/json-patch+json" \
  2. --request PATCH \
  3. --data '[{"op": "add", "path": "/status/capacity/example.com~1foo", "value": "5"}]' \
  4. http://k8s-master:8080/api/v1/nodes/k8s-node-1/status

注意 :在上述请求中, ~1 是PATCH路径中字符 / 的编码。 JSON-Patch中的操作路径值被拦截为JSON指针。 有关更多详细信息,请参阅 IETF RFC 6901, section 3

要在Pod中使用Extended Resource,请将资源名称作为 spec.containers[].resources.requests map中key。

注意:Extended resources不能提交过大的值,因此如果request和limit都存在于容器spec中,则两者必须相等。

TODO:这是什么意思?

只有当所有资源的request都满足时(包括cpu、内存和任何Extended Resources),Pod才会被调度。只要资源的request无法被任何Node满足,Pod将保持在 PENDING 状态。

示例:

下面的Pod有如下request:2 cpus和1“example.com/foo”(extended resource)。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: my-pod
  5. spec:
  6. containers:
  7. - name: my-container
  8. image: myimage
  9. resources:
  10. requests:
  11. cpu: 2
  12. example.com/foo: 1

Planned Improvements(计划改进)

Kubernetes 1.5仅允许在容器上指定资源量。计划对Pod中所有容器共享资源的计费进行改进,例如 emptyDir volumes

Kubernetes 1.5仅支持容器级别的CPU/内存的request/limit。 计划添加新的资源类型,包括node disk space resource和用于添加自定义 resource types 的框架。

Kubernetes通过支持多层的 Quality of Service 支持overcommitment of resources。

overcommitment of resources:笔者理解就是资源超售。

Quality of Service在部分K8s文档上也被简写成QoS。

在Kubernetes 1.5中,对于不同云提供商,或对于同一个云提供商中的不同机器类型,一个CPU单位表达的是不同的意思。 例如,在AWS上,Node的容量在 ECUs 中报告,而在GCE中报告为逻辑内核。我们计划修改cpu资源的定义,从而使得在提供商和平台之间更一致。

What’s next

原文

https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/