Kubernetes 资源管理

一. ResouceQuota

首先看一下 ResourceQuota(资源配额)的使用,资源配额是限制某个命名空间对资源使用的一个总量限制,比如内存、CPU、Pod 数量等。

1. 什么是资源配额

在生产环境中,可能会有多个 Kubernetes 集群,面向开发环境、测试环境、预生产环境和生产环境等。身为 Kubernetes 管理员,必然知道每个环境的规模有多大、可调度资源有多少,并且知道如何合理地为容器分配内存和 CPU,所以一个管理员去管理整个Kubernetes 集群时,很少会有资源分配超出集群可调度范围的情况

但在实际使用时,Kubernetes 集群并非只有一个管理员在使用,也并非只有管理员在使用。公司可能存在多个项目组,每个项目组都有属于自己的命名空间,每个项目组可以在其所在的命名空间创建资源而他们并不知道 Kubernetes 集群是多大规模,也不知道有多少可调度的资源,这样就很容易造成集群资源过量分配,引起集群不可用。在这种情况下,需要对每个项目组合理地分配资源用以避免超出集群的承载能力,也可以减少废弃资源没有及时清理带来的资源浪费

为了解决上述问题,Kubernetes 引入了 ResourceQuota 的概念,以方便 Kubernetes 管理员进行资源分配,比如给A项目组分配 16 核 64GB 的资源,并且最多只能部署 20个Pod、30 个 Service 等,这样来对 Kubernetes 的各类资源进行限制

2. 定义一个 Resourcequota

和其他资源配置方法一样,资源配额也可以通过一个 YAML 文件进行创建,比如定义一个比较常用的Resource0uota如下:

[root@k8s-master ~]# vim resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: resource-test
  labels:
    app: resourcequota
spec:
  hard:
    pods: 50
    requests.cpu: 0.5
    requests.memory: 512Mi
    limits.cpu: 5
    limits.memory: 16Gi
    configmaps: 20
    requests.storage: 40Gi
    persistentvolumeclaims: 20
    replicationcontrollers: 20
    secrets: 20
    services: 50
    services.loadbalancers: "2"
    services.nodeports: "10"

3. Resourcequota 的使用

(1)创建一个用于测试的 namespace

ku create ns quota-example

在这里插入图片描述

(2)编写 Resourcequota 的 yaml 文件

该 demo 可以限制 namespace 的PVC 不能超过1个

vim quota-objects.yaml

在这里插入图片描述

(3)创建 ResourceQuota 并 查看创建的资源限制状态

ku create -f quota-objects.yaml -n quota-example

ku get quota object-quota-demo -n quota-example -oyaml

在这里插入图片描述

备注:

从 status 字段的 userd 看出,当前的资源显示的使用量,并且 namespace 只有在创建了ResourceQuota才会启用资源使用的配额,没有创建 ResourceQuota的 namespace 不限制资源的使用

(4)编写 PVC 的 yaml 文件

vim pvc.yaml 

在这里插入图片描述

(5)创建 PVC 并查看创建的资源限制状态

ku create -f pvc.yaml -n quota-example

ku get quota object-quota-demo -n quota-example -oyaml

在这里插入图片描述

(6)编写 PVC2 的 yaml 文件

vim pvc2.yaml 

在这里插入图片描述

(7)创建 PVC 并查看创建的资源限制状态

ku create -f pvc2.yaml -n quota-example

在这里插入图片描述

此时已经无法在这个 namespace 中创建 PVC,其他资源的限制与之类似

二. LimitRange

和 ResourceQuota 不同的是,LimitRange 用来配置默认值,也就是一个 Pod 如果没有配置要用多少内存、CPU,那么 LimitRange 会在创建 Pod 时添加一个默认值

1. LimitRange 的用途

上一节讲解了每个命名空间的最大资源使用量,细心的话我们可能会发现,如果创建了一个 Pod 或Deployment 没有指定 requests 和 limits 字段,是不是就意味着资源配额对内存和 CPU 的限制变成了一个摆设?答案是肯定的,这时 CPU 和内存永远不会被限制。还有另一种情况,假如一个Namespace 分配了 16 核、64GB 的空间,之后创建一个申请了requests.cpu为16、requests.memory 为64GB 的容器,那么单个 Pod 就能把整个 Namespace 的资源全部占用

为了防止这类情况发生,Kubernetes 又引出了另一个概念:LimitRanger,用于针对没有配置requests 和 limits 的资源设置一个默认值,同时配置单个资源最大的 requests 和 Limits,这样就能解决上述问题(注意:LimitRanger 不会影响已经创建的资源)

2. 示例

(1)配置默认的requests和 limits

