一、K8s 资源限制ResourceQuota
1.1.1 基于租户和团队的资源限制
在一个Kubernetes 集群中,可能会有不同的团队或者不同的租户共同使用,此时可以针对不同的租户和不同的团队进行资源限制。
首先创建两个Namespace 模拟两个租户:
# kubectl create namespace customer2
# kubectl create namespace customer1
配置租户1 的资源限制:
# vim customer1-resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: customer1-quota
namespace: customer1
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "50"
persistentvolumeclaims: "10"
requests.storage: 400Gi
services: "40"
count/replicasets.apps: 1k
配置租户2 的资源限制:
# vim customer2-resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: customer2-quota
namespace: customer2
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "16"
limits.memory: 32Gi 
 pods: "50" 
 count/replicasets.apps: 1k
创建一个Deployment 测试:
# kubectl create deploy test-quota --image=registry.cn-beijing.aliyuncs.com/dotbalo/redis:7.2.5 -n customer1
此时并没有Pod 产生:
# kubectl get po -n customer1
No resources found in customer1 namespace.
添加资源请求:
resources:
requests:
cpu: "3"
memory: "10Mi"
limits:
cpu: "4"
memory: "1024Mi"
由于资源请求大于资源限制,所以也不会产生Pod,此时可以查看RS 的日志:
exceeded quota: customer1-quota, requested: requests.cpu=3, used: requests.cpu=0, limited: requests.cpu=2
1.1.2 基于环境和项目的资源限制
和租户与团队一致,一个集群也可能同时存在多个环境和项目,此时也可以基于环境和项目进行资源限制。
# kubectl create namespace project-dev
# kubectl create namespace project-test
限制dev 的资源:
# vim dev-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: project-dev
spec:
hard:
requests.cpu: "4"
requests.memory: 4Gi
limits.cpu: "8"
limits.memory: 8Gi
pods: "40"
services: "20"
count/replicasets.apps: 1k
限制test 的资源:
# vim test-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: test-quota
namespace: project-test
spec:
hard:
requests.cpu: "8"
requests.memory: 8Gi
limits.cpu: "16"
limits.memory: 16Gi
pods: "100"
services: "40"
count/replicasets.apps: 1k
1.1.3 基于命名空间的资源限制
通常情况下,出于稳定性和安全性考虑,应该对每个Namespace 不受控制的资源进行限制,比如Pod 和ReplicaSet,防止异常创建导致集群故障。此时可以给每个Namespace 添加一个默认的资源限制:
# vim default-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: default-quota
spec:
hard:
count/pods: "1000"
count/replicasets.apps: 2k
二、K8s 资源限制LimitRange
1.1.1 设置容器默认的资源配置
在Kubernetes 集群中部署任何的服务,都建议添加resources 参数,也就是配置内存和CPU资源的请求和限制。如果不想给每个容器都手动添加资源配置,此时可以使用limitRange 实现给每个容器自动添加资源配置。
比如默认给每个容器默认添加cpu 请求0.5 核,内存请求256Mi,cpu 最大使用量1 核,内存最大使用量512Mi:
apiVersion: v1
kind: LimitRange
metadata:
spec:
name: cpu-mem-limit-range
limits:
- default:
cpu: 1
memory: 512Mi
defaultRequest:
cpu: 0.5
memory: 256Mi
type: Container
创建一个没有资源配置的服务:
# kubectl create deploy test-quota --image=registry.cn-beijing.aliyuncs.com/dotbalo/redis:7.2.5 -n customer1
此时Pod 里面的容器会被添加默认的resources 配置(多个容器也会同时添加,已配置的参数不会覆盖):
# kubectl get po -n customer1 -oyaml | grep resources -A 6
resources:
limits:
cpu: "1"
memory: 512Mi
requests:
cpu: 500m
memory: 256Mi
1.1.2 限制容器可以使用的最大和最小资源
除了给容器配置默认的资源请求和限制,limitRange 还可以限制容器能使用的最大资源及可以配置的最小资源。
比如限制容器能配置最大内存是1G,最大CPU 是800m,最小内存是128M,最小CPU 是10m:
# vim min-max.yaml
apiVersion: v1
kind: LimitRange
metadata:
spec:
name: min-and-max
limits:
- max:
cpu: "800m"
memory: 1Gi
min:
cpu: "10m"
memory: 128Mi
type: Container
首先给服务添加一个默认的资源配置:
resources:
limits:
cpu: "2"
memory: 2Gi
requests:
cpu: 1m
memory: 1Mi
创建最大值和最小值的限制:
# kubectl create -f min-max.yaml -n customer1
此时更新Deployment 的资源配置不在limitRange 的限制范围,RS 就会出现如下报错:
minimum cpu usage per Container is 10m, but request is 2m, minimum
memory usage per Container is 128Mi, but request is 2Mi, maximum cpu usage
per Container is 800m, but limit is 2, maximum memory usage per Container is 1Gi, but limit is 2Gi
1.1.3 限制存储使用的大小范围
除了限制CPU 和内存,也会限制PVC 的大小范围,此时把type 改为PersistentVolumeClaim即可。
比如限制每个PVC 只能使用大于等于1G,小于等于3G 的空间:
# vim storage-limit.yaml
apiVersion: v1
kind: LimitRange
metadata:
spec:
name: storagelimits
limits:
- type: PersistentVolumeClaim
max:
storage: 3Gi
min:
storage: 1Gi
创建一个申请5G 的PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-test
spec:
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
storageClassName: local-storage
accessModes:
- ReadWriteMany
此时会有如下报错:
# kubectl create -f pvc.yaml
Error from server (Forbidden): error when creating "pvc.yaml": persistentvolumeclaims "pvc-test" is forbidden: maximum storage usage per PersistentVolumeClaim is 3Gi, but request is 5Gi
此时把storage 改为限制范围内即可正常创建。
三、K8s 服务质量QoS
1.1.1 实现QoS 为Guaranteed 的Pod
Guaranteed 级别的Pod 具有最高的优先级,Kubernetes 会确保这些Pod 获得足够的资源, 也就是Kubernetes 调度器会确保这些Pod 调度到能够提供所需资源的节点上。
配置Guaranteed 级别的Pod,需要满足如下条件:
1) Pod 中的每个容器必须指定limits.memory 和requests.memory,并且两者需要相等
2) Pod 中的每个容器必须指定limits.cpu 和requests.cpu,并且两者需要相等
limits:
cpu: 200m
memory: 512Mi
requests:
cpu: 200m
memory: 512Mi
1.1.2 实现QoS 为Burstable 的Pod
Burstable 级别的Pod 具有中等优先级,Kubernetes 会尽量满足其资源请求,但在资源紧张时可能会被驱逐,Kubernetes 调度器会确保这些Pod 调度到能够提供所需资源的节点上,如果节点上有额外的资源,这些Pod 可以使用超过其请求的资源。
配置Burstable 级别的Pod,需要满足如下条件:
1) Pod 不符合Guaranteed 的配置要求
2) Pod 中至少有一个容器配置了requests.cpu 或requests.memory
requests:
memory: 128Mi
cpu: 100m
1.1.3 实现QoS 为BestEffort 的Pod
BestEffort 级别的Pod 是最低优先级,Kubernetes 不保证这些Pod 获得任何资源,在资源紧张时,这些Pod 最先被驱逐。同时Kubernetes 调度器会尝试将这些Pod 调度到任何节点上,但不保证节点上有足够的资源。
配置BestEffort 级别的Pod,不配置resources 字段即可。