拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

容器云容量规划与弹性扩容实践:从资源展示到多集群台账

容器云容量规划与弹性扩容实践:从资源展示到多集群台账

简介:面向互联网、证券等资源使用时段集中且闲时利用率偏低的业务场景,为容器云平台架构师、运维人员及产品规划者提供容量规划与管理优化的完整思路。文档从用户体验入手,梳理管理员与租户两类视角的资源分配、使用与可用量展示逻辑;随后强调多集群环境下不能只依赖Kubernetes联邦,而应从平台层统筹容器云、云管、DevOps、服务治理等系统融合;最后落到计算、持久化存储、网络资源的需求预测与容量评估,并细化underlay/overlay网络选型、NFS动态存储、平台组件精简、基础镜像优化等实操要点,对私有云环境下的资源治理具有直接参考价值。资源为单个PDF文档,大小约708KB,无需安装即可阅读。已有65人学习下载,适合正在规划容器云平台或希望优化现有资源分配策略的技术团队。

1. 容器云容量规划:为什么闲时资源也无人敢释放

证券行业的容器云平台有个很典型的时点特征:上午 9 点到 10 点,行情和交易相关服务的资源使用冲到峰值,过了这个时段,CPU 和内存的占用率迅速回落。表现出来就是集群平时看着很空闲,各团队却都不敢释放资源,生怕第二天开盘那一刻扩容来不及。这个矛盾在互联网行业同样普遍——业务有波峰波谷,容量规划却只能按波峰做。这本《容器云平台容量规划及管理优化》要解决的,正是从资源展示、多集群台账、需求预测到弹性扩容这一整条链路的规划方法。它没有停留在 Kubernetes 用法上,而是从平台层往下拆,适合正在做容器云平台建设,或已被资源浪费困扰的运维和平台研发人员。

2. 资源用量展示设计:租户和管理员两个视角的四个关键字段

很多团队做容器云平台,第一步先扑在安装部署和网络选型上,等真正上线了才发现:没人说得清资源到底够不够、谁占了多少、该不该释放。这份文档把第一步放在了资源展示上,其实是把容量规划的前置条件定了——没有清晰可见的分配量、使用量、可用量,后面的预测和扩容都是盲猜。而展示要分两个视角,租户和管理员关心的字段并不完全一致。

2.1 租户视角:把「分配了多少、用了多少、还能用多少」一次看清

租户没有义务去理解 Kubernetes 的 namespace 和 ResourceQuota 概念,他们只关心三件事:我有多少资源、我用了多少、我还能不能再申请。所以界面上直接给「分配量 / 使用量 / 可用量」三个数,缺一个用户就没法自己判断该不该发起扩容申请。这里说的分配量是平台批给租户的额度,不是实例实际占用的量;使用量是当前所有工作负载实际 request 的总和;可用量就是二者之差。

光给总量还不够。租户的资源往往分散在多个集群、多个分区上,只给一个汇总数字,用户想扩容不知道扩到哪个集群,想缩容也不知道哪些实例占了多少配额。文档里提到的展示粒度,租户要能一路看到「分布在哪些集群、哪些分区、部署了多少应用、多少服务、多少实例」,这个粒度做下来,用户在服务列表里就能看到每个服务的配置、实例数和资源使用率。

最容易做漏的一个细节:请求峰值和实际使用峰值要分开展示。一个服务 CPU 分配 4 核,平时平均只用 0.5 核,但它在早上 9 点 15 分那波行情里冲到过 3.8 核——只看平均值会觉得它浪费,只看瞬时值又会让用户以为资源总是很紧张。两个值都放出来,用户才能判断要不要调整 limit。文档里举的例子很实在:一个服务分配了大量资源但利用率一直很低,就是不合理;反过来,分配太少导致容器无法启动,就会一直反复重启。这两种情况,都应该通过界面上的资源使用效率数据直接暴露给租户。

2.2 管理员视角:私有云不计费,但资源使用效率必须算

管理员和租户看到的东西要拉开层次。私有云环境不向租户计费,但这不意味着资源可以随便分配随便用,文档里那句话很直接:好钢要用在刀刃上。管理员需要知道每个租户分配了多少、实际用了多少、可用多少,还要知道资源的使用效率——也就是用了的这部分,真正跑出多少业务负载。