可以通过 LimitRanger 配置默认的 requests 和 1imits 值,用来解决创建的资源没有配置或配置过小 的 requests 和 Limits 带来的问题,比如创建一个requests.cpu 默认为0.5(0.5 为半颗 CPU, 1个CPU等于1800m)、requests.memory为256MB、limits.cpu为1、limits.memory 为 512MB 的LimitRanger

(1)编写 limitRange 的 yaml 文件

vim limitrange01.yaml

在这里插入图片描述

(2)创建 pod 并查看信息

ku create -f limitrange01.yaml 

ku get pod default-cpu-demo -o yaml

在这里插入图片描述

(3)删除资源

ku delete -f limitrange01.yaml

在这里插入图片描述

(2)配置 requests 和 limits 的范围

上述针对没有设置 requests 和 limits 字段的资源添加了默认值,但是并没有限制 requests 和limits 的最大值和最小值,这样同样会给集群带来风险,所以在管理资源分配时,对requests 和 limits的最大值和最小值也需要进行管控

requests 和 limits 的最大值和最小值的配置方式和默认值的配置差别不大,比如创建一个内存最小值为 500MB、最大值为 1GB 和 CPU 最小值为 280MB、最大值为 800MB 的 LimitRanger

(1)编写 limitRange 的 yaml 文件

vim limitrange02.yaml

a

备注:

内存最小值为 500M,最大为 1G
CPU 最小为 200m,最大为800m
limits:分配给 pod 的资源上限
requests:分配给 pod 的初始量

(2)创建 pod 并 查看

ku create -f limitrange02.yaml

ku get pod constraints-men-demo-2 -oyaml

在这里插入图片描述

(3)删除资源

ku delete -f limitrange02.yaml

在这里插入图片描述

(3)限制申请存储空间的大小

上述讲解的是对 CPU 和内存的限制,同样 LimitRanger 也可以对存储申请的大小进行限制,比如限制 PVC 申请空间的最小值为 1GB、最大值为 2GB(结合 ResourceQuota 可以同时限制最多存储使用量和最大 PVC 创建的数量)

(1)编写 limitRange 的 yaml 文件

vim limitrange03.yaml
vim hostpath-pv.yaml
vim pvc-hostpath.yaml

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

(2)创建 pod 并 查看

ku create -f limitrange03.yaml
ku create -f hostpath-pv.yaml
ku create -f pvc-hostpath.yaml

在这里插入图片描述

三. QoS

虽然我们进行了资源限制,但是实际使用时依旧会造成节点资源不足,针对资源不足 Kubernetes 会通过重启或驱逐 Pod 释放资源,再重启时,难免会造成一些很重要的服务不可用。但实际情况可能是,如果重启或驱逐一些不重要的 Pod 可能会更好,而这种决策是通过 Qos(Quality of Service,服务质量)决定的,所以在生产环境中,QoS 是一个非常重要的环节

1. 什么是服务质量保证

假设我们有一个 java 进程,需要的 CPU 最低为1核,内存最低为 26 才能正常启动,并且需要 10 个副本才能支撑业务量。此时我们需要创建一个 Deployment 并设置副本为10、requests.cpu为1和requests.memory 为2GB。创建资源时,Scheduler 会根据一系列算法将该 Pod 部署到合适的节点上,当然需要被调度节点最少有1核、2GB 的空间资源。看似一个再简单不过的部署,如果不设置 requests字段会如何呢?

如果未设置 requests 字段,那么 Scheduler 在调度时将不再检査 Node 节点上的资源是否满足该应用程序的最低需求,因为未配置 requests 字段,Scheduler 将随机部署至其他节点,包括已经没有资源的机器。如果部署到了一个没有资源的宿主机上,在该应用程序启动时可能就会引起容器一直无法启用,从而进入恶性循环。而且如果此时 10 个副本中有3个副本都部署到了一个没有多少资源的宿主机上,3个容器就会引起资源竞争,到最后一个也无法启动,并且在启动过程中程序会占用非常高的 CPU,可能会导致上面正在运行的 Pod 和宿主机不可用,此时很大程度上会引起雪崩,所以设置合理的requests 和limits 是非常重要的事情

我们设置了 requests 和 limits 就能万无一失吗?答案当然是不可能的。在使用 Kubernetes 部署时,应用的部署和更新都会经过一系列的调度策略将应用部署在最合适的节点上,但是随着时间的推移,当时“最优”的节点可能已经不再是最佳选择,因为在该服务器上别的应用或者其他管理员部署的应用可能忘记了配置资源限制,所以在日积月累的消耗中,宿主机一些不可压缩的资源(比如内存、磁盘)的使用率将达到最高峰。假如内存达到最高峰时会引起 00MKilled 故障(00MKi1led 即为内存杀手),此时Kubelet 会根据某些策略重启上面的容器用来避免宿主机宕机引来的风险,但是重启容器难免会带来服务中断的现象,如果重启的是比较重要的业务应用,这将是一个非常不好的体验。那么我们如何在系统资源不够的情况下尽量保证一些比较重要的 Pod 不被杀死呢?

