单一的OpenShift集群可以运行数量非常可观的资源和对象。下表列出了从OpenShift 3.11到OpenShift 4.3各个版本支持的对象和资源的最高配置上限(可以看出基本没有变化)。根据Red Hat的说明,这些上限大都并非硬性限制,而是当环境没有出现性能差( Poor Performance)情况时的最高数量。例如每个node运行的pod数量其实是可以超过250个,只不过当所有node部署的pod都超过250个,而且还运行了2000个node,此时OpenShift集群会出现性能显著下降的情况。下表中的数量上限其实都是经过Red Hat测试验证过的,所以用户可以在项目中放心大规模部署OpenShift集群。不过这些数据使用的是样例应用,因此在实际项目中,能运行的对象规模还需要根据用户的应用情况进行评估。
在OpenShift中,为了能合理地分配和使用对象和资源,我们可以对一个对象使用相关资源(可以是另一类对象,或着是诸如CPU、内存这样的系统资源)的数量进行控制和限制。资源限制主要针对以下三个层面:
OpenShift使用以下对象实现资源使用限额:
可以用ClusterResourceQuota对象来限制租户消耗的资源总量,因为它可以使用基于项目的Annotation和Lable的Selector来实现跨多个项目限制资源使用的总配额(不像ResourceQuota仅与一个项目相关)。ClusterResourceQuota对象不属于任何一个项目,它属于整个集群。
$ oc create clusterresourcequota USER-ID-crq --project-annotation-selector openshift.io/requester=USER-ID --hard limits.cpu=20 --hard limits.memory=40Gi
$ oc describe clusterquota USER-ID-crq
Name: USER-ID-crq
Created: 38 hours ago
Labels: <none>
Annotations: <none>
Namespace Selector: ["USER-ID-xxx" "USER-ID-yyy" "USER-ID-zzz"]
Label Selector:
AnnotationSelector: map[openshift.io/requester:USER-ID]
Resource Used Hard
-------- ---- ----
limits.cpu 17500m 20
limits.memory 41064Mi 45Gi
可以用ResourceQuota对象来限制一个项目中能消耗的资源量,ResourceQuota对象属于一个特性项目。
$ oc new-project USER-ID-resourcequota
$ oc create resourcequota -n USER-ID-resourcequota my-quota --hard=cpu=10,memory=10G,pods=10,services=10,replicationcontrollers=10,resourcequotas=10,secrets=20,persistentvolumeclaims=10
resourcequota/my-quota created
$ oc get resourcequota
NAME CREATED AT
my-quota 2020-02-21T00:56:44Z
$ oc describe resourcequota my-quota
Name: my-quota1
Namespace: user1-resourcequota
Resource Used Hard
-------- ---- ----
cpu 0 10
memory 0 10G
persistentvolumeclaims 0 10
pods 0 10
replicationcontrollers 0 10
resourcequotas 1 10
secrets 9 20
services 0 10
$ oc get resourcequota my-quota -o yaml
apiVersion: v1
kind: ResourceQuota
metadata:
creationTimestamp: "2020-02-21T00:53:03Z"
name: my-quota
namespace: user1-resourcequota
resourceVersion: "5783782"
selfLink: /api/v1/namespaces/user1-resourcequota/resourcequotas/my-quota
uid: db282194-95fd-4eb8-959b-f02a470958e9
spec:
hard:
cpu: "10"
memory: 10G
persistentvolumeclaims: "10"
pods: "10"
replicationcontrollers: "10"
resourcequotas: "10"
secrets: "20"
services: "10"
status:
hard:
cpu: "10"
memory: 10G
persistentvolumeclaims: "10"
pods: "10"
replicationcontrollers: "10"
resourcequotas: "10"
secrets: "20"
services: "10"
used:
cpu: "0"
memory: "0"
persistentvolumeclaims: "0"
pods: "0"
replicationcontrollers: "0"
resourcequotas: "1"
secrets: "9"
services: "0"
$ oc get limitrange
NAME CREATED AT
user1-resourcequota-core-resource-limits 2020-02-22T06:51:32Z
$ oc describe limitrange USER-ID-resourcequota-core-resource-limits
Name: user1-resourcequota-core-resource-limits
Namespace: user1-resourcequota
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu - 4 50m 500m -
Container memory - 6Gi 256Mi 1536Mi -
Pod cpu - 4 - - -
Pod memory - 12Gi - - -
$ oc run ruby-hello-world --image=openshift/ruby-hello-world --limits=cpu=200m,memory=100Mi --requests=cpu=100m,memory=50Mi
$ oc get event
LAST SEEN TYPE REASON OBJECT MESSAGE
77s Normal DeploymentCreated deploymentconfig/ruby-hello-world Created new replication controller "ruby-hello-world-1" for version 1
16s Warning FailedCreate deploymentconfig/ruby-hello-world Error creating deployer pod: pods "ruby-hello-world-1-deploy" is forbidden: failed quota: my-quota: must specify cpu,memory
注意:以上说明当为项目定义了resourcequota后,需要为运行在项目中的所有Pod定义CPU和内存使用量限额。一方面可以在Pod中显式定义,另一方面还可通过后面章节中的LimitRange对象为项目中所有Pod提供缺省的CPU和内存使用限额(这个措施在OpenShift 4.2较新版本和4.3以后版本中会自动创建)。
可以通过2种方式可限制Pod和Container对使用资源的数量:
LimitRange对象可对项目中的计算资源进行约束限制,这些资源包括:Pod,Container,Image,ImageStream和PVC。如果这些项目中的已有的资源已经超过了限制,则新的资源将无法创建。
$ oc new-project USER-ID-limit-project
apiVersion: "v1"
kind: "LimitRange"
metadata:
name: "project-limitrange"
spec:
limits:
- type: "Pod"
max:
cpu: "2"
memory: "1Gi"
min:
cpu: "200m"
memory: "60Mi"
- type: "Container"
max:
cpu: "2"
memory: "1Gi"
min:
cpu: "100m"
memory: "4Mi"
default:
cpu: "400m"
memory: "200Mi"
defaultRequest:
cpu: "200m"
memory: "100Mi"
maxLimitRequestRatio:
cpu: "10"
$ oc create -f project-limitrange.yaml -n USER-ID-limit-project
$ oc describe limits/project-limitrange -n USER-ID-limit-project
Name: project-limit-project
Namespace: USER-ID-limit-project
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Pod cpu 200m 2 - - -
Pod memory 60Mi 1Gi - - -
Container cpu 100m 2 200m 400m 10
Container memory 4Mi 1Gi 100Mi 200Mi -
我们还可为每个Pod以及其中的Container进一步指定特定的使用资源上限。需要注意的是当针对Pod单独定义的使用资源超过了其所属项目为Pod定义的缺省能用资源的时候(或整个租户级别已经没有可用资源的时候),Pod是不能正常启动的。
$ oc run ruby-hello-world --image=openshift/ruby-hello-world --limits=cpu=200m,memory=100Mi --requests=cpu=100m,memory=50Mi -n USER-ID-limit-project
$ oc delete all --all -n USER-ID-limit-project
$ oc run ruby-hello-world --image=openshift/ruby-hello-world --limits=cpu=500m,memory=100Mi --requests=cpu=300m,memory=100Mi -n USER-ID-limit-project
$ oc get pod -n USER-ID-limit-project
NAME READY STATUS RESTARTS AGE
ruby-hello-world-1-lwb2n 1/1 Running 0 45s
$ oc describe pod ruby-hello-world-1-lwb2n -n USER-ID-limit-project
Name: ruby-hello-world-1-lwb2n
Namespace: user1-limitrange
Priority: 0
Node: ip-10-0-132-181.ec2.internal/10.0.132.181
Start Time: Fri, 21 Feb 2020 05:44:39 +0000
Labels: deployment=ruby-hello-world-1
deploymentconfig=ruby-hello-world
run=ruby-hello-world
Annotations: k8s.v1.cni.cncf.io/networks-status:
[{
"name": "openshift-sdn",
"interface": "eth0",
"ips": [
"10.128.2.45"
],
"dns": {},
"default-route": [
"10.128.2.1"
]
}]
openshift.io/deployment-config.latest-version: 1
openshift.io/deployment-config.name: ruby-hello-world
openshift.io/deployment.name: ruby-hello-world-1
openshift.io/scc: restricted
Status: Running
IP: 10.128.2.45
IPs:
IP: 10.128.2.45
Controlled By: ReplicationController/ruby-hello-world-1
Containers:
ruby-hello-world:
Container ID: cri-o://c8e1886fc9133141fdc9ebae5a3df884ca32f4313c0e53cf68fc4f038ab6390a
Image: openshift/ruby-hello-world
Image ID: docker.io/openshift/ruby-hello-world@sha256:52384f1f4cc137335b59c25eb69273e766de7646c04c22f66648313f12f1828f
Port: <none>
Host Port: <none>
State: Running
Started: Fri, 21 Feb 2020 05:45:02 +0000
Ready: True
Restart Count: 0
Limits:
cpu: 500m
memory: 100Mi
Requests:
cpu: 300m
memory: 100Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-6ww8z (ro)
。。。
apiVersion: v1
kind: Pod
metadata:
name: only-limit
spec:
containers:
- name: only-limit-2-ctr
image: openshift/hello-openshift
resources:
limits:
cpu: "1"
$ oc apply -f only-limit.yaml -n USER-ID-limit-project
containers:
- image: openshift/hello-openshift
imagePullPolicy: Always
name: only-request-2-ctr
resources:
resources:
limits:
cpu: "1"
memory: 200Mi
requests:
cpu: "1"
memory: 100Mi
apiVersion: v1
kind: Pod
metadata:
name: only-request
spec:
containers:
- name: only-request-2-ctr
image: openshift/hello-openshift
resources:
requests:
cpu: "0.3"
$ oc apply -f only-request.yaml -n USER-ID-limit-project
containers:
- image: openshift/hello-openshift
imagePullPolicy: Always
name: only-request-2-ctr
resources:
limits:
cpu: 400m
memory: 200Mi
requests:
cpu: 300m
memory: 100Mi
在OpenShift中还可对Constainer占用网络带宽进行限制,这主要是在Pod中为Container配置kubernetes.io/ingress-bandwidth和kubernetes.io/egress-bandwidth参数实现的。
{
"kind": "Pod",
"spec": {
"containers": [
{
"image": "openshift/hello-openshift",
"name": "hello-openshift"
}
]
},
"apiVersion": "v1",
"metadata": {
"name": "bandlimit",
"annotations": {
"kubernetes.io/ingress-bandwidth": "10M",
"kubernetes.io/egress-bandwidth": "10M"
}
}
}
$ oc create -f bandlimit.json -n USER-ID-limit-project
pod/bandwidth created
$ oc describe pod/bandwidth -n USER-ID-limit-project
Name: bandwidth
Namespace: user1-limitrange
Priority: 0
Node: ip-10-0-132-181.ec2.internal/10.0.132.181
Start Time: Fri, 21 Feb 2020 06:29:20 +0000
Labels: <none>
Annotations: k8s.v1.cni.cncf.io/networks-status:
[{
"name": "openshift-sdn",
"interface": "eth0",
"ips": [
"10.128.2.46"
],
"dns": {},
"default-route": [
"10.128.2.1"
]
}]
kubernetes.io/egress-bandwidth: 10M
kubernetes.io/ingress-bandwidth: 10M
openshift.io/scc: anyuid
。。。
https://docs.openshift.com/container-platform/4.3/applications/quotas/quotas-setting-per-project.html
https://docs.openshift.com/container-platform/3.11/admin_guide/limits.html
https://docs.openshift.com/container-platform/3.11/dev_guide/compute_resources.html
https://kubernetes.io/zh/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/