开头语
写在前面:如有问题,以你为准,
目前24年应届生,各位大佬轻喷,部分资料与图片来自网络
内容较长,页面右上角目录方便跳转
kubectl exec kube-apiserver-master -n kube-system -- kube-apiserver -h | grep enable-admission-plugins | grep? ResourceQuota
apiVersion: v1
kind: ResourceQuota
metadata:
? name: storage
? namespace: default # 限制 default 名称空间
spec:
? hard: # 是每种指定资源所强制实施的硬性限制集合
??? pods: "3" # 限制 Pod 的数量
??? requests.cpu: "1" # 限制 pod cpu 数量
??? requests.memory: 1Gi # 限制 内存使用量
??? requests.storage: "10G" # 限制 存储使用量
? used: # 是当前命名空间中所观察到的资源总用量
如果对某个命名空间做出了限制,会导致在这个命名空间下创建的pod其配置里面就要对自身做出限制,不然会创建不了,导致报错
在调度的时候: requests 比较重要,这可以帮助 Kubernetes 调度器决定在哪个节点上运行 Pod
在运行的时候: limits????? 比较重要,?? 这有助于确保容器不会无限制地使用资源。
当设置 limits 而没有设置 requests 时,Kubernetes 默认令 requests 等于 limits
requests(资源请求): 定义了对应容器需要的最小资源量
?imits(资源限制):定义了这个容器最大可以消耗的资源上限
(1)对于 CPU,如果 pod 中服务使用 CPU 超过设置的limits,pod 不会被 kill 掉但会被限制。如果没有设置 limits ,pod 可以使用全部空闲的 CPU 资源。
(2)对于内存,当一个 pod 使用内存超过了设置的limits,pod 中 container 的进程会被 kernel 因 OOM kill 掉。当 container 因为 OOM 被 kill 掉时,系统倾向于在其原所在的机器上重启该 container 或本机或其他重新创建一个 pod
0 <= requests <=Node Allocatable, requests <= limits <= Infinity
1. 经常在 K8s 集群种部署负载的时候不设置 CPU?requests?或将 CPU?requests?设置得过低(这样“看上去”就可以在每个节点上容纳更多 Pod )。在业务比较繁忙的时候,节点的 CPU 全负荷运行。业务延迟明显增加,有时甚至机器会莫名其妙地进入 CPU 软死锁等“假死”状态
2. 类似地,部署负载的时候,不设置内存?requests?或者内存?requests?设置得过低,这时会发现有些 Pod 会不断地失败重启。而不断重启的这些 Pod 通常跑的是 Java 业务应用,但是这些 Java 应用本地调试运行地时候明明都是正常的。
3.在 K8s 集群中,集群负载并不是完全均匀地在节点间分配的,通常内存不均匀分配的情况较为突出,集群中某些节点的内存使用率明显高于其他节点。 K8s 作为一个众所周知的云原生分布式容器编排系统,一个所谓的事实上标准,其调度器不是应该保证资源的均匀分配吗
(1)CPU 属于可压缩资源,其中 CPU 资源的分配和管理是 Linux 内核借助于完全公平调度算法( CFS )和 Cgroup 机制共同完成的
简单地讲,如果 pod 中服务使用 CPU 超过设置的 CPU?limits, pod 的 CPU 资源会被限流( throttled )。对于没有设置limit的 pod ,一旦节点的空闲 CPU 资源耗尽,之前分配的 CPU 资源会逐渐减少。不管是上面的哪种情况,最终的结果都是 Pod 已经越来越无法承载外部更多的请求,表现为应用延时增加,响应变慢,对应上面1的情形
(2)内存属于不可压缩资源, Pod 之间是无法共享的,完全独占的,这也就意味着资源一旦耗尽或者不足,分配新的资源一定是会失败的。有的 Pod 内部进程在初始化启动时会提前开辟出一段内存空间。比如 JVM 虚拟机在启动的时候会申请一段内存空间。如果内存?
requests?指定的数值小于 JVM 虚拟机向系统申请的内存,导致内存申请失败( oom-kill ),从而 Pod 出现不断地失败重启。这种情形对应于上面的情形 2
(3)另一方面, K8s 内置的调度算法不仅仅涉及到“最小资源分配节点”,还会把其他诸如 Pod 亲和性等因素考虑在内。并且 k8s 调度基于的是资源的?requests?数值,而之所以往往观察到的是内存分布不够均衡,是因为对于应用来说,相比于其他资源,内存一般是更紧缺的一类资源这种情形对应于上面的情形 3
比如当出现新的 Pod 进行调度时,调度程序会根据其当时对 Kubernetes 集群的资源描述做出最佳调度决定。但是 Kubernetes 集群是非常动态的,由于整个集群范围内的变化,比如一个节点为了维护,我们先执行了驱逐操作,这个节点上的所有 Pod 会被驱逐到其他节点去,但是当我们维护完成后,之前的 Pod 并不会自动回到该节点上来,因为 Pod 一旦被绑定了节点是不会触发重新调度的
资源名称 | 描述 |
limits.cpu | 所有非终止状态的 Pod,其 CPU 限额总量不能超过该值。 |
limits.memory | 所有非终止状态的 Pod,其内存限额总量不能超过该值。 |
requests.cpu | 所有非终止状态的 Pod,其 CPU 需求总量不能超过该值。 |
requests.memory | 所有非终止状态的 Pod,其内存需求总量不能超过该值。 |
hugepages- | 对于所有非终止状态的 Pod,针对指定尺寸的巨页请求总数不能超过此值。 |
cpu | 与 requests.cpu 相同。 |
memory | 与 requests.memory 相同。 |
apiVersion: v1
kind: ResourceQuota
metadata:
? name: mem-cpu
? namespace: default # 限制 default 名称空间
spec:
? hard:
??? requests.cpu: "1"
??? requests.memory: 1Gi
??? limits.cpu: "2"
??? limits.memory: 2Gi
requests:这是您为 Pod 请求的资源数量,即 Pod 的最小资源需求。它用于告诉 Kubernetes 集群为您的 Pod 分配多少资源。如果您设置了 requests,Kubernetes 集群将确保为 Pod 预留这些资源。这是在调度 Pod 到节点时的关键指标,它确保了节点上有足够的资源可供 Pod 使用。如果节点上没有足够的资源来满足 requests,Pod 可能无法被调度。
?limits:这是您为 Pod 设置的资源上限,即 Pod 的资源使用的最大限制。它用于限制 Pod 的资源使用,以防止它占用过多的资源并影响其他 Pod。如果您设置了 limits,Kubernetes 集群将确保 Pod 的资源使用不会超过这些限制。如果 Pod 尝试使用超出 limits 设置的资源量,它可能会被终止或受到限制。
总结一下,requests 是资源的保底需求,确保 Pod 有足够的资源可供使用,并在调度时起作用。limits 是资源的上限,用于限制 Pod 的资源使用,以确保它不会超过限制。
apiVersion: v1
kind: Pod
metadata:
? creationTimestamp: null
? labels:
??? run: web
? name: web
? namespace: test
spec:
? containers:
? - image: nginx:1.17.1
??? name: web
??? resources:
????? requests:
??????? cpu: 0.5
??????? memory: 256Mi
????? limits:
??????? cpu: 1
??????? memory: 512Mi
status: {}
[root@master cks]# kubectl create -f RQ-cpu-mem.yaml
resourcequota/mem-cpu created
[root@master cks]# kubectl get quota -n test
NAME????? AGE?? REQUEST?????????????????????????????????????? LIMIT
mem-cpu?? 13m?? requests.cpu: 0/1, requests.memory: 0/512Mi?? limits.cpu: 0/2, limits.memory: 0/1Gi
[root@master cks]# kubectl run -n test web --image=nginx:1.17.1
Error from server (Forbidden): pods "web" is forbidden: failed quota: mem-cpu: must specify limits.cpu for: web; limits.memory for: web; requests.cpu for: web; requests.memory for: web
kubectl run -n test web --image=nginx:1.17.1 --dry-run=client -oyaml > pod.yaml
[root@master cks]# kubectl apply -f pod.yaml
pod/web created
[root@master cks]# kubectl get quota -n test
NAME????? AGE?? REQUEST????????????????????????????????????????????? LIMIT
mem-cpu?? 26m?? requests.cpu: 500m/1, requests.memory: 256Mi/512Mi?? limits.cpu: 1/2, limits.memory: 512Mi/1Gi
[root@master cks]# kubectl apply -f pod.yaml
pod/web2 created
[root@master cks]# kubectl get quota -n test
NAME????? AGE?? REQUEST?????????????????????????????????????????? LIMIT
mem-cpu?? 26m?? requests.cpu: 1/1, requests.memory: 512Mi/512Mi?? limits.cpu: 2/2, limits.memory: 1Gi/1Gi
[root@master cks]# kubectl get pod -n test
NAME?? READY?? STATUS??? RESTARTS?? AGE
web??? 1/1???? Running?? 0????????? 58s
web2?? 1/1???? Running?? 0????????? 24s
资源名称 | 描述 |
requests.storage | 所有 PVC,存储资源的需求总量不能超过该值。 |
persistentvolumeclaims | 在该命名空间中所允许的 PVC 总量。 |
.storageclass.storage.k8s.io/requests.storage | 在所有与 相关的持久卷申领中,存储请求的总和不能超过该值。 |
.storageclass.storage.k8s.io/persistentvolumeclaims | 在与 storage-class-name 相关的所有持久卷申领中,命名空间中可以存在的持久卷申领总数。 |
?在 Kubernetes 1.8 版本中,本地临时存储的配额支持已经是 Alpha 功能
资源名称 | 描述 |
requests.ephemeral-storage | 在命名空间的所有 Pod 中,本地临时存储请求的总和不能超过此值。 |
limits.ephemeral-storage | 在命名空间的所有 Pod 中,本地临时存储限制值的总和不能超过此值。 |
ephemeral-storage | 与 requests.ephemeral-storage相同。 |
注意:如果所使用的是 CRI 容器运行时,容器日志会被计入临时存储配额。 这可能会导致存储配额耗尽的 Pods 被意外地驱逐出节点。 参考日志架构 了解详细信息。
apiVersion: v1
kind: ResourceQuota
metadata:
? name: storage
? namespace: default # 限制 default 名称空间
spec:
? hard:
??? requests.storage: "10G"
apiVersion: v1
kind: ResourceQuota
metadata:
? name: storage
? namespace: test
spec:
? hard:
??? requests.storage: "10G"
[root@master cks]# kubectl apply -f RQ-storage.yaml
resourcequota/storage created
[root@master cks]# kubectl get quota -n test
NAME????? AGE?? REQUEST?????????????????????????????????????? LIMIT
mem-cpu?? 51m?? requests.cpu: 0/1, requests.memory: 0/512Mi?? limits.cpu: 0/2, limits.memory: 0/1Gi
storage?? 31s?? requests.storage: 0/10G
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
? name: pvc
? namespace: test
spec:
? accessModes: # 访客模式
??? - ReadWriteMany
? resources: # 请求空间
??? requests:
????? storage: 5Gi
[
root@master cks]# kubectl apply -f RQ-pvc.yaml
persistentvolumeclaim/pvc-rq created
[root@master cks]# kubectl get pvc -n test
NAME???? STATUS??? VOLUME?? CAPACITY?? ACCESS MODES?? STORAGECLASS?? AGE
pvc-rq?? Pending???????????????????????????????????????????????????? 10s
# pending 代表没匹配大小一样的pv
[root@master cks]# kubectl get quota -n test
NAME????? AGE???? REQUEST?????????????????????????????????????? LIMIT
mem-cpu?? 56m???? requests.cpu: 0/1, requests.memory: 0/512Mi?? limits.cpu: 0/2, limits.memory: 0/1Gi
storage?? 5m28s?? requests.storage: 5Gi/10G
[root@master cks]# kubectl apply -f RQ-pvc.yaml
Error from server (Forbidden): error when creating "RQ-pvc.yaml": persistentvolumeclaims "pvc-rq-2" is forbidden: exceeded quota: storage, requested: requests.storage=5Gi, used: requests.storage=5Gi, limited: requests.storage=10G
# 因为重新创建会导致存储使用 >= 10G ,k8s 认为会超过限制
# 改成 4G 即可创建成功
[root@master cks]# kubectl apply -f RQ-pvc.yaml
persistentvolumeclaim/pvc-rq-2 unchanged
[root@master cks]# kubectl get pvc -n test
NAME?????? STATUS??? VOLUME?? CAPACITY?? ACCESS MODES?? STORAGECLASS?? AGE
pvc-rq???? Pending???????????????????????????????????????????????????? 5m14s
pvc-rq-2?? Pending???????????????????????????????????????????????????? 94s
[root@master cks]# kubectl get quota -n test
NAME????? AGE???? REQUEST?????????????????????????????????????? LIMIT
mem-cpu?? 58m???? requests.cpu: 0/1, requests.memory: 0/512Mi?? limits.cpu: 0/2, limits.memory: 0/1Gi
storage?? 7m40s?? requests.storage: 9Gi/10G
widgets 设置配额,请使用 count/widgets.example.com。
资源名称 | 描述 |
configmaps | 在该命名空间中允许存在的 ConfigMap 总数上限。 |
persistentvolumeclaims | 在该命名空间中允许存在的 PVC的总数上限。 |
pods | 在该命名空间中允许存在的非终止状态的 Pod 总数上限。Pod 终止状态等价于 Pod 的 .status.phase in (Failed,Succeeded)为真。 |
replicationcontrollers | 在该命名空间中允许存在的ReplicationController 总数上限。 |
resourcequotas | 在该命名空间中允许存在的 ResourceQuota 总数上限。 |
services | 在该命名空间中允许存在的 Service 总数上限。 |
services.loadbalancers | 在该命名空间中允许存在的 LoadBalancer 类型的 Service 总数上限。 |
services.nodeports | 在该命名空间中允许存在的 NodePort 类型的 Service 总数上限。 |
secrets | 在该命名空间中允许存在的 Secret 总数上限。 |
例如,pods 配额统计某个命名空间中所创建的、非终止状态的 Pod 个数并确保其不超过某上限值。 用户可能希望在某命名空间中设置 pods 配额,以避免有用户创建很多小的 Pod, 从而耗尽集群所能提供的 Pod IP 地址。
apiVersion: v1
kind: ResourceQuota
metadata:
? name: pods-rq
? namespace: default # 限制 default 名称空间
spec:
? hard:
??? pods: "3" # 限制 Pod 的数量
??? count/deployments.apps:"3"? # 限制 deployment 的数量
??? count/services:"3" # 限制 services 的数量
apiVersion: v1
kind: ResourceQuota
metadata:
? name: object-rq
? namespace: test # 限制 default 名称空间
spec:
? hard:
??? pods: "3" # 限制 Pod 的数量
[root@master cks]# kubectl apply -f RQ-object.yaml
resourcequota/object-rq created
[root@master cks]# kubectl get quota -n test
NAME??????? AGE?? REQUEST?????????????????????????????????????? LIMIT
mem-cpu???? 63m?? requests.cpu: 0/1, requests.memory: 0/512Mi?? limits.cpu: 0/2, limits.memory: 0/1Gi
object-rq?? 6s??? pods: 0/3
storage???? 12m?? requests.storage: 0/10G
---
apiVersion: apps/v1 # 版本号
kind: Deployment # 类型
metadata: # 元数据
? name: rq-deployment # deployment的名称
? namespace: test # 命名类型
spec: # 详细描述
? replicas: 2 # 副本数量
? selector: # 选择器,通过它指定该控制器可以管理哪些Pod
??? matchLabels: # Labels匹配规则
????? app: nginx-pod
? template: # 模块 当副本数据不足的时候,会根据下面的模板创建Pod副本
??? metadata:
????? labels:
??????? app: nginx-pod
??? spec:
????? containers:
??????? - name: nginx # 容器名称
????????? image: nginx:1.17.1 # 容器需要的镜像地址
????????? ports:
??????????? - containerPort: 80 # 容器所监听的端口
????????? resources:
??????????? requests:
????????????? cpu: 0.5
????????????? memory: 256Mi
??????????? limits:
????????????? cpu: 1
????????????? memory: 512Mi
[root@master cks]# kubectl apply -f RQ-deploy.yaml
deployment.apps/rq-deployment created
[root@master cks]# kubectl get deploy -n test
NAME??????????? READY?? UP-TO-DATE?? AVAILABLE?? AGE
rq-deployment?? 2/2???? 2??????????? 2?????????? 6s
[root@master cks]# vim RQ-deploy.yaml
[root@master cks]# kubectl get pod -n test
NAME???????????????????????????? READY?? STATUS??? RESTARTS?? AGE
rq-deployment-69f7bd5dd9-gcrdc?? 1/1???? Running?? 0????????? 46s
rq-deployment-69f7bd5dd9-h48bw?? 1/1???? Running?? 0????????? 46s
[root@master cks]# kubectl get quota -n test
NAME??????? AGE???? REQUEST?????????????????????????????????????????? LIMIT
mem-cpu???? 68m???? requests.cpu: 1/1, requests.memory: 512Mi/512Mi?? limits.cpu: 2/2, limits.memory: 1Gi/1Gi
object-rq?? 5m15s?? pods: 2/3
storage???? 18m???? requests.storage: 0/10G
# 因为 mem-cpu 的限制,所有只设置2个副本
示例:创建一个配额对象,并将其与具有特定优先级的 Pod 进行匹配
# 集群中的 Pod 可取三个优先级类之一,即 "low"、"medium"、"high"
# 为每个优先级创建一个配额对象
apiVersion: v1
kind: List
items:
- apiVersion: v1
? kind: ResourceQuota
? metadata:
??? name: pods-high
? spec:
??? hard:
????? cpu: "1000"
????? memory: 200Gi
????? pods: "10"
??? scopeSelector:
????? matchExpressions:
????? - operator : In
??????? scopeName: PriorityClass
??????? values: ["high"]
- apiVersion: v1
? kind: ResourceQuota
? metadata:
??? name: pods-medium
? spec:
??? hard:
????? cpu: "10"
????? memory: 20Gi
????? pods: "10"
??? scopeSelector:
????? matchExpressions:
????? - operator : In
??????? scopeName: PriorityClass
??????? values: ["medium"]
- apiVersion: v1
? kind: ResourceQuota
? metadata:
??? name: pods-low
? spec:
??? hard:
????? cpu: "5"
????? memory: 10Gi
????? pods: "10"
??? scopeSelector:
????? matchExpressions:
????? - operator : In
??????? scopeName: PriorityClass
??????? values: ["low"]
apiVersion: v1
kind: Pod
metadata:
? name: high-priority
spec:
? containers:
? - name: high-priority
??? image: ubuntu
??? command: ["/bin/sh"]
??? args: ["-c", "while true; do echo hello; sleep 10;done"]
??? resources:
????? requests:
??????? memory: "10Gi"
??????? cpu: "500m"
????? limits:
??????? memory: "10Gi"
??????? cpu: "500m"
? priorityClassName: high # priorityClassName 指的是什么,就优先使用这个优先级的配额约束。
apiVersion: v1
kind: LimitRange
metadata:
? name: cpu-min-max-demo-lr
? namespace: default # 限制 default 命名空间
spec:
? limits:
? - max:? # 对应limits的最大值
????? cpu: "800m"
????? memory: 1Gi
??? min: # 对应request的最小值
????? cpu: "200m"
????? memory: 200Mi
??? type: Container
# Pod 中的容器的 cpu 的范围是 200m~800m
# Pod 中的容器的 memory 的范围是 200mi~1Gi
apiVersion: v1
kind: LimitRange
metadata:
? name: mem-min-max-demo-lr
? namespace: default # 限制 default 命名空间?
spec:
? limits:
? - max:
????? memory: 1Gi
??? min:
????? memory: 500Mi # Pod 中的容器的 memory 的范围是 500Mi~1Gi
??? type: Container
apiVersion: v1
kind: LimitRange
metadata:
? name: mem-limit-range
? namespace: default # 限制 default 命名空间????
spec:
? limits:
? - default:
????? memory: 512Mi
??? defaultRequest:
????? memory: 256Mi # 为命名空间配置默认的内存请求和限制
??? type: Container
apiVersion: v1
kind: LimitRange
metadata:
? name: storagelimits
spec:
? limits:
? - type: PersistentVolumeClaim
??? max:
????? storage: 2Gi
??? min:
????? storage: 1Gi
?
?apiVersion: v1
kind: ResourceQuota
metadata:
? name: storagequota
spec:
? hard:
??? persistentvolumeclaims: "5" # 限制 PVC 数目和累计存储容量
??? requests.storage: "5Gi"
?
当您创建一个新的 Pod 并没有显式指定资源请求时,Kubernetes会使用
Default Request作为默认值。这可以帮助 Kubernetes 调度器决定在哪个节点上运行 Pod
如果您没有显式指定资源限制,Kubernetes会使用Default Limit作为默认值。这有助于确保容器不会无限制地使用资源
apiVersion: v1
kind: LimitRange
metadata:
? name: cpu-limit-range
? namespace: default # 限制 default 命名空间???
spec:
? limits:
? - default: # 可以与 max 一起设置
????? cpu: 1
??? defaultRequest:
????? cpu: 500m # 声明了一个默认的 CPU 请求和一个默认的 CPU 限制
??? type: Container
apiVersion: v1
kind: LimitRange
metadata:
? name: cpu-min-max-demo-lr
? namespace: test # 限制 default 命名空间
spec:
? limits:
? - max:? # 对应limits的最大值
????? cpu: "800m"
????? memory: 1Gi
??? min: # 对应request的最小值
????? cpu: "200m"
????? memory: 200Mi
??? type: Container
# Pod 中的容器的 cpu 的范围是 200m~800m
# Pod 中的容器的 memory 的范围是 200mi~1Gi
其中 Default 参考的是 min 和 max ,因为没有对 default 单独设置
[root@master cks]# kubectl get limits -n test
NAME????????????????? CREATED AT
cpu-min-max-demo-lr?? 2023-11-06T11:42:17Z
[root@master cks]# kubectl describe limits -n test
Name:?????? cpu-min-max-demo-lr
Namespace:? test
Type??????? Resource? Min??? Max?? Default Request? Default Limit? Max Limit/Request Ratio
----??????? --------? ---??? ---?? ---------------? -------------? -----------------------
Container?? cpu?????? 200m?? 800m? 800m???????????? 800m?????????? -
Container?? memory??? 200Mi? 1Gi?? 1Gi????????????? 1Gi??????????? -