系列目录html
当你编排一个pod的时候,你也能够可选地指定每一个容器须要多少CPU和多少内存(RAM).当容器请求特定的资源时,调度器能够更好地根据资源请求来肯定把pod调度到哪一个节点上.当容器请求限制特定资源时,特定节点会以指定方式对容器的资源进行限制.node
对于资源请求和资源限制的区别,能够查看QoSmysql
CPU和RAM都是资源类型,资源类型有一个基本单位.CPU资源经过单位核数来指定,内存经过单位字节来指定.它们和api资源不一样.api资源,例如pod和service是kubernetes api server能够读取和修改的对象.git
pod里的每个容器均可以指一个或多个如下内容:sql
spec.containers[].resources.limits.cpudocker
spec.containers[].resources.limits.memoryapi
spec.containers[].resources.requests.cpubash
spec.containers[].resources.requests.memoryapp
尽管请求和限制只能经过单个的容器来指定,可是咱们一般说pod的资源请求和资源限制,这样更方便.Pod对于某一特定资源的请求(或限制)是pod里单个容器请求资源的和.frontend
对cpu资源的请求和限制用单位cpu来衡量,一个cpu在kubernetes里和如下任意一个是等价的:
1 AWS vCPU
1 GCP Core
1 Azure vCore
1 IBM vCPU
在祼机因特尔超线程处理器上一个超线程
带小数的请求也是容许的.一个指定
spec.containers[].resources.requests.cpu
值为0.5的容器会被确保分配1个cpu的一半资源.值0.1和100m是等价的,能够读做100 millicpu
,也有人读做100 millicores
,实际上意义是同样的.请求资源的值为0.1将会被api转换为100m,请求的精度比1m更小是不容许的,所以100m一个较优的选择.CPU资源的请求老是绝对量,永远不会是一个相对值,值是0.1时对于单核cpu,双核cpu或者甚至48核cpu都是同样的.
对内存资源的请求/限制用字节来衡量.你可使用一个纯整数或者定点整数带上E, P, T, G, M, K这些后缀,你也可使用2的幂次方的:Ei, Pi, Ti, Gi, Mi, Ki来表示,好比如下表示的量相等
128974848, 129e6, 129M, 123Mi
如下定义的pod包含两个容器,每个都请求0.25cpu和64MiB (226 字节)的内存.每个都限制0.5cpu和128MIB内存.你能够说pod请求0.5cpu和128MiB内存,限制1cpu和256MiB内存
前面说过,pod的资源请求/限制是pod里的容器资源请求/限制的和
apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: db image: mysql env: - name: MYSQL_ROOT_PASSWORD value: "password" resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" - name: wp image: wordpress resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
当你建立一个pod,kubernetes会选择一个节点来运行.对于每种资源类型,不管是cpu仍是内存,节点能够提供给pod的都是有上限的.对于每种资源,调度器都会确保被调度的pod的请求的总和小于节点的承载能力.请注意即使节点上的cpu或者内存的使用率很是低,可是若是容量检测失败,调度器仍然可能拒绝把某一pod放到指定节点上.这确保后来资源使用增多时不会出现资源短缺的状况.
当kubelete启动了pod的容器,它会把cpu和内存的限制传入到容器的runtime里
当使用的是docker时:
spec.containers[].resources.requests.cpu
的值被转换为核数值,它也多是小数,乘1024.这个值和2二者较大的一个会被做为--cpu-shares
标识的值传入docker run
命令
spec.containers[].resources.limits.cpu
被转换为millicore
值而且乘以100.结果值是容器每100毫秒可用的cpu时间的总和.
注意默认的时间段配额是100毫秒,最小配额是1毫秒.
spec.containers[].resources.limits.memory
被转换为整数,而后做为--momory
标识的值传入docker run
命令.若是一个容器超过了它的资源限制,则它可能会被终止.若是它是可重启的(根据pod编排时重启策略),则kubelete会重启它,就像对待其它运行时错误同样.
一个容器可能会被容许或者不被容许超过超过它的cpu限制.可是超过cpu资源限制时它不会被杀掉.
failedScheduling
若是调度器找不到任何能够放置pod的节点,pod一直是未调度状态找到一个合适的节点.调度器每当找不到合适节点来放置pod,就会产生一个事件,信息以下
kubectl describe pod frontend | grep -A 3 Events Events: FirstSeen LastSeen Count From Subobject PathReason Message 36s 5s 6 {scheduler } FailedScheduling Failed for reason PodExceedsFreeCPU and possibly others
上面的示例中,因为节点的cpu资源不足,名称为frontend
的pod调度失败.相似的错误提示也多是因为内存资源不足(PodExceedsFreeMemory).通常地,若是相似这样的消息出现,能够进行如下尝试:
集群中添加更多节点
终止一些非必须进程来为挂起的pod腾出资源
检测确保pod小于node,好比节点的容量是cpu:1,若是pod请求的是cpu:1.1将永远不会被调度.
你能够经过kubectl describe nodes命令来查看节点的容量以及可分配的量:
kubectl describe nodes e2e-test-minion-group-4lw4
Name: e2e-test-minion-group-4lw4 [ ... lines removed for clarity ...] Capacity: cpu: 2 memory: 7679792Ki pods: 110 Allocatable: cpu: 1800m memory: 7474992Ki pods: 110 [ ... lines removed for clarity ...] Non-terminated Pods: (5 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits --------- ---- ------------ ---------- --------------- ------------- kube-system fluentd-gcp-v1.38-28bv1 100m (5%) 0 (0%) 200Mi (2%) 200Mi (2%) kube-system kube-dns-3297075139-61lj3 260m (13%) 0 (0%) 100Mi (1%) 170Mi (2%) kube-system kube-proxy-e2e-test-... 100m (5%) 0 (0%) 0 (0%) 0 (0%) kube-system monitoring-influxdb-grafana-v4-z1m12 200m (10%) 200m (10%) 600Mi (8%) 600Mi (8%) kube-system node-problem-detector-v0.1-fj7m3 20m (1%) 200m (10%) 20Mi (0%) 100Mi (1%) Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) CPU Requests CPU Limits Memory Requests Memory Limits ------------ ---------- --------------- ------------- 680m (34%) 400m (20%) 920Mi (12%) 1070Mi (14%)
经过上面的输出,你能够看到若是有一个pod请求或者 6.23Gi 内存,则它不适合调度到此节点上.
经过查看pods
部分,你能够看到你能够看到哪些pod在本节点上占用了资源
可供pod使用的资源数量小于节点的实际容量,这是由于系统守护进程按比例使用可用资源.allocatable
字段里的数量是pod实际可用的资源数量,详情请查看可用资源
pod可能因为资源不足被终止,你可使用kubectl describe pod
来检测pod是否因为资源达到上限被杀死
kubectl describe pod simmemleak-hra99
Name: simmemleak-hra99 Namespace: default Image(s): saadali/simmemleak Node: kubernetes-node-tf0f/10.240.216.66 Labels: name=simmemleak Status: Running Reason: Message: IP: 10.244.2.75 Replication Controllers: simmemleak (1/1 replicas created) Containers: simmemleak: Image: saadali/simmemleak Limits: cpu: 100m memory: 50Mi State: Running Started: Tue, 07 Jul 2015 12:54:41 -0700 Last Termination State: Terminated Exit Code: 1 Started: Fri, 07 Jul 2015 12:54:30 -0700 Finished: Fri, 07 Jul 2015 12:54:33 -0700 Ready: False Restart Count: 5 Conditions: Type Status Ready False Events: FirstSeen LastSeen Count From SubobjectPath Reason Message 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 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 "k8s.gcr.io/pause:0.8.0" already present on machine 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 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 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
表示simmemleak容器停止而且被重启了五次.
你能够经过kubectl get pod
加上-o go-template=...
选项来获取上次终止的容器的状态
kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-hra99
Container Name: simmemleak 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(内存溢出)
此功能在1.14版本中为beta状态
Kubernetes在1.8的版本中引入了一种相似于CPU,内存的新的资源模式:ephemeral-storage,而且在1.10的版本在kubelet中默认打开了这个特性。ephemeral-storage是为了管理和调度Kubernetes中运行的应用的短暂存储。在每一个Kubernetes的节点上,kubelet的根目录(默认是/var/lib/kubelet)和日志目录(/var/log)保存在节点的主分区上,这个分区同时也会被Pod的EmptyDir类型的volume、容器日志、镜像的层、容器的可写层所占用。ephemeral-storage即是对这块主分区进行管理,经过应用定义的需求(requests)和约束(limits)来调度和管理节点上的应用对主分区的消耗。
在节点上的kubelet启动的时候,kubelet会统计当前节点的主分区的可分配的磁盘资源,或者你能够覆盖节点上kubelet的配置来自定义可分配的资源。在建立Pod时会根据存储需求调度到知足存储的节点,在Pod使用超过限制的存储时会对其作驱逐的处理来保证不会耗尽节点上的磁盘空间。
若是运行时指定了别的独立的分区,好比修改了docker的镜像层和容器可写层的存储位置(默认是/var/lib/docker)所在的分区,将再也不将其计入ephemeral-storage的消耗。
全部的container能够指定如下一个或多个选项
spec.containers[].resources.limits.ephemeral-storage
spec.containers[].resources.requests.ephemeral-storage
对ephemeral-storage
资源的请求/限制经过字节来衡量.同上面内存的请求/限制方式同样,这里再也不细述.
好比如下pod包含两个容器,每个都对Local ephemeral storage的请求为2GiB,限制为4GiB.此时,整个pod对资源的请求为4GiB,对资源的限制为8GiB
apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: db image: mysql env: - name: MYSQL_ROOT_PASSWORD value: "password" resources: requests: ephemeral-storage: "2Gi" limits: ephemeral-storage: "4Gi" - name: wp image: wordpress resources: requests: ephemeral-storage: "2Gi" limits: ephemeral-storage: "4Gi"
ephemeral-storage
请求的pod如何调度当你建立一个pod,kubernetes调度器选择一个节点来运行它.每一个节点都有可供pod使用的最大Local ephemeral storage最大量,详细信息请查看Node Allocatable
调度器保证被调度的容器资源总和小于节点的容量
对于容器级别的隔离,若是容器的可写层( writable layer)和日志(log)超出了容量限制,容器所在的pod将会被驱离;对于pod级别的隔离,若是pod里全部容器使用的总Local ephemeral storage和pod的emptydir存储卷超过限制,pod将会被驱离.
示例
apiVersion: v1 kind: Pod metadata: name: teststorage labels: app: teststorage spec: containers: - name: busybox image: busybox command: ["bash", "-c", "while true; do dd if=/dev/zero of=$(date '+%s').out count=1 bs=10MB; sleep 1; done"] # 持续写入文件到容器的rootfs中 resources: limits: ephemeral-storage: 100Mi #定义存储的限制为100M requests: ephemeral-storage: 100Mi
测试这个Pod就能发如今容器写入超过存储限制时就会被驱逐掉了:
/tmp kubectl apply -f pod.yaml pod "teststorage" created /tmp kubectl get pod -w NAME READY STATUS RESTARTS AGE teststorage 0/1 ContainerCreating 0 3s teststorage 1/1 Running 0 7s teststorage 0/1 Evicted 0 1m
查看kubernetes的pod的事件也能看到它是因为超过了限制的ephemeral-storage被驱逐掉:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 2m default-scheduler Successfully assigned teststorage to minikube Normal SuccessfulMountVolume 2m kubelet, minikube MountVolume.SetUp succeeded for volume "default-token-l7wp9" Normal Pulling 2m kubelet, minikube pulling image "busybox" Normal Pulled 2m kubelet, minikube Successfully pulled image "busybox" Normal Created 2m kubelet, minikube Created container Normal Started 2m kubelet, minikube Started container Warning Evicted 1m kubelet, minikube pod ephemeral local storage usage exceeds the total limit of containers {{104857600 0} {<nil>} 100Mi BinarySI} Normal Killing 1m kubelet, minikube Killing container with id docker://busybox:Need to kill Pod