这一点和公有云计费场景有本质区别。公有云通过账单天然约束了浪费行为,私有云没有这个约束,只能靠平台自己把低效使用暴露出来。所以管理员视图里的核心指标不是「分配了多少」,而是「分配了之后用没用起来」。具体到界面上,管理员应该能看到按租户、按集群、按分区的资源利用率排行,能一眼找出「分配 32 核但持续 3 天利用率不到 10%」的租户或服务,然后再去看这个租户下面的服务是不是规格设置偏大、副本数过多。

这里要特别提醒:不要直接把租户自己的三数视图原样搬到管理端。租户看到的是「我的额度够不够用」,管理员看到的是「整个平台的资源被用得合不合理」,这是两套不同的查询维度。把这两套视图混在一个界面里,最后的结果往往是谁都不好用——租户嫌信息太多,管理员嫌看不到关键排名。

2.3 从展示反推采集:请求值与实际使用值的口径差异

展示字段定下来之后,采集口径就是下一个坑。文档中提到的服务配置和实例配置,对应到 Kubernetes 里就是 request 和 limit 这两套值。很多平台在界面上只展示 limit,这会导致一个错觉:服务显示用了 4 核,其实它只是被限到 4 核,真正跑起来也许只有 0.5 核。

建议在资源面板里至少保留三列数据:request(调度承诺值)、limit(上限值)、实际使用值。租户判断「够不够」主要看 request 的汇总和可用配额的对比;判断「浪不浪费」主要看实际使用值和 request 的比值。如果一个服务 request 设了 2 核,实际长期只有 0.2 核,这个比值是 10%,管理员视图里就应该被标记为低效服务。

采集周期也要说清楚。默认的 60 秒采样对趋势判断够用,但对峰值捕捉不够,需要额外落一组 5 秒粒度的短期数据,专门用于最近 5 分钟的峰值计算。这个数据不用长期保存,保留 24 小时足够,用于回答「早上那波峰值到底冲到了多少」这类复盘问题时,非常有价值。

3. 多集群容量台账:平台层为什么必须高于 Kubernetes

资源展示把现状看清楚之后,就要回答容量规划的下一个问题:这些资源分布在哪、谁在持有、总量还有多少。文档里有一个判断我比较认同——容器云平台不能只考虑 Kubernetes,不是实现集群联邦就算多集群了,平台设计一定要高于 Kubernetes。很多人从开发人员角度理解容器云,把平台等同于 Kubernetes,如果真是这样,直接用 Kubernetes 就够了,没必要再封装一层。平台要做的是把集群、租户、分区抽象成统一的资源台账。

3.1 单集群起步还是多集群起步:先回答备份需求

文档里的建议很务实:初始需求量不是很大时,不适合搭建多个集群。多集群不是越多越好,每个集群都要有控制面、监控、日志组件,这些组件本身就要吃掉一部分资源。只有在明确的多集群备份需求下,才需要搭至少两个集群,把关键业务做备份部署。

这一点在容量规划里很关键。单集群场景下,规划只需面对一个资源池;多集群场景下,同一个租户的资源可能散在多个集群里,每个集群的剩余容量要单独统计。文档特别提到,在多集群环境下租户可能拥有多个集群的资源,每个集群的资源都可以基于云管来做扩容。这要求平台有全局的顶层资源视角——平台资源总量、使用量、分配量、可用量,然后才是每个集群、每个分区、每个租户、每个节点的资源总分配和使用情况。

3.2 租户是逻辑概念:平台层要管理 Kubernetes 之外的对象

Kubernetes 里没有租户概念,这是很多封装型平台最容易露馅的地方。租户在 Kubernetes 眼中只是一组对象:一组 namespace、一组 RBAC 绑定、一组 ResourceQuota。但真实的租户还需要资源分区、配置中心、日志中心这些平台层对象,这些对象不在 Kubernetes 的模型里,所以一份简单的替换方案或一个集群联邦项目,根本回答不了「租户怎么隔离、配额怎么管理、资源怎么跨集群调度」这些问题。

