1 2 3 4 5 6 7 作者:李晓辉 联系方式: 1. 微信:Lxh_Chat 2. 邮箱:939958092@qq.com  
让用户自己在 Kubernetes 上创建工作负载确实能提高效率。不过呢,集群的资源是有限的,像 CPU、内存和存储这些。如果工作负载太多,超出了集群能提供的资源,那工作负载可能就运行不正常了。好在 Kubernetes 有个厉害的功能,工作负载可以提前预留资源,还能声明资源的上限。这样就能避免资源被过度占用,保证工作负载都能正常运行,工作负载可以指定下列属性:
资源限值 
第一招叫“资源限值”,就是给工作负载设个“天花板”,规定它在正常运行时最多能用多少资源。要是工作负载突然出故障或者负载突然变高,这个限值就能防止它把资源全占了,影响到别的工作负载正常运行。
资源请求 
第二招是“资源请求”,工作负载可以提前说一声自己最少需要多少资源。Kubernetes 就会按照这些请求去分配资源,要是集群里资源不够,新的工作负载就暂时不能部署。这样一来,就能保证每个工作负载都能拿到自己需要的资源,安稳运行。
pod上的资源配额 说到创建工作负载,可以给每个 Pod 设置资源配额。就像给 Pod 划个“资源小房间”,让它在里面“住”得刚刚好。
比如说,一个 Pod 既设置了 request(请求配额),又设置了 limits(资源限制)。这就好比给 Pod 定了个“最低生活保障”和“最高消费限额”。
至于单位嘛,内存单位挺有意思的:1Mi 等于 1024KB,这是按二进制来的;1M 等于 1000KB,这是按十进制来的。要是啥单位都不带,那就是字节啦。
CPU 单位也很简单:1 等于 1000m,这个还能带小数点,比如 1.5 就等于 1500m。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 cat  >  quota.yml  <<EOF apiVersion:  v1 kind:  Pod metadata:   name:  pod-limit    labels:      name:  pod-limit  spec:   containers:    -  name:  app      image:  registry.ocp4.example.com:8443/redhattraining/hello-world-nginx:latest      imagePullPolicy:  IfNotPresent      resources:        requests:          memory:  "64Mi"          cpu:  "100m"        limits:          memory:  "128Mi"          cpu:  "100m"  EOF 
创建并确认配额
1 2 3 4 5 6 7 8 [student@workstation ~]$ oc describe -f quota.yml | grep -A 6 Limits     Limits:       cpu:     100m       memory:  128Mi     Requests:       cpu:        100m       memory:     64Mi     Environment:  <none> 
虽然给单个 Pod 设置了资源配额,看起来好像挺合理的,但要是有人“机灵”得很,多创建几个 Pod,那资源不就偷偷被占多了嘛。就像本来给一个 Pod 分了 100m 的 CPU,那要是搞两个 Pod,不就变成 200m 了,三个就是 300m,这要是不限制,资源就被“薅羊毛”了。
所以,为了避免这种情况,就得给整个项目(project)设置个上限,就像给整个“资源池”拉起一道防线,不管对方怎么创建 Pod,总的资源都不会超过这个上限。这样一来,资源分配就更公平、更可控啦,也能防止有人“钻空子”。
项目级别设置资源限额 先创建一个project
1 oc new-project lixiaohui 
给lixiaohui整个project设置配额
1 2 3 4 5 6 7 8 9 10 11 12 13 14 cat  >  project-quota.yml  <<EOF apiVersion:  v1 kind:  ResourceQuota metadata:   name:  lixiaohuiquota    namespace:  lixiaohui  spec:   hard:      pods:  "1"      requests.cpu:  "1"      requests.memory:  "1Gi"      limits.cpu:  "2"      limits.memory:  "2Gi"  EOF 
创建并查看
这样比较直观的显示了我们目前可以申请多少资源
1 2 3 4 5 [student@workstation ~]$ oc create -f project-quota.yml resourcequota/lixiaohuiquota created [student@workstation ~]$ oc get -f project-quota.yml NAME             AGE   REQUEST                                                LIMIT lixiaohuiquota   8s    pods: 0/1, requests.cpu: 0/1, requests.memory: 0/1Gi   limits.cpu: 0/2, limits.memory: 0/2Gi 
我们试着创建一个超过项目配额的资源请求,看看是否失败
我们申请的内存不超标,但是CPU不管是request还是limit,都是超标的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 cat  >  exec-pod.yml  <<EOF apiVersion:  v1 kind:  Pod metadata:   name:  frontend    namespace:  lixiaohui  spec:   containers:    -  name:  app      image:  registry.ocp4.example.com:8443/redhattraining/hello-world-nginx:latest      imagePullPolicy:  IfNotPresent      resources:        requests:          memory:  "64Mi"          cpu:  "150m"        limits:          memory:  "128Mi"          cpu:  "150m"  EOF 
从下面的报错来看,你超过限额就不行,我们通过给project设置限额,杜绝了用多个pod来绕过限额的可能
1 2 [student@workstation ~]$ oc create -f exec-pod.yml Error from server (Forbidden): error when creating "exec-pod.yml" : pods "frontend"  is forbidden: exceeded quota: lixiaohuiquota, requested: limits.cpu=15,requests.cpu=15, used: limits.cpu=0,requests.cpu=0, limited: limits.cpu=2,requests.cpu=1 
项目级别设置数量限额 在 Kubernetes 中,可以通过 ResourceQuota(资源配额)  来限制一个命名空间(Namespace)内资源的数量和使用情况。这个功能就像是给整个项目设置了一个“资源天花板”,防止资源被过度占用。
为什么需要数量限额? 
假设你有一个项目,里面有多个团队在创建 Pod。如果不对数量进行限制,每个团队可能会无限制地创建 Pod,导致整个集群资源被耗尽。比如,一个团队可能为了测试,一口气创建了 100 个 Pod,而其他团队可能只需要 10 个 Pod 就够用了。这样一来,资源分配就会变得很不公平,甚至可能导致集群崩溃。
如何设置数量限额? 
数量限额可以通过设置 ResourceQuota  来实现。你可以指定一个命名空间内可以创建的 Pod 数量上限。比如,你可以设置一个项目最多只能创建 50 个 Pod。这样一来,不管团队怎么折腾,Pod 的总数都不会超过 50 个。
我们看下面这个例子,在lixiaohui的命名空间中只允许创建一个pod
1 2 3 4 5 6 7 8 9 10 cat  >  number-quota.yml  <<-EOF apiVersion:  v1 kind:  ResourceQuota metadata:   name:  number-quota    namespace:  lixiaohui    spec:   hard:      count/pods:  "1"  EOF 
创建并验证
1 2 3 4 5 [student@workstation ~]$ oc create -f number-quota.yml resourcequota/number-quota created [student@workstation ~]$ oc get -f number-quota.yml NAME           AGE   REQUEST           LIMIT number-quota   3s    count/pods: 0/1 
我们来创建一个3副本的deployment
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 cat  >  deployment.yml  <<EOF apiVersion:  apps/v1 kind:  Deployment metadata:   name:  nginx-deployment    namespace:  lixiaohui        labels:      app:  nginx  spec:   replicas:  3    selector:      matchLabels:        app:  nginx    template:      metadata:        labels:          app:  nginx      spec:        containers:        -  name:  nginx          image:  registry.ocp4.example.com:8443/redhattraining/hello-world-nginx:latest          imagePullPolicy:  IfNotPresent          ports:          -  containerPort:  8080          resources:            requests:              memory:  "64Mi"              cpu:  "150m"            limits:              memory:  "128Mi"              cpu:  "150m"  EOF 
创建并验证发现,只有1个在线
1 2 3 4 5 [student@workstation ~]$ oc create -f deployment.yml deployment.apps/nginx-deployment created [student@workstation ~]$ oc get -f deployment.yml NAME               READY   UP-TO-DATE   AVAILABLE   AGE nginx-deployment   1/3     1            1           4s 
查询为什么只有一个在线
清晰的看到,是因为超过了pod数量才失败
1 2 3 4 5 6 7 8 9 10 [student@workstation ~]$ oc get replicasets.apps NAME                          DESIRED   CURRENT   READY   AGE nginx-deployment-577877fb79   3         1         1       48s [student@workstation ~]$ oc describe replicasets.apps nginx-deployment-577877fb79 ... Events:   Type     Reason            Age                From                   Message   ----     ------            ----               ----                   -------   Normal   SuccessfulCreate  63s                replicaset-controller  Created pod: nginx-deployment-577877fb79-2lxp6   Warning  FailedCreate      63s                replicaset-controller  Error creating: pods "nginx-deployment-577877fb79-rtj2j"  is forbidden: exceeded quota: lixiaohuiquota, requested: pods=1, used: pods=1, limited: pods=1 
跨project的集群级别配额 有时候,一个集群里有好多项目(也就是命名空间),每个项目都有自己的资源配额。但有时候,集群管理员可能需要从更高的层面来控制资源,比如限制某个开发团队管理的所有项目总共能用多少资源。这时候,就得用到集群级别的资源配额啦。
想象一下,有一群开发人员,他们管理着好几个项目(也就是好几个命名空间)。每个项目都有自己的资源配额,比如每个项目最多能用 10GB 的内存。但是,集群管理员可能担心这些项目加起来会用掉太多资源,比如整个集群的内存。这时候,就需要一个更高层次的控制手段。
集群资源配额的作用 
集群资源配额就像是给整个集群加了一道“总闸门”。它不仅可以限制单个项目(命名空间)的资源使用,还可以限制一组项目(比如某个开发团队管理的所有项目)的总资源使用量。这样一来,即使每个项目都有自己的配额,整个团队的资源使用也不会超过管理员设定的上限。
如何实现? 
集群资源配额的实现方式和命名空间资源配额有点像,但多了一个“选择器”(Selector)。选择器的作用就是告诉 Kubernetes:“嘿,我要对这几个特定的项目(命名空间)应用这个配额。”比如,你可以指定一个开发团队管理的所有项目,然后给这些项目设置一个总的内存使用上限。
集群管理员可能会对资源应用限制,而不限于单个命名空间。例如,一组开发人员管理着许多命名空间。命名空间配额可以限制每个命名空间的 RAM 使用量。但是,集群管理员无法限制该开发人员组管理的所有工作负载的总 RAM 使用量。
这里我们给具有quota=lixiahui标签的所有namespace设置了配额
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cat  >  cluster-quota.yml  <<-EOF apiVersion:  quota.openshift.io/v1 kind:  ClusterResourceQuota metadata:   name:  cluster-quota  spec:   quota:      hard:        limits.memory:  400Mi    selector:      annotations:  {}     labels:        matchLabels:          quota:  lixiahui  EOF 
创建并确认
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [student@workstation ~]$ oc create -f cluster-quota.yml clusterresourcequota.quota.openshift.io/cluster-quota created [student@workstation ~]$ oc get -f cluster-quota.yml NAME            AGE cluster-quota   3s [student@workstation ~]$ oc describe -f cluster-quota.yml Name:           cluster-quota Created:        48 seconds ago Labels:         <none> Annotations:    <none> Namespace Selector: [] Label Selector: quota=lixiahui AnnotationSelector: map[] Resource        Used    Hard --------        ----    ---- limits.memory      0       400Mi 
我们创建一个zhangsan的project,然后给这个project添加上预期的标签,再创建一个名为lixiaohui的pod
1 2 3 4 5 6 7 8 9 10 11 oc new-project zhangsan oc label namespace zhangsan quota=lixiahui oc describe project zhangsan Name:                   zhangsan Created:                23 seconds ago Labels:                 kubernetes.io/metadata.name=zhangsan                         pod-security.kubernetes.io/audit=restricted                         pod-security.kubernetes.io/audit-version=v1.24                         pod-security.kubernetes.io/warn=restricted                         pod-security.kubernetes.io/warn-version=v1.24                         quota=lixiahui 
看上去我们预期的quota=lixiahui标签已经存在,先来看看集群配额是否已经选中zhangsan
没问题,已经选中了zhangsan
1 2 3 4 5 6 7 8 9 10 11 [student@workstation ~]$ oc describe clusterresourcequotas.quota.openshift.io cluster-quota Name:           cluster-quota Created:        3 minutes ago Labels:         <none> Annotations:    <none> Namespace Selector: ["zhangsan" ] Label Selector: quota=lixiahui AnnotationSelector: map[] Resource        Used    Hard --------        ----    ---- limits.cpu      0       400Mi 
我们创建一个pod看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 cat  >  lixiaohui-pod.yml  <<EOF apiVersion:  v1 kind:  Pod metadata:   name:  lixiaohui    namespace:  zhangsan  spec:   containers:    -  name:  app      image:  registry.ocp4.example.com:8443/redhattraining/hello-world-nginx:latest      imagePullPolicy:  IfNotPresent      resources:        requests:          memory:  "64Mi"          cpu:  "150m"        limits:          memory:  "128Mi"          cpu:  "150m"  EOF 
查看配额,然后创建出来,再看看配额
1 2 [student@workstation ~]$ oc create -f lixiaohui-pod.yml pod/lixiaohui created 
再看的时候,就用了128Mi了
1 2 3 4 5 6 7 8 9 10 11 12 [student@workstation ~]$ oc describe clusterresourcequotas.quota.openshift.io cluster-quota Name:           cluster-quota Created:        19 minutes ago Labels:         <none> Annotations:    kubectl.kubernetes.io/last-applied-configuration={"apiVersion" :"quota.openshift.io/v1" ,"kind" :"ClusterResourceQuota" ,"metadata" :{"annotations" :{},"name" :"cluster-quota" },"spec" :{"quota" :{"hard" :{"limits.memory" :"400Mi" }},"selector" :{"annotations" :{},"labels" :{"matchLabels" :{"quota" :"lixiahui" }}}}} Namespace Selector: ["zhangsan" ] Label Selector: quota=lixiahui AnnotationSelector: map[] Resource        Used    Hard --------        ----    ---- limits.memory   128Mi   400Mi 
我们再创建一个lisi的project,并分配quota=lixiaohui的标签,然后再创建一个pod,如果集群资源配额又上升,就说明不管你在哪儿创建,都会受到这个限制
1 2 oc new-project lisi oc label namespace lisi quota=lixiahui 
我们创建一个pod看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 cat  >  lixiaohui-pod.yml  <<EOF apiVersion:  v1 kind:  Pod metadata:   name:  lixiaohui    namespace:  lisi  spec:   containers:    -  name:  app      image:  registry.ocp4.example.com:8443/redhattraining/hello-world-nginx:latest      imagePullPolicy:  IfNotPresent      resources:        requests:          memory:  "64Mi"          cpu:  "150m"        limits:          memory:  "128Mi"          cpu:  "150m"  EOF 
创建并验证配额是否上升,从刚才的128,上升到256,说明不管你在哪个project,都会受到限制
1 2 3 4 5 6 7 8 9 10 11 12 13 [student@workstation ~]$ oc create -f lixiaohui-pod.yml [student@workstation ~]$ oc describe clusterresourcequotas.quota.openshift.io cluster-quota Name:           cluster-quota Created:        25 minutes ago Labels:         <none> Annotations:    kubectl.kubernetes.io/last-applied-configuration={"apiVersion" :"quota.openshift.io/v1" ,"kind" :"ClusterResourceQuota" ,"metadata" :{"annotations" :{},"name" :"cluster-quota" },"spec" :{"quota" :{"hard" :{"limits.memory" :"400Mi" }},"selector" :{"annotations" :{},"labels" :{"matchLabels" :{"quota" :"lixiahui" }}}}} Namespace Selector: ["zhangsan"  "lisi" ] Label Selector: quota=lixiahui AnnotationSelector: map[] Resource        Used    Hard --------        ----    ---- limits.memory   256Mi   400Mi