ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

OpenShift ClusterResourceQuota 共享配额设计解析:跨项目资源总量管控的实现与准入机制

OpenShift ClusterResourceQuota 共享配额设计解析:跨项目资源总量管控的实现与准入机制 测试云原生质量保障【免费下载链接】originConformance test suite for OpenShift项目地址https://gitcode.com/gh_mirrors/or/origin点击查看免费下载导读ClusterResourceQuota集群级资源配额是 OpenShift 为按实体如用户限制资源总量、而不关心其内部如何细分这一管理需求设计的核心机制。本文基于仓库中的设计提案 docs/proposals/shared-quota.md系统讲解该对象的类型模型、准入强制、加锁策略与权限模型并结合仓库中的 e2e 测试与 CLI 测试还原其真实落地形态。读完本文你将掌握 ClusterResourceQuota 的完整工作原理、与普通 ResourceQuota 的差异、跨命名空间配额执行的性能权衡以及如何通过标签选择器为项目组分配总量配额并验证配额生效。一、问题背景为什么普通 ResourceQuota 不够用集群管理员cluster-admin经常面临这样一个诉求限制某个实体从用户开始在集群中创建资源的总数而不关心该用户如何在内部细分这些配额。Kubernetes 原生提供的ResourceQuota是命名空间namespace级别的——一个ResourceQuota只能约束单个命名空间内的资源。当用户可以在多个项目project即命名空间中工作、或者一个用户的资源分散在多个项目中时管理员无法用一个配额对象统一管控该用户的资源总量。OpenShift 中实体之间的关联机制是标签选择器label selection因此设计提案给出的思路非常直接创建一个位于集群作用域的ClusterResourceQuota对象它镜像集群作用域下的ResourceQuota。具体做法是通过结构化的标签把项目关联到其所有者例如给项目打上owner用户名的标签然后用标签选择器选中这些项目将配额一次性分配给某个用户拥有的全部项目。这样管理员只需维护少量集群级配额对象即可对用户横跨多个项目的资源创建总量进行统一管控。二、核心对象模型ClusterResourceQuota 类型设计提案中给出了完整的 Go 类型定义这也是quota.openshift.io/v1API 组中ClusterResourceQuota对象的模型基础// ClusterResourceQuota mirrors ResourceQuota at a cluster scope. This object is easily convertible to // synthetic ResourceQuota object to allow quota evaluation re-use. type ClusterResourceQuota struct { unversioned.TypeMeta kapi.ObjectMeta // Spec defines the desired quota Spec ClusterResourceQuotaSpec // Status defines the actual enforced quota and its current usage Status ClusterResourceQuotaStatus } type ClusterResourceQuotaSpec struct { // Selector is the label selector used to match projects. It is not allowed to be empty // and should only select active projects on the scale of dozens (though it can select // many more less active projects). These projects will contend on object creation through // this resource. Selector map[string]string // Spec defines the desired quota Quota kapi.ResourceQuotaSpec } type ClusterResourceQuotaStatus struct { // Overall defines the actual enforced quota and its current usage across all namespaces Overall kapi.ResourceQuotaStatus // ByNamespace slices the usage by namespace. This division allows for quick resolution of // deletion reconciliation inside of a single namespace without requiring a recalculation // across all namespaces. This map can be used to pull the deltas for a given namespace. ByNamespace map[string]kapi.ResourceQuotaStatus }设计要点拆解字段类型说明Spec.Selectormap[string]string用于匹配项目的标签选择器不允许为空。设计建议它最好只选中数十个量级的活跃项目也可选中更多低活跃项目被选中的项目将在这一个资源上共同争用配额额度。Spec.Quotakapi.ResourceQuotaSpec复用 Kubernetes 原生ResourceQuotaSpec即硬上限hard定义本身与原生配额完全一致这是实现可复用的配额评估的关键。Status.Overallkapi.ResourceQuotaStatus跨所有命名空间的整体实际执行配额与当前用量。Status.ByNamespacemap[string]kapi.ResourceQuotaStatus按命名空间切分的用量明细。这种划分让单个命名空间内的删除对账deletion reconciliation可以快速完成无需重新跨所有命名空间全量计算只需从这张映射中取出对应命名空间的差值即可。提案明确指出该对象可以轻松转换为合成的 ResourceQuota 对象从而复用配额评估逻辑——这是整个设计能够以较低成本落地的基石。仓库中的真实 YAML 形态提案中的类型最终在quota.openshift.io/v1API 组中落地。仓库中的测试样例 clusterresroucequota.yaml 展示了其实际 YAML 结构apiVersion: quota.openshift.io/v1 kind: ClusterResourceQuota metadata: name: blue spec: quota: hard: pods: 10 secrets: 20 selector: annotations: null labels: matchLabels: color: nocolor可以看到spec.selector.labels.matchLabels对应提案中的Selector字段spec.quota.hard则完全沿用原生 ResourceQuota 的资源计数格式。另一份模板样例 clusterresourcequota.yaml 进一步展示了 CRQ 支持计数的资源种类除了pods、secrets、cpu、memory、configmaps等通用资源外还包括 OpenShift 与第三方扩展的计数型资源apiVersion: quota.openshift.io/v1 kind: ClusterResourceQuota spec: quota: hard: pods: ${{PODS_LIMIT}} secrets: ${{SECRETS_LIMIT}} cpu: ${{CPU_LIMIT}} memory: ${MEMORY_LIMIT} requests.cpu: ${{REQUESTS_CPU}} requests.memory: ${REQUEST_MEMORY} limits.cpu: ${{LIMITS_CPU}} limits.memory: ${LIMITS_MEMORY} configmaps: ${{CONFIGMAPS_LIMIT}} count/templates.template.openshift.io: ${{TEMPLATE_COUNT}} count/servicemonitors.monitoring.coreos.com: ${{SERVICE_MONITOR}} count/deployments.apps: ${{DEPLOYMENT}}其中count/resource形式用于统计任意 API 资源的对象数量openshift.io/imagestreams等自定义资源名则用于统计 OpenShift 特有资源。三、强制执行的准入机制复用 ResourceQuota 的桶化与评估代码提案对ClusterResourceQuota的执行路径给出了明确的架构决策ClusterResourceQuota将交由一个准入插件admission plugin强制执行该插件复用ResourceQuota准入插件中的桶化bucketing与评估evaluation代码。由于ClusterResourceQuotaSpec.Quota与Status.Overall/ByNamespace直接复用kapi.ResourceQuotaSpec与kapi.ResourceQuotaStatus准入插件可以像处理普通命名空间配额一样进行用量统计与上限判定只是作用域从单个命名空间扩展到了被标签选择器命中的一组命名空间。两级加锁策略跨命名空间的总量强制必然涉及并发一致性问题提案明确了两级加锁方案单 API Server 维度ClusterResourceQuota的更新在进程内通过**进程内锁in-process lock**串行化集群维度多 API Server 时ClusterResourceQuota的更新通过**基于resourceVersion的条件更新condition updates on resourceVersion**来保证一致性。跨命名空间创建资源的竞争这种同一配额被多个命名空间共享的模型天然会引入竞争。提案给出了一个具体场景crq-a 覆盖 ns-1 与 ns-2两个命名空间同时在创建 Pod。在 Pod 被准入之前都要先检查 crq-a于是 ns-1 的 Pod 创建会被阻塞等待 ns-2 的 Pod 完成准入。也就是说共享配额把并发资源创建从命名空间内的局部问题变成了配额组的全局问题。这是共享配额方案与后文配额分配allocation方案最核心的差异点。仓库中的端到端验证提案描述的机制在仓库的 e2e 测试 clusterquota.go 中有完整、可运行的验证测试标签为[sig-api-machinery][Feature:ClusterResourceQuota]。该测试的完整链路与提案一一对应创建集群级配额通过quota.openshift.io/v1客户端创建一个ClusterResourceQuotaSelector使用MatchLabelslabelSelectorKey: barHard同时包含原生资源与扩展资源cq : quotav1.ClusterResourceQuota{ ObjectMeta: metav1.ObjectMeta{Name: cqName}, Spec: quotav1.ClusterResourceQuotaSpec{ Selector: quotav1.ClusterResourceQuotaSelector{ LabelSelector: metav1.LabelSelector{MatchLabels: map[string]string{labelSelectorKey: bar}}, }, Quota: corev1.ResourceQuotaSpec{ Hard: corev1.ResourceList{ corev1.ResourceConfigMaps: resource.MustParse(2), openshift.io/imagestreams: resource.MustParse(1), count/templates.template.openshift.io: resource.MustParse(1), count/servicemonitors.monitoring.coreos.com: resource.MustParse(1), }, }, }, }给两个项目打标签测试通过labelNamespace给firstProjectName与secondProjectName两个命名空间打上匹配标签clusterquota.go随后用waitForQuotaLabeling轮询等待配额在命名空间中生效。跨命名空间累加用量测试依次在两个项目中创建 ConfigMap、ImageStream、Template、ServiceMonitor含自定义 CRD 资源每次创建后通过waitForQuotaStatus轮询Status.Total.Used验证用量确实按跨命名空间的累加值增长。验证总量拒绝当第一个项目中的资源已占用配额后在第二个项目创建同类资源会收到apierrors.IsForbidden配额超限被拒绝。这正是提案中ns-1 与 ns-2 在 crq-a 上共同争用额度的行为验证。测试中还有一处细节值得一提QuotaWaitTimeout time.Minute的注释说明——该值必须大于 cluster quota 对账控制器cluster-policy-controller 中的 reconciliation controller的同步超时因为出现罕见死锁时它可能挂起 30 秒clusterquota.go。这印证了共享配额机制存在跨控制器对账的时序约束。四、API 与权限模型project-owner 角色与配额投射project-owner 角色为了让配额机制可被普通用户理解和使用提案设计了新的角色project-owner将创建一个名为project-owner的新角色。project-owners类似于project-admins但他们还拥有更新部分resourcequota文档的权限。这里有一个精心设计的权限边界不能让project-owner修改任意resourcequota文档——否则 cluster-admin 将无法通过往命名空间里放入极低配额的resourcequota来锁死lock down一个命名空间。短期内的实现方式是通过命名一组特殊配额名来匹配当时的配额作用域scopeterminating、notTerminating、bestEffort、notBestEffort、default这五个名称对应 Kubernetes ResourceQuota 的标准 scope 概念终止/非终止 Pod、BestEffort/非 BestEffort QoS 类以及默认值。长期方案则可以演进为基于标签选择器的权限控制permissions based on label selectors。配额投射让用户能预测创建是否成功提案提出的另一个关键 API 设计是配额投射projection应用于特定项目的、集群作用域的resourcequotaallocation资源将被投射projected进命名空间成为命名空间作用域的localresourcequota资源。这样做的好处是项目内的 ACL 规则只需要对localresourcequota拥有 get、list 权限用户就能在发起资源创建之前查询自己项目内可见的配额信息从而预判自己的创建请求会成功还是失败——而不是等到请求被准入插件拒绝才知道配额已耗尽。从仓库的实际实现看这一投射思想最终以AppliedClusterResourceQuotaappliedclusterresourcequota资源的形式落地位于quota.openshift.io/v1API 组下e2e 测试中反复通过AppliedClusterResourceQuotas(namespace).List(...)读取某命名空间实际应用的集群配额如 clusterquota.go并以此诊断配额拒绝原因CLI 测试 quota.sh 中普通用户deads可以直接执行oc get appliedclusterresourcequota -n quota-foo --as deads -o name查看自己项目中被应用的 CRQ并通过-o jsonpathused{.status.total.used.secrets}读取跨命名空间聚合后的用量——这正是用户可预测创建成败能力的体现oc explain测试explain.go也确认quota.openshift.io/v1组下存在appliedclusterresourcequotas资源类型。CLI 实战创建 CRQ 的三种选择器quota.sh 给出了 cluster-admin 创建 CRQ 的真实命令形态可归纳为三种选择器1. 标签选择器label selector——对应提案中的Selector字段# 给命名空间打上 owner 标签后选中该标签匹配的所有项目 oc label namespace/quota-foo ownerdeads oc create clusterquota for-deads --project-label-selectorownerdeads --hardsecrets102. 注解选择器annotation selector——按项目注解匹配oc create clusterquota for-deads-by-annotation \ --project-annotation-selectoropenshift.io/requesterdeads --hardsecrets503. 带逗号的注解值需转义oc create clusterquota annotation-value-with-commas \ --project-annotation-selectoropenshift.io/requesterdeads,\openshift.io/withcommayes,true,1\ \ --hardpods10该测试还验证了选择器的校验逻辑非法的注解键如openshift.#$%/requesterdeads会被拒绝并提示prefix part a (DNS-1123...) subdomain must consist of lower case alphanumeric characters缺少值的注解openshift.io/novalue会被拒绝并提示Malformed annotation selector。测试同样演示了 CRQ 的动态跟随能力oc delete project quota-foo之后通过oc get clusterresourcequota/for-deads-by-annotation -o jsonpath{.status.namespaces[*].namespace}可以观察到被删除命名空间会从 CRQ 的ByNamespace状态中移除quota.sh——即配额状态会随项目生命周期自动对账。五、与 Label Constrained Quota Allocation 的方案对比提案用一整节对比了两种实现路径共享配额shared quota即 ClusterResourceQuota与标签约束的配额分配label constrained quota allocation。这一对比是理解本设计取舍的核心。配额分配allocation方案的优缺点通过约束分配quota allocation可以写出一个相当高效的实现它只需跨集群监视 resourcequota 对象。这消除了资源创建期间的跨命名空间竞争。优点实现高效、无需在资源创建路径上加锁、不存在跨命名空间争用。缺点对使用者极不友好。提案以新项目创建为例说明为了在配额分配上保持安全新项目在创建时必须把所有被配额的对象全部置零zero out。我们无法在全球范围内合理地做到这一点因为并非所有集群管理员都希望对所有对象设置配额。即使可以安全地用all 作用域配额覆盖单个作用域项目创建之后项目管理员仍必须检查他所有的配额分配上限并创建、修改对应的 resource quota 文档然后才能在项目里做任何事。这要求项目管理员在使用项目之前就对整套配额系统有相当深入的理解——学习成本过高。共享配额ClusterResourceQuota方案的优势相比之下共享配额方法在正常使用中不需要项目管理员采取任何行动。只有集群管理员才需要操心细节项目管理员只需要使用他的项目即可。对普通用户零负担项目管理员无需理解配额系统即可正常使用项目可叠加细分如果项目管理员愿意他可以自行设置resourcequota对象来约束特定项目防止某个项目耗尽自己的共享额度支持超卖overcommit项目管理员可以超额预订自己的clusterresourcequota即各项目内部配额的加总可以超过共享配额的总量。性能基准共享配额的竞争成本提案作者在 PR测试代码即为此文所述机制的早期原型中用100 个命名空间共享同一个 CRQ做了最坏情况下的竞争压测我为每个命名空间各创建一个 Pod并在尝试创建下一个之前等待 API Server 的响应。这是最坏情况的行为因为针对给定命名空间的多个请求会被批处理batched锁成本会被摊薄。测试结果单客户端每命名空间每秒可创建 2.6 个 Pod双并发客户端replication controller manager 的工作方式吞吐翻倍。提案据此给出的结论是两种方案互不排斥Neither approach precludes the other但考虑到 clusterresourcequota 相对易用、且扩展性合理我们应该从这里开始。也就是说共享配额先行的策略是基于易用性优先 可接受的竞争成本的综合权衡而非绝对的技术优越性。六、落地现状与仓库证据汇总提案设计仓库落地证据ClusterResourceQuota对象与类型quota.openshift.io/v1API 组样例见 clusterresroucequota.yaml 与 clusterresourcequota.yaml存储路径登记于 etcd_storage_path.go跨命名空间总量强制与按命名空间用量e2e 测试 clusterquota.go覆盖 ConfigMap、ImageStream、Template、ServiceMonitor 四类资源的跨命名空间累加与拒绝配额投射localresourcequota实际实现为命名空间内的appliedclusterresourcequota资源普通用户可 get/list 查看见 quota.sh选择器校验quota.sh 验证非法标签/注解选择器被拒绝与原生 ResourceQuota 的关系命名空间级配额计数测试见 resourcequota.go镜像类配额准入测试见 quota_admission.go可对照理解 CRQ 复用的评估逻辑总结ClusterResourceQuota是 OpenShift 用标签选择器 集群级配额对象 复用 ResourceQuota 评估逻辑的准入插件组合出的跨命名空间资源管控方案它以几乎零用户学习成本为设计优先级把细分与超卖的灵活性留给项目管理员同时通过ByNamespace状态切分与按命名空间投射appliedclusterresourcequota把对账和可观测成本控制在合理范围。其代价——跨命名空间资源创建时的竞争锁——则通过设计阶段的压测100 命名空间下单客户端 2.6 pods/ns/s、双客户端翻倍被量化为可接受的扩展性边界。对于需要在多项目场景下按用户/团队做总量管控的集群管理员而言这套机制是比逐命名空间堆叠 ResourceQuota 更直接、更易维护的选择。赞分享测试云原生质量保障【免费下载链接】originConformance test suite for OpenShift项目地址https://gitcode.com/gh_mirrors/or/origin点击查看免费下载相关推荐Cantera完全指南从入门到精通的化学动力学与热力学模拟工具Cantera完全指南从入门到精通的化学动力学与热力学模拟工具 Cantera是一款功能强大的开源软件工具套件专为解决涉及化学动力学、热力学和输运过程的复杂科学计算高性能计算IronClaw 的共享 WASM 资源限额器ironclaw_wasm_limiter 的设计、实现与架构约束IronClaw 的共享 WASM 资源限额器ironclaw_wasm_limiter 的设计、实现与架构约束 ironclaw_wasm_limiter人工智能AI 应用交互助手AI AgentTiDB Global Resource Control 设计解析用 Request Unit 实现共享集群中的全局资源控制与跨租户调度TiDB Global Resource Control 设计解析用 Request Unit 实现共享集群中的全局资源控制与跨租户调度 导读 在多应用共享同数据库分布式数据库后端OLAP上一篇Blue Hydra高级配置优化蓝牙设备发现性能的7个技巧下一篇RuoYi-Vue-fast通知公告功能实现消息推送机制分析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表