文档里给了一个明确的设计原则:租户可以是一个逻辑概念,是 Kubernetes 一些对象的集合,也包括 Kubernetes 之外的对象。落在实现上,平台层的租户模型应该有自己独立的资源额度表,和底层的 namespace 解耦。租户申请资源,平台先在额度表里扣减,再决定在哪个集群创建 namespace。这样一来,租户扩容就不需要直接改 namespace 的 quota,而是走平台层的额度调整逻辑。

这也是后面弹性扩容能自动化运行的前提。如果租户的资源额度直接绑定在 namespace 的 ResourceQuota 上,那每次扩容都要去改 YAML,人工介入就不可避免。

3.3 全局容量台账:从平台总量到节点使用量的四级视图

容量台账建议按四级维度组织:平台、集群、分区、节点。每一级都维护总量、分配量、使用量、可用量和利用率这五个字段,上一级的分配量等于下一级分配量的总和,这样从任何一层下钻都能对上账。

层级总量分配量使用量可用量利用率
平台云管提供的全部计算/存储/网络资源所有集群分配量之和所有集群实际使用之和总量减分配量使用量 / 总量
集群该集群节点容量之和集群内所有分区分配量之和集群内所有工作负载实际用量总量减分配量使用量 / 总量
分区分区资源池容量分区内所有租户分配量之和分区内实际使用量总量减分配量使用量 / 总量
节点节点 Allocatable 容量节点上实例 request 之和节点上实例实际用量总量减分配量使用量 / 总量

四个字段的计算不复杂,但采集时要注意:分配量统计的是 request 而不是 limit。原因很简单,调度器按 request 做调度决策,limit 只在运行时兜底。如果拿 limit 统计分配量,一个 limit 设 8 核、request 只设 0.5 核的服务会把账面上的容量大量占掉,导致台账显示资源不足,实际却很空闲。

另外,平台自身的组件和 Kubernetes 组件占用的资源,在台账里要单列一行。文档提醒过:如果平台设计得不好,组件和 Kubernetes 组件会占用很多资源,造成浪费。这部分通常是看不见的黑匣子,但它在节点的 Allocatable 里是实打实扣掉的。建议把这部分资源单独统计为「系统预留」,既方便排查节点为什么可用容量比预期少,也能在容量规划时把这部分一并算进总需求。

4. 需求预测与容量规划:计算、存储、网络三块盘子的推演

有了台账,才能谈预测。租户的资源需求通常基于应用部署要求来确定,分配时往往按最大请求量来算。某一阶段内所有租户需求的总和,基本上就反映了容器云平台的资源需求量,再预留一部分资源应对意外情况,或者实现按比例自动扩展,就能得出这一阶段需要的资源容量。规划时要同时看三块:计算资源、持久化存储、网络资源。

4.1 计算资源:从实例规格反推集群容量,并预留扩展余量

计算资源的评估方法很直接:评估应用服务和部署每个实例的 CPU 与内存分配,就能大致知道所需的计算资源。这里有个容易忽略的点——平台组件和 Kubernetes 组件本身占用的资源。文档里特意提到,很多人追求微服务,把服务拆分得很碎,在容器云平台里每个服务都部署成一个容器,就要维护很多容器,这本身就会造成大量资源浪费。评估容量时,平台组件和 k8s 组件的开销应该按固定比例预留,通常按节点总容量的 10% 到 15% 规划比较稳妥。

计算资源这块的预测逻辑可以分成三步走。第一步,把租户要部署的所有服务的实例规格列出来,算出 request 总和;第二步,加上平台组件、监控、日志、网络插件这些系统开销;第三步,按文档建议再预留一部分资源应对意外情况,这部分如果做成按比例自动扩展,就不需要把余量留太大。

这里最怕的是照着 limit 做预测。很多团队在资源评估表里填的是服务 limit 值,4 核 8G 这种规格看着没问题,但如果是 limit 和 request 没配平的服务,几十个实例下去,账面上的容量需求会比实际高出一大截,平台建设成本被严重高估。

4.2 持久化存储:NFS 起步,动态分配交给 StorageClass

持久化存储是私有容器云里绕不开的一块。文档给出的建议很接地气:如果没有特殊要求,私有云用 NFS 就可以了。不要一上来就上分布式存储,NFS 的并发性能对大多数内部系统够用,运维复杂度和成本都低一个量级。

