默认情况下pod运行没有任何CPU和内存的限制。这意味着系统中的pod可以尽可能多的消耗CPU和内存在pod执行的节点。
基于多种原因用户可能希望对系统中的单个pod的资源使用量进行限制。
例如:
1.集群中的每个节点都有2GB内存。集群管理员不同意pod需要超过2GB的内存,因为这个集群里面没有节点可以支持这个需求。为了预防pod永久不能调度到一个节点上,管理员拒绝超过2GB的pod。
2.在一个组织中两个团体分享一个集群,分别运行开发和生产工作负载。生产工作负载消耗8G内存,但是开发工作负载消耗512MB内存。管理员给每一个工作负载建立分离的命名空间,并且给每个命名空间限制。
3.用户可以创建一个资源消耗刚刚低于机器资源容量的pod。可用的剩余空间太小,但是每个节点都是如此对于整个集群是很昂贵的浪费。因此,集群管理员希望设置限制pod必须消耗其平均节点大小至少20%内存和CPU,为了提供统一的调度和限制浪费。
这个例子演示如何限制应用于一个Kubernetes命名空间控制每个pod最大/最小资源限制。此外,这个例子演示了在没有最终用户指定值的情况下如何将默认资源限制应用于pod。
有关详细信息参阅限制范围文档。Kubernetes资源模型详细信息参考资源。
第0步:前提条件
这个例子需要一个运行的Kubernetes集群。如何建立一个集群参考Getting Started guides。如果你还没有准备好,请转到<kubernetes>目录。
第1步: 创建一个命名空间
这个例子将在自己的命名空间工作,以演示涉及的概念。
让我们创建一个叫limit-example的命名空间:
$ kubectl create namespace limit-example
namespace "limit-example" created
注意 kubectl命令可以打印创建或突变的资源的类型和名称,然后可以在后续的命令中使用:
$ kubectl get namespaces
NAME STATUS AGE
default Active 51s
limit-example Active 45s
第2步:应用命名空间限制
给我们的命名空间创建一个简单的限制。
kubectl create -f docs/admin/limitrange/limits.yaml --namespace=limit-example
limitrange "mylimits" created
让我们看一下给我们命名空间施加的限制。
$ kubectl describe limits mylimits --namespace=limit-example
Name: mylimits
Namespace: limit-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Pod cpu 200m 2 - - -
Pod memory 6Mi 1Gi - - -
Container cpu 100m 2 200m 300m -
Container memory 3Mi 1Gi 100Mi 200Mi -
在这种情境下,我们已经说过:
1.如果指定了最大的资源约束(2 CPU和1G内存 在这种情况下),那么必须为所有的容器指定资源限制。尝试创建pod的时候,未指定资源限制将导致验证错误。注意在limits.yaml中设置了默认的限制 (300m CPU 和 200Mi内存)。
2.如果指定了最小的资源约束(100m CPU和3Mi内存 在这种情况下)那么必须给所有的容器资源指定一个请求。尝试创建pod的时候,未指定请求将导致验证错误。注意 在limits.yaml给defaultRequest设置了默认的值(200m CPU和100Mi内存)。
3.对于任何pod,所有容器内存资源请求必须大于等于6Mi,所有的容器内存总和必须小于等于1Gi;所有容器的CPU总和请求必须大于等于200m,所有容器的资源限制必须小于等于2。
第3步:创建点施行
命名空间中列举的限制,只在集群中的pod创建或更新的时候施行。如果修改限制为不同的值范围,将不会影响以前在命名空间中创建的pod。如果资源(CPU或内存)受到限制,那么用户将会在创建的时候收到错误说明。
我们发布一个Deployment创建包含一个容器的pod演示如果将默认值应用于每一个pod。
$ kubectl run nginx --image=nginx --replicas=1 --namespace=limit-example
deployment "nginx" created
注意 kubectl run
创建一个Deployment在大于等于1.2版本的Kubernetes集群。如果你是使用的老版本,创建replication controllers代替。如果你想获取老的行为,使用--generator=run/v1
创建replication controllers。详细信息参考 kubectl run
。Deployment管理1个包含单独容器的pod副本。让我们看看它管理的pod。首先找到这个pod的名字:
$ kubectl get pods --namespace=limit-example
NAME READY STATUS RESTARTS AGE
nginx-2040093540-s8vzu 1/1 Running 0 11s
让我们以yaml的格式打印这个pod的输出(使用 -o yaml),然后查看resources字段。
注意你的pod名字跟这里可能不一样:
$ kubectl get pods nginx-2040093540-s8vzu --namespace=limit-example -o yaml | grep resources -C 8
resourceVersion: "57"
selfLink: /api/v1/namespaces/limit-example/pods/nginx-2040093540-ivimu
uid: 67b20741-f53b-11e5-b066-64510658e388
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources:
limits:
cpu: 300m
memory: 200Mi
requests:
cpu: 200m
memory: 100Mi
terminationMessagePath: /dev/termination-log
volumeMounts:
注意 我们的nginx容器已经占用了命名空间默认的CPU和内存资源限制和请求。
让我们创建一个超过我们允许限制的pod,它有一个容器请求3个CPU内核。
$ kubectl create -f docs/admin/limitrange/invalid-pod.yaml --namespace=limit-example
Error from server: error when creating "docs/admin/limitrange/invalid-pod.yaml": Pod "invalid-pod" is forbidden: [Maximum cpu usage per Pod is 2, but limit is 3., Maximum cpu usage per Container is 2, but limit is 3.]
让我们创建一个在允许限制边界内的pod。
$ kubectl create -f docs/admin/limitrange/valid-pod.yaml --namespace=limit-example
pod "valid-pod" created
现在看看这个pod的resources字段。
$ kubectl get pods valid-pod --namespace=limit-example -o yaml | grep -C 6 resources
uid: 3b1bfd7a-f53c-11e5-b066-64510658e388
spec:
containers:
- image: gcr.io/google_containers/serve_hostname
imagePullPolicy: Always
name: kubernetes-serve-hostname
resources:
limits:
cpu: "1"
memory: 512Mi
requests:
cpu: "1"
memory: 512Mi
注意 这个pod指定了明确的资源限制和请求,所以它没有使用命名空间的默认值。
注意:在运行容器的物理节点上默认Kubernetes设置中强制执行CPU资源限制。除非管理员采用以下方式部署kubelet:
$ kubelet --help
Usage of kubelet
....
--cpu-cfs-quota[=true]: Enable CPU CFS quota enforcement for containers that specify CPU limits
$ kubelet --cpu-cfs-quota=false ...
第4步:清除
要删除此示例使用的资源,只需删除limit-example命名空间。
$ kubectl delete namespace limit-example
namespace "limit-example" deleted
$ kubectl get namespaces
NAME STATUS AGE
default Active 12m
总结
集群管理员想要限制单个容器或pod资源消耗的总计,可以限制每个kubernetes命名空间的允许范围。在没有明确任务的情况下,Kubernetes系统能够应用默认的资源限制和请求,以便限制pod在节点上的资源消耗量。