Kubernetes 资源配额管理实战用 ResourceQuota 与 LimitRange 治理 Namespace 资源【免费下载链接】kubernetes-handbookKubernetes 架构与生态从云原生到 AI 原生基础设施的构建指南项目地址: https://gitcode.com/gh_mirrors/ku/kubernetes-handbook当多个团队或用户共用同一个 Kubernetes 集群时难免会发生资源竞争——一个团队的一次性大任务可能挤占其他团队的全部算力。本文基于本仓库kubernetes-handbook中 guide/resource-quota-management.md 的实践脉络结合仓库内真实的 API Server 配置与manifests/spark-with-kubernetes-native-scheduler目录下的配额清单系统讲解如何用ResourceQuota与LimitRange两类准入控制插件为 namespace 设置资源上限。读完本文你将掌握计算资源配额、对象数量配额与默认资源请求/限制的完整配置方法并理解这些配额在 Kubernetes API Server 内部是如何被强制执行的。为什么需要 namespace 资源配额Kubernetes 集群是一种共享基础设施。当多个团队、多个业务线甚至多个租户共用同一集群时如果没有配额约束任何一个团队都可以无限创建 Pod、申请存储卷、创建 Service最终导致集群资源被少数使用者耗尽其他团队的应用无法被调度。ResourceQuota就是为解决这一问题而生的它针对某一 namespace生效限制该 namespace 内所有 Pod 占用的资源 request 与 limit 总量也限制该 namespace 内可创建的对象数量。配合LimitRange可以进一步为 namespace 内未显式声明资源请求的 Pod 注入默认的 request/limit 值使配额约束更加完整、可预期。开启配额功能API Server 的准入控制配置资源配额不是一个独立服务而是 Kubernetes API Server 中的准入控制器Admission Controller。准入控制器位于 API Server 中在对象被持久化之前拦截对 API Server 的请求用来做身份验证、授权以及对象校验与变更详见 concepts/admission-controller.md。本仓库给出了真实的准入控制配置证据。在 etc/kubernetes/apiserver 中可以看到KUBE_ADMISSION_CONTROL--admission-controlServiceAccount,NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota也就是说只要在 API Server 启动参数中加入ResourceQuota集群便开启了资源配额限制功能加入LimitRange则可以对单个资源申请的范围以及默认值做限制。这份配置通过 systemd/kube-apiserver.service 中ExecStart/usr/bin/kube-apiserver $KUBE_ADMISSION_CONTROL ...的方式被加载到 kube-apiserver 进程中。关于这两个准入控制器的作用concepts/admission-controller.md 给出了官方语义LimitRanger确保所有资源请求不会超过 namespace 的LimitRangeResourceQuota观察传入请求并确保它不违反 namespace 的ResourceQuota对象中列举的任何约束。版本说明--admission-control参数在 Kubernetes 1.10 中已弃用替换为--enable-admission-plugins。对于 1.10 及以上版本建议使用--enable-admission-pluginsNamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota的组合1.10 之前的版本中准入控制器按指定顺序执行ResourceQuota在验证阶段运行。本仓库对应的 etc/kubernetes/apiserver 配置适用于 1.9 及更早版本的环境。两个控制器的分工可以这样理解控制器作用范围核心职责ResourceQuota某一 namespace限制 namespace 中所有 Pod 占用的总资源request 和 limit以及对象数量LimitRange某一 namespace设置 namespace 中 Pod 的默认资源 request 和 limit 值并限制单容器资源申请范围资源配额的三种类型按照配额对象的不同资源配额分为三种类型计算资源配额如requests.cpu、requests.memory、limits.cpu、limits.memory约束 namespace 内所有 Pod 对 CPU 与内存的请求/限制总量存储资源配额如requests.storage以及各类存储类StorageClass对应的 PVC 存储总量对象数量配额如pods、configmaps、secrets、services、persistentvolumeclaims等约束 namespace 内某类 Kubernetes 对象的数量上限。实战为 spark-cluster 配置计算资源配额本仓库以 Spark 应用场景为例——spark-clusternamespace 承载着 Spark 的 resource-staging-server见 manifests/spark-with-kubernetes-native-scheduler/kubernetes-resource-staging-server.yaml该 Deployment 自身声明了requests.cpu: 100m、requests.memory: 256Mi、limits.cpu: 1000m、limits.memory: 2560Mi。Spark 作业动辄需要大量 executor若不加限制很容易把集群资源吃光因此配额管控尤为必要。计算资源配额的清单文件为 manifests/spark-with-kubernetes-native-scheduler/spark-compute-resources.yamlapiVersion: v1 kind: ResourceQuota metadata: name: compute-resources namespace: spark-cluster spec: hard: pods: 20 requests.cpu: 20 requests.memory: 100Gi limits.cpu: 40 limits.memory: 200Gi这份配额的含义是在spark-clusternamespace 中——同时存在的 Pod 总数最多20个所有 Pod 的requests.cpu总和不超过20即 20 个 CPU 核心所有 Pod 的requests.memory总和不超过100Gi所有 Pod 的limits.cpu总和不超过40所有 Pod 的limits.memory总和不超过200Gi。其中requests.cpu的单位是 core允许浮点数例如0.1等价于100m100 毫核requests.memory以字节为单位支持E/P/T/G/M/K十进制后缀与Ei/Pi/Ti/Gi/Mi/Ki二进制后缀关于 CPU 与内存单位的详细约定可参考 practice/manage-compute-resources-container.md。创建配额后可用如下命令查看配额生效状态kubectl -n spark-cluster describe resourcequota compute-resources输出中会同时展示Resource配额项、Used当前已用量与Hard上限三列例如pods一行的Used会显示当前 namespace 内实际存在的 Pod 数。若 namespace 内的资源使用量已逼近上限新的 Pod 创建请求会被ResourceQuota准入控制器拒绝。实战配置对象数量限制除了计算资源配额同样可以约束对象的数量防止 namespace 内堆积过多 ConfigMap、Secret、Service 等对象。对象数量配额的清单文件为 manifests/spark-with-kubernetes-native-scheduler/spark-object-counts.yamlapiVersion: v1 kind: ResourceQuota metadata: name: object-counts namespace: spark-cluster spec: hard: configmaps: 10 persistentvolumeclaims: 4 replicationcontrollers: 20 secrets: 10 services: 10 services.loadbalancers: 2这份配额的含义是在spark-clusternamespace 中ConfigMap 最多10个、PVC 最多4个、ReplicationController 最多20个、Secret 最多10个、Service 最多10个其中 LoadBalancer 类型的 Service 最多2个。对象数量配额是典型的多租户治理手段例如限制services.loadbalancers可以避免云厂商的负载均衡资源被无限创建而产生费用限制persistentvolumeclaims可以控制持久化存储的占用规模。ResourceQuota与LimitRange可以同时存在于同一 namespace 中互不冲突——本仓库的 spark 示例正是同时创建了compute-resources与object-counts两个配额对象。实战配置 CPU 和内存 LimitRangeLimitRange解决的是默认值问题当用户创建 Pod 时没有为容器显式声明resources.requests和resources.limitsLimitRanger准入控制器会按照 namespace 中定义的默认值自动注入从而保证配额约束总能生效——否则用户完全可以通过不声明 request/limit 来绕过ResourceQuota的总量限制。LimitRange 清单文件为 manifests/spark-with-kubernetes-native-scheduler/spark-limit-range.yamlapiVersion: v1 kind: LimitRange metadata: name: mem-limit-range spec: limits: - default: memory: 50Gi cpu: 5 defaultRequest: memory: 1Gi cpu: 1 type: Container其中两个关键字段的含义default即容器默认的limit值资源上限defaultRequest即容器默认的request值资源申请量。也就是说spark-clusternamespace 中任何未显式声明资源的容器都会被自动注入limits.memory: 50Gi、limits.cpu: 5、requests.memory: 1Gi、requests.cpu: 1的默认值。type: Container表明该条 limit 规则作用在容器层级Pod 的资源 request/limit 是其所有容器对应值之和详见 practice/manage-compute-resources-container.md。LimitRange 与 ResourceQuota 的配合关系ResourceQuota管的是 namespace 内所有 Pod 的总和是否越界LimitRange管的是单个容器的资源申请是否落在允许范围内并为未声明资源的容器填充默认值当两者同时开启时LimitRanger先为 Pod 注入默认的 request/limitResourceQuota再校验注入后的总量是否突破配额上限——这也是推荐同时开启二者的原因。配额生效的底层机制与验证从源码与配置层面看配额强制执行的链路是用户在 namespace 内创建ResourceQuota/LimitRange对象如上述三个 yaml 清单用户创建 Pod、Service 等资源时请求进入 API ServerAPI Server 依次执行已启用的准入控制器本仓库环境为ServiceAccount, NamespaceLifecycle, NamespaceExists, LimitRanger, ResourceQuota见 etc/kubernetes/apiserverLimitRanger校验并注入默认资源值ResourceQuota校验当前 namespace 的资源与对象用量一旦违反hard中任一项即拒绝请求拒绝时 API Server 返回forbidden错误kubectl create等客户端操作会直接报错。配额被拒绝时的典型排查方式# 查看 namespace 当前配额与用量 kubectl -n spark-cluster get resourcequota # 查看配额详情含 Used / Hard 对比 kubectl -n spark-cluster describe resourcequota compute-resources kubectl -n spark-cluster describe resourcequota object-counts # 查看被拒绝的 Pod 事件 kubectl -n spark-cluster describe pod pod-name当事件中出现failed quota/exceeded quota之类的信息时说明 Pod 创建请求被ResourceQuota拦截需要检查describe resourcequota输出中Used与Hard的差值及时清理不再使用的 Pod、Service 或 PVC。这与节点调度失败FailedScheduling: insufficient cpu是两类不同的问题配额限制发生在 API Server 的准入阶段而节点容量不足发生在调度阶段参见 practice/manage-compute-resources-container.md 的疑难解答部分。多租户场景下的配额治理建议结合本仓库的实践在多团队共享集群时推荐遵循以下策略每个团队独占 namespace以团队或业务线为单位划分 namespace配额天然按 namespace 隔离互不影响计算配额 对象配额同时下发参考本文两个ResourceQuota清单既约束 CPU/内存总量也约束 ConfigMap、Secret、Service、PVC 等对象的数量上限用 LimitRange 兜底默认值为 namespace 配置默认 request/limit避免用户因未声明资源而绕过配额、也避免个别容器申请超规格的资源导致 namespace 总量被快速耗尽配额值与业务容量匹配配额上限应结合业务真实需求设定例如 spark-cluster 的配额上限pods 20、requests.memory 100Gi需要覆盖 driver、executor 与 resource-staging-server 的总需求过紧会导致作业无法提交过松则失去治理意义结合 RBAC 控制配额管理权限只有具备相应权限的管理员才能创建/修改ResourceQuota防止普通用户自行调高配额或删除配额对象RBAC 与 namespace 级权限的说明可参考 practice/rbac-support-in-kubernetes.md。参考本主题原始文档管理 namespace 中的资源配额配额清单spark-compute-resources.yaml配额清单spark-object-counts.yaml配额清单spark-limit-range.yaml准入控制器详解API Server 配置含 KUBE_ADMISSION_CONTROLkube-apiserver systemd 服务单元管理容器的计算资源CPU/内存单位与调度、驱逐机制Kubernetes 中的 RBAC 支持【免费下载链接】kubernetes-handbookKubernetes 架构与生态从云原生到 AI 原生基础设施的构建指南项目地址: https://gitcode.com/gh_mirrors/ku/kubernetes-handbook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考