真正需要花心思的是动态分配。租户首次申请资源时会评估存储需求,通常会静态创建持久化存储卷;但某些容器会动态创建,需要动态分配存储卷。这个场景在 Kubernetes 里有标准解法:用 StorageClass、PV、PVC 加 ServiceAccount 来实现存储的自动分配和租户访问控制。StorageClass 定义了存储类型和回收策略,PVC 描述需求,PV 是实际分配的存储卷,ServiceAccount 则控制哪个租户能访问哪个存储资源。

落到容量规划上,存储的台账建议单独建,不要和计算资源混在一张表里。存储池的总容量、已分配 Volume 的容量、实际写入数据量这三个值要能对得上。这里有个经验:很多租户申请的存储远远超过实际写入量,PVC 分配 100G,最终可能只写了 20G。所以存储利用率要按实际写入量算,规划下一批采购时才能避免盲目扩容。

4.3 网络资源:underlay 与 overlay 的网段规划分寸

网络资源的规划是最容易被低估的部分。调研容器云时大家更多讨论选什么网络模型,很少讨论网络资源的规划和管理。文档里讲得很清楚:选不同的网络模型,后期运维和管理方法完全不一样,而且网络规划要在平台建设早期就定下来,等集群跑起来再改网络模型基本等于重建。

underlay 网络下,容器直接使用物理网络地址,需要提前规划分配网段及 IP 地址范围,还要规划业务 Pod 网段和网络地址类型(B 类或 C 类地址),并且作为容器云平台的专用网段,不要和其他业务混用。这里有个很现实的数字:C 类地址一个网段只有 250 来个可用地址,部署量稍微大一点就不够用,所以规划时要专门区分管理网段(节点所在网段)和业务网段(容器实例 IP 网段),并提前确定地址类型。

overlay 网络下,容器网络是虚拟的,需要规划的网段和 IP 会少一些,但文档同样建议对虚拟网络做统一规划,选择合理的虚拟网段和虚拟 IP 范围,不要放任自流。两种网络各有优缺点,企业级场景下不同的集群可以部署不同的网络类型来支持不同业务——比如一个集群用 underlay 做全网可达的固定 IP 访问场景,另一个集群用 overlay 跑常规业务。下表是我每次做选型时都会拉出来的对比维度:

维度underlayoverlay
网段规划需提前规划独立业务网段和 IP 范围虚拟网段,也建议统一规划
地址类型按容器量选 B 类或 C 类,C 类仅 250 余个可用地址虚拟 IP 范围,相对宽松
容器可达性全网可达,便于固定 IP 访问和问题排查隔离性好,跨网络访问依赖网关
运维复杂度网段独占,需和其它业务隔离虚拟网络,隧道开销略高
适用场景需要固定 IP、外部直接访问容器的场景常规微服务,不与外部直连的场景

当初我们在一套环境里同时跑了两种网络,踩过的坑是跨集群通信的网关配置不一致,排障时非常费劲,后来统一收敛成「一个集群只固定用一种网络模型,跨集群通信一律走平台网关」,排查链路才清晰起来。

5. 弹性扩容的坑与解法:namespace 限额、租户扩容和节点扩展

容量规划的最终落地动作是弹性扩容。文档在这一部分花了不少篇幅,因为厂商设计不合理会把弹性伸缩变成负担。核心矛盾集中在 namespace 资源限额、租户自动扩容和平台扩容方式上。这里面的坑,几乎都是等扩容触发时才暴露的。

5.1 namespace 强制限额:为什么扩容出来的 Pod 起不来

Kubernetes 的 namespace 可以设置限额,但不是必须设置限额。问题出在有些厂商实现平台时,以 namespace 对应租户下的应用,强制必须设置资源限额,也就是应用的资源限额。这个设计表面上是为租户好,实际会卡死按需自动弹性扩展:分配的资源不够时,扩容的服务实例无法启动,必须人工去修改 namespace 限额。

我在一套环境里遇到过的典型案例:某租户的服务副本数从 4 扩到 8,HPA 已经触发了,但新 Pod 一直 Pending,events 里报 quota exceeded。原因就是 namespace 的 ResourceQuota 把 requests.cpu 和 requests.memory 设成了硬上限,而服务每个副本的 request 又比较高,扩展副本数时 requests 总和直接顶到配额上限。