前面讲了这么多主要是为了引出本节的主角:QoS;我们可以用 Qos 来提高某些应用的服务质量,以保证宿主机资源不够时尽可能保证某些应用不被杀死

Kubernetes为我们提供了3种级别的服务质量,分别是:

服务质量含义
Guaranteed最高服务质量,当宿主机内存不够时,会先杀死Qos为BestEffort 和 Burstable 的Pod,如果内存还是不够,才会杀死 Qos 为Guaranteed 的 Pod,该级别 Pod 的资源占用量一般比较明确,即 requests 字段的 cpu 和 memory 与 limits 字段的 cpu 和 memory 配置的一致
Burstable服务质量低于 Guaranteed,当宿主机内存不够时,会先杀死 Qos为 BestEffort 的 Pod如果内存还是不够,就会杀死 Qos 级别为 Burstable 的 Pod,用未保证 Qos 质量为 Guaranteed 的Pod,该级别的 Pod 一般知道最小资源使用量,但是当机器资源充足时,还是想尽可能使用更多的资源,即 limits 字段的 cpu 和 memory 大于 requests 字段的 cpu 和 memory 的配置
BestEffort尽力而为,当宿主机内存不够时,首先杀死的就是该 Qos 的 Pod,用以保证 Burstable和 Guaranteed 级别的 Pod 正常运行

实现不同级别的服务质量是根据requests 和 ljmits 的配置诀定的」在宿主机资源不够时会先杀死服务质呈为 BestEffort 的 Pod,然后杀死服务质量为Burstable 的Pod,最后杀死服务质量为Guaranteed 的 Pod。所以在生产环境中比较重要的应用最好设置为 Guaranteed,当然如果集群资源足够使用,可以都设置为 Guaranteed。接下来看一下如何实现这3种 QoS

2. 示例

首先创建一个用于测试的 Namespace

ku create namespace qos-example

在这里插入图片描述

(1)实现 Qos 为 Guaranteed 的 Pod

创建此类型的 Pod 需要满足的条件如下:

Pod 中的每个容器必须指定 limits.memory和requests.memory,并且两者需要相等
Pod 中的每个容器必须指定 limits.cpu 和 requests.cpu,并且两者需要相等

①:编写 yaml 文件

vim qos-pod.yaml

在这里插入图片描述

②:创建并查看 Pod

ku create -f qos-pod.yaml -n qos-example

ku get pod qos-demo -n qos-example -o yaml

在这里插入图片描述

(2)实现 Qos 为 Burstable 的 Pod

创建一个 Qos 为 Burstable 的 Pod 需要满足以下条件:

Pod 不符合 Guaranteed 的配置要求
Pod 中至少有一个容器配置了 requests.cpu 或者 requests.memory

①:编写 yaml 文件

vim qos-pod-2.yaml

在这里插入图片描述

②:创建并查看 Pod

ku create -f qos-pod-2.yaml -n qos-example

ku get pod qos-demo-2 -n qos-example -o yaml

在这里插入图片描述

(3)实现 Qos 为 BestEffort 的 Pod

创建一个 Qos 为 Burstable 的 Pod 更为简单,Pod 中的所有容器都没有设置 requests 和 limits
字段即可

①:编写 yaml 文件

vim qos-pod-3.yaml

在这里插入图片描述

②:创建并查看 Pod

ku create -f qos-pod-3.yaml -n qos-example

ku get pod qos-demo-3 -n qos-example -o yaml

在这里插入图片描述

总结:

提升服务可用性只从应用程序级别考虑是远远不够的,也需要考虑服务器的稳定性。在使用Kubernetes 部署程序时,很容易造成资源的过量分配,作为 Kubernetes 管理员,必须要去考虑服务器的可用性,防止服务器岩机带来的雪崩

通常情况下,依赖的底层中间件的 QoS 会配置为 Guaranteed,其他服务可能并不需要那么高的OoS。在实际使用时。最有可能超额分配的是内存,而CPU通常使用率不高,只有在高频工作时CPU 才会处于忙碌状态。所以在设置resources 参数时,内存的request 需要按需配置,比如一个程序的运行内存最少为 2GB,那么内存的 request 就要设置为 2GB,而不能低于 2GB。对于 CPU,Limit 参数很重要,防止 Pod 的 CPU 过高,从而引起宿主机的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值