
一、Kubernetes资源管理
1. 节点总硬件资源
capacity表示节点整机物理硬件的原始资源上限,是机器自身具备的全部硬件规格,没有做任何资源预留扣除。包含CPU、内存、临时存储、大页内存、最多Pod数量等硬件指标,反映服务器硬件出厂配置。
kubelet、操作系统、容器运行时等底层组件本身也要占用这部分硬件,Pod不能直接使用全部capacity资源。
capacity数据由节点上的kubelet组件负责采集并上报,kubelet启动时会同步内置cadvisor子模块。由其采集本机CPU、内存等硬件资源信息,kubelet再将采集到的整机硬件容量数据同步上报至apiserver。
[Step1] 执行命令查看指定节点完整资源描述信息,重点查看“capacity”部分。
root@k8s-master:~# kubectl get nodes k8s-worker1 -o yaml
2. 节点可调度资源
Kubernetes集群内各计算节点均具备CPU、内存等硬件资源,可通过清单文件查看节点资源的详情。
allocatable是从capacity总硬件中,扣除系统预留资源后,真正能够分配给业务Pod使用的资源额度。kubelet会预先预留一部分CPU、内存、临时存储供给节点系统组件,防止业务Pod抢占资源导致节点宕机。Kubernetes调度器调度Pod、计算资源配额时,全部以allocatable数值作为判断依据,而非capacity资源。
capacity表示机器硬件原始总资源,allocatable表示扣除kubelet、系统组件预留资源后,能够分配给业务Pod的资源。调度器调度Pod时以allocatable数值为准。
[Step1] 执行命令查看指定节点完整资源描述信息,重点查看“allocatable”部分。
root@k8s-master:~# kubectl get nodes k8s-worker1 -o yaml
3. 组件类型
Kubernetes集群各节点除业务容器外,还运行大量关键后台程序,这类程序并非容器化部署,主要分为两类:
kubernetes daemon:Kubernetes守护进程,集群相关的后台服务,如kubelet、dockerd等。
system daemon:系统守护进程,独立于k8s的系统服务,如sshd等。
为保障两类程序稳定运行,避免业务容器抢占资源造成节点故障,Kubernetes提供驱逐策略(eviction policy)机制。
4. 资源回收
节点资源不足时,kubelet会依据驱逐策略执行Pod回收操作。当集群不可压缩资源达到短缺阈值,便会触发驱逐行为,常见不可压缩资源包含:可用内存(memory.available)、可用宿主机磁盘(nodefs.available)、容器运行镜像存储空间(imagefs.available)等。
[Step1] 在Kubernetes中,设置的eviction默认阈值如下。
memory.available<100Mi
nodefs.available<10%
nodefs.inodesFree<5%
imagefs.available<15%5. 资源驱逐机制
Kubernetes的节点资源驱逐Eviction包含Soft软驱逐和Hard硬驱逐两类机制:
软驱逐(Soft Eviction):支持为资源阈值设置宽期限,用于规避瞬时资源峰值造成的误驱逐。当资源占用达到阈值后,kubelet会持续观测资源状态。若宽限期结束后资源压力仍未缓解,则启动Pod驱逐,同时允许Pod执行优雅退出逻辑。
硬驱逐(Hard Eviction):不存在宽限期,属于兜底保护机制。资源指标一旦达到阈值,kubelet会马上强制销毁Pod,快速释放紧缺资源,避免节点因资源耗尽宕机。
当宿主机资源占用达到驱逐阈值时,节点会标记为“MemoryPressure”(内存压力)或“DiskPressure”(磁盘压力)状态。同时自动加上对应动态污点,阻止新Pod调度至该节点。触发驱逐时,kubelet会依据Pod的QoS服务质量等级确定删除顺序:
优先驱逐BestEffort Pod(尽力服务级);
其次驱逐Burstable(弹性服务级)中紧缺资源实际使用量超出requests申请额度的Pod;
最后才会驱逐Guaranteed Pod(保障服务级),该类Pod仅在资源使用超出limits限制时,才会被纳入驱逐候选。
同一QoS等级下,集群会按照Pod优先级判定驱逐先后,低优先级的Pod优先被回收。
二、Kubernetes调度
1. Kubernetes调度器
客户端提交Pod创建请求至API Server后,请求会交由调度组件kube-scheduler处理,由其筛选出集群内最优可用节点用于部署运行Pod。整个Pod调度流程分为3个核心阶段:
节点预选(Predicates):依据预设筛选规则逐一校验集群所有节点,剔除资源、标签、亲和性等条件不匹配的节点,完成候选节点过滤。在具体的调度流程中,默认调度器首先会调用一组“Predicate”的算法,来检查各个Node。
节点优选(Priorities):对预选后留存的合格节点进行综合优先级打分排序,量化判定各节点运行当前 Pod 的适配程度。调用一组“Priority”的调度算法,来给节点预选中的每个Node打分,最终得分最高的Node就是调度结果。当调度器对一个Pod调度成功,会在它的“spec.nodeName”字段填上调度结果的名字。
节点选定(Select):选取优先级得分最高的节点作为Pod部署目标,若存在多个相同优先级最优节点,系统将随机从中on选定一个节点承载Pod。
2. Predicates常用策略
预选策略(Predicates)本质是节点过滤器。典型规则包含:节点标签需要与Pod的节点选择器匹配(由PodMatchNodeSelector规则实现)。Pod容器声明的资源请求量不得超过节点剩余可分配资源(PodFitsResources规则)。调度器将依次执行所有预选规则筛选节点,若预选后无符合条件的节点,Pod将持续处于Pending状态,直至出现满足条件的节点完成调度。
3. 打分阶段
调度器通过预选策略筛选出合格节点列表后,进入优选阶段(Priorities)。调度器会调用一系列优选函数,对每一个通过预选的节点进行评估,计算对应的优先级分数,分值区间为0~10。分数为0代表不适宜运行该Pod,分数为10代表该节点最适合承载当前Pod。
调度器支持为每一个优选函数配置权重,在计算节点最终优先级分值时,先将单个优选函数得出的分数乘以对应权重,再把所有优选函数的加权结果求和,得到节点综合得分。借助权重配置,管理员能够自主调整各类优选规则的影响程度,改变调度器的偏向性。
三、资源配额
1. 单个Pod限额
Pod支持设置CPU、Memory两种资源限额。
1.1 CPU资源计量规则
单位m代表毫核,1颗逻辑CPU核心等价于1000m。
数值无单位时直接表示CPU核心数
支持小数写法,如0.1代表0.1核
1.2 内存资源计量规则
十进制标识M:换算基数为1000,例如100M=100x1000KB
二进制标识Mi:换算基数为1024,例如100Mi=100x1024Ki
数值无单位时,默认表示为字节
1.3 Kubernetes常见资源配额字段
2. 命名空间资源总量配额
通过为单个Pod配置“requests”和“limits”资源限制,能够有效规避因单容器程序逻辑Bug或瞬时流量峰值引发的资源激增问题,避免单个Pod耗尽节点硬件资源。但是单个Pod资源限制存在明显短板,该管控手段仅约束单个容器实例,若通过Deployment控制器调整副本数,批量创建大量Pod,多个Pod叠加占用的CPU与内存总和仍会耗尽整个节点乃至集群资源,无法实现全局资源管控。
为了解决多个Pod批量抢占资源的管控盲区,Kubernetes提供了“ResourceQuota”命名空间资源总量配额机制。该资源对象作用于独立命名空间,可统一统计并限制当前命名空间内所有非终止状态Pod的总资源使用量,从命名空间维度约束CPU、内存、巨页、Pod总数等各类资源的整体上限,实现租户/业务维度的资源隔离与总量管控。
ResourceQuota spec.hard常用可选字段如下表所示:
3. 资源限制区间
3.1 LimitRange核心定义
LimitRange作用于单个命名空间的资源管控对象,面向单个容器与Pod做粒度管控,能够统一约束命名空间内容器CPU、内存等资源的最小申请值、最大使用上限。同时限制资源上限与资源申请的比值,规范单个Pod资源的配置标准。弥补ResourceQuota仅能管控命名空间资源总用量,无法约束单实例资源大小的短板。从单容器维度避免出现资源配置过大过小甚至缺失资源配额的问题。
当同一命名空间下存在多条LimitRange规则且均匹配待创建Pod时,Kubernetes会按照管控类型(Container、Pod、PersistentVolumeClaim)分类校验,依次核对对应类型的资源约束条件,全部校验通过后Pod才可以正常创建。
3.2 LimitRange解决痛点
ResourceQuota仅限制命名空间资源总容量,无法约束单个容器资源大小;
开发人员创建Pod时可能不写requests/limits,或是内存、CPU配置过大/过小,引发节点资源失衡;
LimitRange可强制规范单容器资源区间,缺失配置时自动填充默认值。
3.3 LimitRange核心能力
限制资源最小/最大值,规定单个容器CPU、内存的requests、limits取值范围:
min:容器资源申请不能低于该值
max:容器资源上限不能高于该值,如果Pod配置超出区间,创建直接报错拒绝。
设置默认资源配置,若创建Pod时间未填写requests/limits,LimitRange会自动给容器注入默认的requests、limits,确保所有Pod都具备资源配额,避免无限制抢占资源。
约束requests与limits比例,配置“maxLimitRequestRatio”限制requests和limits的比值,防止内存/CPU弹性区间过大。例如:内存比例为3,代表limits.memory÷requests.memory≤3。
3.4 管控资源对象类型
limits.type是LimitRange中用于指定当前资源限制规则要管控的资源对象类型,用于区分规则是约束容器、Pod整体还是PVC。
3.5 LimitRange与ResourceQuota核心区别
四、资源配额案例配置
1. 单个Pod限额案例
[Step1] 本地新建YAML清单,定义Pod资源描述模板。
root@k8s-master:~# vim busybox-resources.yml
# 写入下列内容
apiVersion: v1 # 固定配置
kind: Pod # 资源类型
metadata:
name: busybox-resources
spec:
containers:
- name: busybox-resources
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sleep","10000"]
# 配置容器资源限额,包含requests和limits两类子项
resources:
requests: # 资源申请配额,集群调度器分配节点资源的判断依据
memory: "64Mi" # 申请内存64Mi,调度器会预留64Mi内存供容器使用
cpu: "100m" # 申请CPU 100毫核(0.1核),调度时预留0.1核CPU资源
limits: # 资源使用硬上限,限制容器最大可用硬件资源,防止容器耗尽节点资源
memory: "128Mi" # 内存最大使用上限128Mi,容器内存占用超过该值会触发OOM被直接终止
cpu: "100m" # CPU最大使用上限100毫核,容器CPU占用超出上限会被系统节流降频,不会杀死容器[Step2] 根据YAML清单向Kubernetes集群声明式地创建Pod资源。
root@k8s-master:~# kubectl create -f busybox-resources.yml[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的运行状态与基础信息。
root@k8s-master:~# kubectl get -f busybox-resources.yml
[Step4] 验证:查看busybox-resources的详细信息,可以看到Limits和Requests字段。
root@k8s-master:~# kubectl describe pod busybox-resources
2. 命名空间资源总量配置
[Step1] 创建一个namespace,名称为quota。
root@k8s-master:~# kubectl create namespace quota[Step2] 本地新建YAML清单,定义ResourceQuota资源描述模板。
root@k8s-master:~# vim resource-quota.yml
# 写入下列内容
apiVersion: v1 # 固定配置
kind: ResourceQuota # 资源类型
metadata:
name: resource-quota
namespace: quota
spec:
hard: # 硬件总量上限,达到该数值后,拒绝创建新资源
pods: "1" # 命名空间下最多允许1个非终止状态Pod运行
requests.cpu: "1" # 命名空间内所有Pod的CPU总申请上限为1核
limits.cpu: "2" # 命名空间内所有Pod的CPU总限额上限为2核
limits.memory: "2Gi" # 命名空间所有Pod的内存总限额上限为2Gi[Step3] 根据YAML清单向Kubernetes集群声明式地创建ResourceQuota资源。
root@k8s-master:~# kubectl create -f resource-quota.yml[Step4] 验证:查看quota命名空间下所有ResourceQuota资源配额使用情况。
root@k8s-master:~# kubectl get resourcequotas -n quota
[Step5] 本地新建YAML清单,定义Pod资源描述模板。
root@k8s-master:~# vim quota-pod.yml
# 写入下列内容
apiVersion: v1 # 固定配置
kind: Pod # 资源类型
metadata:
name: quota-pod
namespace: quota
spec:
containers:
- name: quota-busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sleep","10000"]
# 配置容器资源限额,包含requests和limits两类子项
resources:
requests: # 资源申请配额,集群调度器分配节点资源的判断依据
memory: "64Mi" # 申请内存64Mi,调度器会预留64Mi内存供容器使用
cpu: "10" # 申请CPU 10核
limits: # 资源使用硬上限,限制容器最大可用硬件资源,防止容器耗尽节点资源
memory: "128Mi" # 内存最大使用上限128Mi,容器内存占用超过该值会触发OOM被直接终止
cpu: "10" # CPU最大使用上限10核,容器CPU占用超出上限会被系统节流降频,不会杀死容器[Step6] 根据YAML清单向Kubernetes集群声明式地创建Pod资源,此时可以看到报错信息,原因是超出命名空间ResourceQuota配额限制。
root@k8s-master:~# kubectl create -f quota-pod.yml
[Step7] 修改YAML文件,将“requests.cpu”和“limits.cpu”核心数调整为1。
root@k8s-master:~# vim quota-pod.yml
# 修改后文件内容如下
apiVersion: v1
kind: Pod
metadata:
name: quota-pod
namespace: quota
spec:
containers:
- name: quota-busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sleep","10000"]
resources:
requests:
memory: "64Mi"
cpu: "1"
limits:
memory: "128Mi"
cpu: "1"[Step8] 根据YAML清单向Kubernetes集群声明式地创建Pod资源,此时能够正常创建。
root@k8s-master:~# kubectl create -f quota-pod.yml[Step9] 验证:基于文件内定义的资源清单,查询集群中该资源的运行状态与基础信息。
root@k8s-master:~# kubectl get -f quota-pod.yml
[Step10] 验证:查看quota命名空间下所有ResourceQuota资源配额使用情况,可以看到上述创建Pod所占用的资源。
root@k8s-master:~# kubectl get resourcequotas -n quota
3. 资源限制区间配置
[Step1] 创建一个namespace,名称为limit。
root@k8s-master:~# kubectl create namespace limit[Step2] 本地新建YAML清单,定义LimitRange资源描述模板。
root@k8s-master:~# vim limit-range.yml
# 写入下列内容
apiVersion: v1 # 固定配置
kind: LimitRange # 资源类型
metadata:
name: limit-range
namespace: limit
spec:
limits: # 定义资源范围约束规则列表
- type: Container # 约束对象类型:Container容器级约束
max: # 单个容器允许设置的资源上限最大值
cpu: "2" # 单个容器CPU最高只能设置2核
memory: "1Gi" # 单个容器内存最高只能设置1Gi
min: # 单个容器允许设置的资源上限最小值
cpu: "200m" # 单个容器CPU最低必须200毫核
memory: "6Mi" # 单个容器内存最低必须6Mi
default: # 容器未手动定义limits时,自动填充的资源上限默认值
cpu: "500m"
memory: "128Mi"
defaultRequest: # 容器未手动定义requests时,自动填充的资源申请默认值
cpu: "200m"
memory: "64Mi"[Step3] 根据YAML清单向Kubernetes集群声明式地创建LimitRange资源。
root@k8s-master:~# kubectl create -f limit-range.yml[Step4] 验证:查看命名空间limit下的名为limit-range的LimitRange资源详细配置,可以看到资源上下限以及默认资源规则。
root@k8s-master:~# kubectl describe limitranges -n limit limit-range
[Step5] 本地新建YAML清单,定义Pod资源描述模板。
root@k8s-master:~# vim limit-range-pod.yml
# 写入下列内容
apiVerions: v1 # 固定配置
kind: Pod # 资源类型
metadata:
name: limit-range-pod
namespace: limit
spec:
- name: limit-range-pod
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sleep","1000"][Step6] 根据YAML清单向Kubernetes集群声明式地创建Pod资源。
root@k8s-master:~# kubectl create -f limit-range-pod.yml[Step7] 验证:查看YAML文件中Pod资源的详细信息,筛选出包含Limit的行及其后续5行内容。因为在创建Pod时未手动定义request和limits,命名空间内的LimitRange规则会自动为容器填充预设的默认资源参数。
root@k8s-master:~# kubectl describe -f limit-range-pod.yml | grep Limits -A 5