apiVersion: v1 kind: ResourceQuota metadata: name: app-quota namespace: team-a spec: hard: requests.cpu: "8" requests.memory: "16Gi" limits.cpu: "16" limits.memory: "32Gi"

上面这个配置里,requests.cpu 上限是 8 核。如果服务每个副本 request 是 1 核,那么当副本数扩展到第 8 个时,requests 总和正好等于 8 核;再往前扩一步,第 9 个副本就会被拒绝。HPA 的扩展策略并不会因为 quotas 而暂停,它会持续尝试创建副本,然后持续失败,直到有人在控制台里发现异常。要解决这个问题,要么把 ResourceQuota 的 requests 和 limits 分开设置,给扩展留出余量;要么干脆不在应用级 namespace 上做强制限额,把配额管理上移到平台层租户维度。

这背后有个设计取舍:namespace 的 ResourceQuota 是 Kubernetes 原生的硬边界,适合做强制隔离;但它是静态的,扩缩容频繁的场景下非常不灵活。平台层需要把「租户额度」和「namespace 限额」解耦,租户额度用平台自己的模型管理,namespace 限额只做兜底防护,不承载租户日常扩容逻辑。

5.2 租户自动扩容:容器云平台与云管平台的两层资源边界

Kubernetes 里没有租户概念,租户功能必须在平台层实现。文档明确强调,租户可能是一组 Kubernetes 对象的集合,也包括平台层对象,所以一个 Kubernetes 集群远远不够,平台层必须有自己的租户模型。在此基础上,租户资源不足时的自动扩容,就涉及两层资源管理:容器云平台层的资源和云管平台层的资源。

容器云平台的资源是基于云管资源的,租户的资源扩容由容器云平台负责分配;当容器云平台自身资源不足时,再由云管平台自动分配新的计算资源进来。这两层职责边界要清晰划分,不要混在一起把问题复杂化。我们考虑过给租户自动扩容加审批流程,和云管平台集成实现,但最终发现审批流程依然会带来大量维护工作量。正确的方向是尽量自动化、无人化,减少人为介入。

这里的关键是:租户扩容不是改一个 namespace 配额那么简单,它可能涉及跨集群调度、云管资源分配、甚至物理节点扩容。理想情况下流程应该是这样的:租户在平台发起扩容 → 平台检查租户额度和目标集群剩余容量 → 集群容量不足时自动向云管申请新节点 → 新节点加入集群 → 扩容完成。整个过程不需要人点任何审批按钮,只有超出租户额度的申请才需要人工介入。

5.3 平台扩容方式:虚拟化节点快,物理节点要留备机

平台自身的扩容有两种路径,差异比较大。云管平台往往基于虚拟化,资源管理相对容易,可以快速创建虚拟机、增加节点、扩展资源,所以用云管来支撑容器云平台的弹性资源伸缩相对容易实现。但容器云平台也可以直接基于物理服务器部署容器,每台物理服务器是一个节点,要扩展资源就可能需要增加物理服务器节点——节点加入容器云平台很容易,但物理服务器的准备通常需要时间。

文档给出的建议很实际:要备份一些机器用于弹性扩容,可以由云管平台统一维护这些备用机器。也就是说,理想的资源供给结构是云管同时管理虚拟化和物理服务器,以及其他云资源,共同为容器云平台提供资源支持。这在容量规划里意味着:不要把「现有节点容量」当成「全部可用容量」,要把云管的备机池也算进可扩展容量的边界。

备机池的规划逻辑也要提前定:备机数量按在线节点总量的比例预留,还是按最大业务峰值预留?按比例预留成本可控,但峰值来临时可能不够;按峰值预留成本高但稳妥。我的做法是分两级——平时保留少量热备机应对瞬时扩容,同时和云管协商好冷备资源池,需要大规模扩容时提前 30 分钟申请拉起。这样既控制闲置成本,又不会在突发流量面前束手无策。

值得一提的还有资源池水位算法。很多平台判断「要不要扩容节点」只看节点分配率(所有 Pod requests 之和除以节点容量),这个指标在业务高峰时响应太慢。更合理的做法是加一个快速指标:节点在过去 5 分钟的 CPU 实际使用率。这个指标比分配率更接近业务真实压力,两者结合判断扩容时机,比单看任何一项都准。这些就是容量优化里的「玄学」——每一步都有优化空间,但每一步都藏着一个变量。

