K8s-kubernetes(二)资源限制-详细介绍

发布于:2025-08-15 ⋅ 阅读:(20) ⋅ 点赞:(0)

在这里插入图片描述

K8s如何合理规定对象资源使用

基本概念

  • Kubernetes中,占用资源最小单元单个Pod
  • Kubernetes中,资源占用主要针对服务器CPU内存

为什么要做资源限制

  • 对于Kubernetes集群而言,所有Pod都会占用K8s集群所在服务器的资源,如果不做资源控制,则很有可能出现某些Pod无限制占用资源(CPU、内存),导致系统崩溃

资源限制设置方式

Pod、Container级别控制

关键参数:request、limits
  • request参数

    • controller做调度时,创建Pod最低资源占用标准
  • limits参数

    • 单个Pod运行时的资源占用上限真正限制资源可用到多少
    • 当容器试图使用超过limits指定的CPU时会被 CFS 限流;试图使用超过limits指定的内存时会被 OOM Killer 杀掉并重启
使用示例
	apiVersion: v1
	kind: Pod
	metadata:
	  name: demo-pod
	spec:
	  containers:
	  - name: app
	    image: nginx:latest
	    resources: # k8s中定义资源规格的关键字,主要针对CPU和内存
	      requests: # Pod最低的资源占用。调度器在将Pod指派给某个节点时,会检查该节点“可分配资源”是否满足request要求
	        cpu: "100m"        # 0.1 核
	        memory: "128Mi"    # 128 MB
	      limits: # Pod运行时的最大资源使用上限,
	        cpu: "500m"        # 0.5 核(上限)
	        memory: "256Mi"    # 256 MB(上限)

命名空间级别控制

关键策略对象:LimitRange
  • 在命名空间级别,可以使用LimitRange给整个命名空间设置默认值/最大值
  • LimitRange不仅仅是默认值的概念,也是一道硬性检查
    • 默认值:如果 Pod 或容器未显式声明 requests 或 limits,LimitRange 会自动注入默认值
    • 硬性检查:如果Pod或容器显式声明了request或者limits,但是不在 LimitRange的允许范围内不允许创建Pod
使用示例
apiVersion: v1
kind: LimitRange  #LimitRange类型对象
metadata:
  name: cpu-mem-limit #LimitRange对象名称
  namespace: dev #该策略适用的命名空间
spec: #定义策略具体规则
  limits: #limits为一个列表,可以包含多个限制策略
  - type: Container #表示该限制针对的是容器级别,而不是Pod或其他级别
    min: #指定容器资源的最小值,如果容器请求的资源低于这个值,K8s 会拒绝创建
      cpu: 100m #最少请求 0.1 个 CPU 核心
      memory: 128Mi #最少请求128M内存
    max: #超过这个值的容器会被拒绝创建
      cpu: 1 #最大请求1个CPU核心
      memory: 1Gi #最大请求1G内存
    default: #默认配置,当容器和Pod没有显式声明resources.limits,自动使用这里配置的默认值
      cpu: 500m #当容器和Pod没有显式声明resources.limits,默认resources.limits.cpu=500m
      memory: 512Mi #当容器和Pod没有显式声明resources.limits,默认resources.limits.memory=512Mi 
    defaultRequest: #默认配置,当容器和Pod没有显式声明resources.request,默认的requests数量,request: Pod最低的资源占用。调度器在将Pod指派给某个节点时,会检查该节点“可分配资源”是否满足request要求
      cpu: 200m
      memory: 256Mi
    maxLimitRequestRatio: #限制比例:限制与请求的最大比例,控制 limit/request 的最大比例。作用:防止用户设置过高的 limit 而请求很低的资源,防止节点资源被过度使用或者其他Pod的资源无法保证
      cpu: 2 # CPU的限制值不能超过请求值的2倍。如果请求是250M内存,则限制不能超过500M。如果超过这个比例,Pod 会被拒绝创建

命名空间/集群级别总量限制

关键对象:ResourceQuota
  • ResourceQuota是一种命名空间级别硬限制机制,作用是给每个命名空间设定资源总量红线
  • 一旦配额用满,任何导致超配的对象创建都会被拒绝,包括通过Deployment、StatefulSet等控制器间接创建的Pod
ResourceQuota作用范围
  • ResourceQuota控制的是集群节点级别的总量,还是命名空间的总量?
    • ResourceQuota控制的是单个命名空间资源的总量
    • 如果希望控制集群节点级别,需要多命名空间+ResourceQuota集群级策略(如 ClusterPolicy、PodNodeSelector、多集群联邦)来实现
ResourceQuota和LimitRange有什么区别
  • ResourceQuota限制的是整个命名空间资源的总量
  • LimitRange限制的是这个命名空间内,单个资源限制量默认值
  • 两者需要结合使用才能达到最佳效果
使用示例
  1. 确保准入控制器已启用
    • 大多数发行版默认已包含 --enable-admission-plugins=ResourceQuota;若手动搭建,需在 kube-apiserver 启动参数里加入
  2. 编写YML并应用
