九、资源配额、资源限制、服务质量Qos
1. 节点可用性延伸
已经从多个维度保障了服务的可用性,比如调度到不同的机器和机房、配置可靠的健康检查等。但是上述措施都是基于应用级别去做的,如果我们的Kubernetes集群用来运行容器的节点有了故障,带来的影响是很大的,所以在保证应用本身的前提下,也要通过一些措施保障节点的可用性。
节点故障大部分都是由于资源分配不合理、超额分配引起的,因此需要用某个技术手段保证节点的资源不会过大地超额分配。
Kubernetes为我们提供了开箱即用的资源管理,可以通过ResourceQuota和LimitRange的配合防止节点资源超额分配。
2. 资源配额(ResourceQuota)
2.1 什么是资源配额
在生产环境中,可能会有多个Kubernetes集群,面向开发环境、测试环境、预生产环境和生产环境等。面对多k8s集群管理员,或者多项目组自己的命名空间进行操作时,并不知道Kubernetes集群是多大规模,也不知道有多少可调度的资源,所以在这样就很容易造成集群资源过量分配,引起集群不可用。
在这种情况下,需要对每个项目组合理地分配资源,用以避免超出集群的承载能力,也可以减少废弃资源没有及时清理带来的资源浪费。
资源配额的工作方式如下:
- 不同的团队可以在不同的命名空间下工作。这可以通过 RBAC强制执行。
- 集群管理员可以为每个命名空间创建一个或多个 ResourceQuota 对象。
- 当用户在命名空间下创建资源(如 Pod、Service 等)时,Kubernetes 的配额系统会跟踪集群的资源使用情况, 以确保使用的资源用量不超过 ResourceQuota 中定义的硬性资源限额。
- 如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN), 并在消息中给出有可能违反的约束。
- 如果命名空间下的计算资源 (如 cpu 和 memory)的配额被启用, 则用户必须为这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。 提示: 可使用 LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。
2.2 ResourceQuota配置
可资源配额如下:
资源名称 | 描述 |
limits.cpu | 所有非终止状态的 Pod,其所有Pod的CPU限额总量不能超过该值。 |
limits.memory | 所有非终止状态的 Pod,其所有Pod的内存限额总量不能超过该值。 |
requests.cpu | 所有非终止状态的 Pod,其所有Pod的CPU需求总量不能超过该值。 |
requests.memory | 所有非终止状态的 Pod,其所有Pod的内存需求总量不能超过该值。 |
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 总数上限。 |
[root@k8s-master01 resource]# cat resourceQuota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: resource-test
labels:
app: resourcequota
spec:
hard:
pods: 2
requests.cpu: 0.5
requests.memory: 512Mi
limits.cpu: 5
limits.memory: 16Gi
configmaps: 2
requests.storage: 40Gi
persistentvolumeclaims: 20
replicationcontrollers: 20
secrets: 20
services: 50
services.loadbalancers: "2"
services.nodeports: "10"
创建命名空间,并创建ResourceQuota限额
kubectl create namespace rq-test
kubectl create -f resourceQuota.yaml -n rq-test
查看该命名空间的限额与使用情况。
从 Kubernetes v1.9 开始,支持使用如下格式的限定名称空间中标准类型对象的总数量:
- count/persistentvolumeclaims
- count/services
- count/secrets
- count/configmaps
- count/replicationcontrollers
- count/deployments.apps
- count/replicasets.apps
- count/statefulsets.apps
- count/jobs.batch
- count/cronjobs.batch
- count/deployments.extensions
#示例
apiVersion: v1
kind: ResourceQuota
metadata:
name: resource-test
labels:
app: resourcequota
spec:
hard:
count/services: 2
count/deployments.apps: 2
Tips:ResourceQuota作用于Pod,并且有命名空间限制!
3. 资源限制(LimitRange)
3.1 什么是资源限制
和ResourceQuota不同的是,LimitRange用来配置默认值,也就是一个Pod如果没有配置要用多少内存、CPU,LimitRange会在创建Pod时添加一个默认值。
可能出现的情况:
- 如果创建了一个Pod或Deployment没有指定requests和limits字段,是不是就意味着资源配额对内存和CPU的限制变成了一个摆设,在CPU和内存为0时无限制地创建Pod,从而造成无法统计的情况。
- 假如一个Namespace分配了16核、64GB的空间,之后创建一个申请了requests.cpu为16、requests.memory为64GB的容器,那么单个Pod就能把整个Namespace的资源全部占用。
为了防止这类情况发生,Kubernetes又引出了另一个概念:LimitRange,用于针对没有配置requests和limits的资源设置一个默认值,同时配置单个资源最大的requests和limits,这样就能解决上述问题。
Tips:LimitRange不会影响已经创建的资源!
3.2 LimitRange配置
可以通过LimitRange配置默认的requests和limits值,用来解决创建的资源没有配置或配置过小的requests和limits带来的问题。
一个 LimitRange(限制范围) 对象提供的限制能够做到:
- 在一个命名空间中实施对每个Pod最小和最大的资源使用量的限制。
- 在一个命名空间中实施对每个 PersistentVolumeClaim能申请的最小和最大的存储空间大小的限制。
比如创建一个requests.cpu默认为0.5(0.5为半颗CPU,1个CPU等于1000m)、requests.memory为256MB、limits.cpu为1、limits.memory为512MB,限制PVC申请空间的最小值为1GB、最大值为2GB的LimitRange。
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-mem-limit-range
spec:
limits:
- default: #默认limits配置
cpu: 1
memory: 512Mi
defaultRequest: #默认Request配置
cpu: 0.5
memory: 256Mi
type: Container
- type: PersistentVolumeClaim #默认PVC设置
max:
storage: 2Gi
min:
storage: 1Gi
Tips:LimitRange作用于Pod,并且有命名空间限制!
本篇文章内容参考杜宽的《云原生Kubernetes全栈架构师》,视频、资料文档等,大家可以多多支持!还有k8s训练营、“我为什么这么菜”知乎博主等资料文档,感谢无私奉献!