5.4 避坑排查记录:五条扩容和容量规划踩坑实录

以下五条现象来自实际排查记录,按「现象 → 原因 → 解决」梳理。

第一条:Pod 扩容后一直 Pending,events 报 QuotaExceeded。现象:HPA 触发扩容,新副本始终处于 Pending 状态,查看事件提示配额超限。原因:namespace 的 ResourceQuota 硬上限过小,requests 总和抵到配额。解决:调整 ResourceQuota 的 requests 和 limits 配额,或取消应用级强制限额,把租户额度的判断放在平台层。

第二条:节点 CPU 空闲,但租户扩容仍然报资源不足。现象:集群整体负载很低,某租户扩容时平台提示资源不足,无法调度。原因:节点上 system-reserved 和 kube-reserved 预留过大,导致 Allocatable 容量被大量占用;或资源池判断逻辑只看分配量,没看实际使用量。解决:检查节点 Allocatable 与实际使用量,重新校准系统预留比例。

第三条:扩容审批流程走完,业务高峰已经过去。现象:租户提交扩容申请后层层审批,等流程走完,压测或行情高峰已经结束,扩容失去意义。原因:自动扩容链路里每一步都插入人工审批,链路过长。解决:只在超出租户额度时走审批,常规扩容全部自动化,由平台按水位策略直接执行。

第四条:underlay 网络容器 IP 与其它系统冲突。现象:业务 Pod 部署后,访问外部系统时偶发连接错乱,排查发现是容器 IP 和别的业务服务器 IP 重叠。原因:业务网段没有独占,容器云平台网段与其它系统混用。解决:将管理网段、业务网段独立规划并固定为容器云平台专用段,不再分配给其它业务使用。

第五条:租户反馈服务频繁重启,业务时断时续。现象:服务实例反复 CrashLoopBackOff,业务间歇性不可用。原因:服务分配的 request 资源过小,容器启动时内存不足被 OOMKill,或健康检查失败被反复重启。解决:核对服务实例规格与 requests 配置,为实例设置足够的最小启动资源,再结合运行监控逐步调低。

这五条都有个共同特征:问题不是出在扩容动作本身,而是出在扩容之前的容量规划环节——配额设计、预留策略、网段规划,任意一环有隐患,都会在扩容那一刻集中爆发。

6. 容量省在细节里:镜像大小、组件整合与自动化运行

容量规划做到最后,比拼的往往是细节。文档里提到的两个细节,长期收益比很多复杂的调度策略都大。

第一个是基础镜像优化。同样的 Java 微服务,用 JDK 还是 JRE 镜像,用 Tomcat 还是其它应用服务器镜像,镜像大小不同,耗费的资源就不一样。单个容器差别不明显,但几十个、上百个服务实例叠加,节点磁盘、内存、镜像仓库存储的开销差距就非常可观。容器平台的组件服务同样如此——如果每个小服务都单独部署成一个容器,维护大量容器本身就是浪费。

镜像选型体积量级内存占用典型场景
JDK 基础镜像大相对高需要编译、调试工具的开发环境
JRE 基础镜像中较低仅运行 Spring Boot 等微服务
精简 JDK 定制镜像小低生产环境标准化运行镜像
Alpine 系镜像最小最低静态编译或轻量服务

生产环境建议维护一份经过裁剪的基础镜像列表,团队不允许随意使用基础镜像,这样能同时控制镜像体积和运行时开销。

第二个是自动化、无人化运行。扩容实现自动化后,长期节省的时间精力可以做其它更有意义的事。这要求平台把资源使用管理和优化当成一个持续过程,随着实践和认知提升,逐步改进一些不合理的环节。

从那以后,我每次做容量规划都强制走一遍同样的流程:先核对租户界面和管理员界面的展示口径,再拉一遍四级台账对账,然后检查网络模型是否与业务需求匹配,最后才做扩容策略配置和备机规划。这套流程看着繁琐,但每一步都在避免「闲时不敢释放、峰值扩不动」的尴尬局面。希望这篇拆解能帮你在规划自己平台的容量时,少走几段弯路。

本文还有配套的精品资源,点击获取

返回列表