apiVersion: v1
kind: ResourceQuota #类型为ResourceQuota
metadata:
  name: team-a-quota #名称
  namespace: team-a #作用的命名空间
spec:
  hard: #hard 是一个 map,key 是被限制的资源类型,value 是字符串形式的硬性上限
    requests.cpu: "20" #该命名空间内所有 非终止状态 Pod 的 spec.containers[*].resources.requests.cpu 之和 ≤ 20 CPU(= 20 核)
    requests.memory: 40Gi #所有 Pod 的 requests.memory 总和 ≤ 40 GiB
    limits.cpu: "40" #所有 Pod 的 limits.cpu 总和 ≤ 40 核
    limits.memory: 80Gi #所有 Pod 的 limits.memory 总和 ≤ 80 GiB
    pods: "50" #命名空间里当前存在的 Pod 对象数量 ≤ 50 个(Running / Pending / Succeeded 都算,Failed 或 Completed 且 TTL 已过的不算)
    persistentvolumeclaims: "10" #PVC 对象总数 ≤ 10 个
    count/deployments.apps: "15" #apps/v1 组下的 Deployment 对象 ≤ 15 个
  1. 查看配额使用/剩余
kubectl describe quota <ResourceQuota名称> -n <命名空间>

引申问题1:LimitRange限制了容器最大使用资源,如果使用中超过这个限制,会发生什么

  • 结论
    • 最终表现是容器会被OOMKilled
  • 原因
    • LimitRange属于准入控制,即在Pod创建/更新时作限制校验,如果超出或低于限制要求,则不允许创建
    • Pod创建完后LimitRange任务结束,不再发挥作用
    • 实际的运行时限制,是由cgroup 和 kubelet 负责,限制的方式也不是拒绝分配,而是直接杀掉

引申问题2:如果容器资源一旦超限就OOMKilled,如何保证应用稳定性?

  1. 预估
    • 在配置上线前,充分压测评估出最大峰值
    • 给足安全余量,一般要在压测峰值上再加20%-50%作为安全余量
  2. 观察
    • 上线后持续观察,并设置预警措施
  3. 调优
    • 发现不足就及时调大,并滚动升级
    • 垂直扩容(加大limit限制值)
    • 水平扩容(拆业务、分片、增加副本数,降低单实例负载)
    • 应用层优化(减少缓存大小、调整GC参数、使用内存池、对象复用)**
  4. 兜底
    • 保证即使有实例被OOMKilled,其余实例还可以承载流量

引申问题3:LimitRange 和 ResourceQuota 对已有 Pod 有什么影响

这是一个非常重要的问题,涉及 Kubernetes 中资源限制策略的生效范围和时效性

✅ 1. LimitRange 对已有 Pod 的影响
  • 不会影响已存在的 Pod
  • LimitRange 只在 新创建的 Pod 或容器 时生效。
  • 它的作用是在 Pod 创建时:
    • 自动补全 resources.requestsresources.limits
    • 验证资源是否在允许范围内。

🔍 如果已有 Pod 的资源配置超过了 LimitRange 的 max 限制

  • 不会强制修改或终止这些 Pod。
  • 它们会继续运行,直到被手动删除或更新。
  • 只有在重新创建或更新 Pod 时,才会触发 LimitRange 的验证。

✅ 2. ResourceQuota 对已有 Pod 的影响
  • 不会强制终止或修改已存在的 Pod
  • ResourceQuota 是针对命名空间资源总量的限制。
  • 它在创建新资源时检查是否超过配额。

🔍 如果已有资源已经超过了配额限制

  • 不会影响这些资源的运行。
  • 无法再创建新的资源,直到资源使用量低于配额。

🧠 举个例子

假设你在 dev 命名空间中设置了如下配额:

limits.cpu: "4"

而已有 Pod 总共使用了 5 个 CPU:

  • ✅ 已有 Pod 不会被删除或停止。
  • ❌ 新 Pod 无法创建,除非已有 Pod 被删除或资源使用量降低。

📌 总结
特性 LimitRange ResourceQuota
是否影响已有 Pod ❌ 不影响 ❌ 不影响
是否影响新建 Pod ✅ 生效 ✅ 生效
是否强制修改已有资源 ❌ 不会 ❌ 不会
是否阻止新资源创建 ✅(不符合规则) ✅(超出配额)

✅ 建议做法
  • 在设置 LimitRangeResourceQuota 前,先评估当前命名空间资源使用情况。
  • 使用 kubectl describe quotakubectl top pod 查看资源使用。
  • 如果想让“老 Pod”也受新限制,只能人工或自动化地做:手动滚动重启 Deployment/StatefulSet → 新 Pod 走新规则。
  • 配合策略引擎(如 Kyverno)实现更强的资源治理。

注意事项

  1. LimitRange 和 ResourceQuota设置前,已有存在的pod,这部分Pod不会不受影响
  2. 一个命名空间建议只创建一个
  3. 多租户集群,防止某个用户的 Pod 占用过多资源
  4. CICD环境,限制测试 Pod 的最大资源,防止资源争抢
  5. 为未声明资源的容器自动分配合理默认值,避免调度失败

网站公告

今日签到

点亮在社区的每一天
去签到