news 2026/9/10 6:17:23

Onyx Helm Chart 集群容量规划实战:从 Sizing 分层到生产级资源配置调优

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Onyx Helm Chart 集群容量规划实战:从 Sizing 分层到生产级资源配置调优

Onyx Helm Chart 集群容量规划实战:从 Sizing 分层到生产级资源配置调优

【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer

本指南以 deployment/helm/charts/onyx/SIZING.md 为核心,系统讲解 Onyx(danswer)Helm Chart 的容量规划方法:包括 small / medium / large 三档规模对应的资源配置片段、四条来自生产集群的经验法则、以及如何与 Terraform 基础设施分层一一对应。读完本文,你将能根据自身用户规模与文档量,为 Onyx 的 api-server、Celery 工作线程、模型服务器和 OpenSearch 编写一份可直接落地的 values 覆盖文件。

起点:默认资源校准目标与三档规模模型

Onyx Chart 的默认资源配置(见 values.yaml)是为"中型部署"校准的:约 200–1,000 用户、文档量最多 ~200 万、所有组件单副本。当你的部署规模变大或变小,就需要用独立的 values 文件覆盖默认值。

容量规划的第一条原则是:没有任何一份"万能"预设。因为哪些组件运行在集群内、哪些使用托管服务,会显著改变资源总量——例如集群内跑一个 OpenSearch Pod、同时使用 AWS RDS 托管 Postgres,是完全可以接受的混合形态。因此本指南的做法是:按需从下面的片段中复制进你自己的 values 文件

三档规模对照表

SIZING.md 给出的分层与 Terraform 模块(deployment/terraform/modules/aws)中onyx模块的size入参一一对应(默认medium,校验仅接受small/medium/large,见 variables.tf):

档位用户规模文档量Terraform 节点配对
small最多 ~200< ~50 万1× 8 vCPU / 32 GiB(m7i.2xlarge)¹
medium~200–1,000~50 万–200 万m7i.4xlarge ×1–5
large1,000+数百万级m7i.4xlarge ×2–8 + 专用索引节点

¹ 该节点形态仅在 Postgres、Redis、对象存储全部外置(RDS / ElastiCache / S3)时成立;若这些数据面组件也留在集群内,则需要第二个节点。

Terraform 侧各档位的基础设施默认值

为便于对照,onyx模块在各档位下为计算与数据面提供的完整默认(见 deployment/terraform/modules/aws/README.md 的 "T-shirt sizing" 一节):

设置项smallmediumlarge
主 EKS 节点组m7i.2xlarge ×1–3³m7i.4xlarge ×1–5m7i.4xlarge ×2–8
文档索引节点¹无³m6i.2xlarge,100 GBr6i.4xlarge,512 GB
RDS Postgresdb.t4g.large,64→256 GBdb.t4g.large,128→512 GBdb.m7g.xlarge,256→1024 GB
ElastiCache Rediscache.m6g.largecache.m6g.xlargecache.m6g.2xlarge
OpenSearch 数据节点²r7g.large.search ×1,256 GBr8g.xlarge.search ×1,512 GBr8g.2xlarge.search ×1,1 TB(12k IOPS)
OpenSearch 专用主节点²3× m7g.medium.search3× m7g.medium.search3× m7g.medium.search

¹ 专用索引节点组仅在集群内运行文档索引(Chart 内置的 OpenSearch StatefulSet)时有意义。它创建时带有vespa-dedicated=true污点,因此 StatefulSet 必须同时携带下文 Large 片段中的 tolerationnodeSelector 才能被调度上去。 ² 仅当enable_opensearch = true时创建。 ³ small 档不创建索引节点组——small 档的 Chart sizing 把集群内索引放在主节点上即可。

注意:上表中的每个值都只是默认值,任何一个 sizing 变量被显式设为非空(如postgres_instance_typeopensearch_instance_typemain_node_max_size)都会覆盖对应档位的默认。该模块与 Chart 的配合方式是:Terraform 档位负责"基础设施有多大",SIZING.md 的片段负责"工作负载怎么摆",二者需成对使用。

四条生产原则:来自真实集群的容量规划经验

SIZING.md 的核心价值在于四条由生产环境沉淀的原则,它们解释了为什么某些看似"反直觉"的配置才是正确的。

1. Request 负责调度,Limit 负责突发

稳态使用量通常只是默认 requests 的一小部分;真正搞垮部署的几乎总是limit——CPU 被限流(CFS quota 耗尽)、内存 OOM。因此在调整资源时,优先审视 limit 是否给足,而不是把 request 调大去"贴合"实际用量。这一点在 api-server 的注释中也有印证:values.yaml明确警告"CPU limit 必须远高于 request",因为在并发慢流(slow-stream)负载下,1 核的 limit 会耗尽 CFS 配额,进而卡死异步/health端点导致 liveness 被杀。

2. api-server 要"横向扩容"而非"纵向加码"

api-server 应使用 HPA,且只配 CPU 目标。原因:空闲时 api-server 的 RSS(常驻内存)约 1.1 Gi,紧贴内存 request(默认 1 Gi,见 values.yaml),如果给 HPA 加上内存目标,它会被永久钉在最大副本数。Chart 的 HPA 模板(templates/api-hpa.yaml)按值渲染 metric:targetMemoryUtilizationPercentage设为空字符串时,内存指标不会进入 HPA spec,从而实现"仅 CPU 目标"。

3. OpenSearch 的内存压力在堆外

OpenSearch 的内存占用大头是堆外内存:k-NN 原生内存 + Lucene page cache。所以随着索引增长,要上调容器内存,但 Java 堆应保持在 ~4g,直到你有了确凿的堆使用数据——不要按比例放大堆。Chart 默认opensearchJavaOpts: "-Xmx4g -Xms4g"(values.yaml),Xms 与 Xmx 保持一致,这也是官方推荐"堆约为内存 limit 的 50%"的体现。

4. 被钉死的索引模型服务器不只是"慢"

如果 embedder(索引模型服务器)在大型 re-index 期间连续数小时顶在 CPU limit 上,可能饿死 docprocessing 的心跳(heartbeat),触发索引停滞看门狗(stall watchdog,相关实现见 backend/onyx/background/celery/tasks)。因此在计划大规模批量 re-index 之前,先提高索引侧的 CPU limit(并考虑加副本)。这正是 Chart 在indexCapability.resources注释中反复强调的:"limit 而非 request 决定 re-index 吞吐"(values.yaml)。

Small 档:为单节点瘦身

适合 pilot 与小团队:所有工作负载收进一台 8 vCPU / 32 GiB 节点。完整片段如下:

webserver: replicaCount: 2 # keeps rolling deploys seamless # Embedding traffic is light and bursty at this scale. inferenceCapability: resources: requests: {cpu: 500m, memory: 3Gi} limits: {cpu: 3000m, memory: 10Gi} indexCapability: resources: requests: {cpu: 500m, memory: 3Gi} limits: {cpu: 3000m, memory: 6Gi} # Coordination singletons measure single-digit millicores in production. celery_beat: resources: requests: {cpu: 250m, memory: 512Mi} limits: {cpu: 1000m, memory: 1Gi} celery_worker_monitoring: resources: requests: {cpu: 250m, memory: 512Mi} limits: {cpu: 1000m, memory: 4Gi} celery_worker_primary: resources: requests: {cpu: 250m, memory: 2Gi} limits: {cpu: 1000m, memory: 4Gi} # Craft build-loop worker; set back to 1 if you use Craft/sandbox features. celery_worker_scheduled_tasks: replicaCount: 0 # If your document index is in-cluster (opensearch.enabled: true): opensearch: resources: requests: {cpu: 1000m, memory: 4Gi} limits: {cpu: 2000m, memory: 8Gi}

逐项说明(对照 Chart 默认值):

  • webserver 副本 = 2:保证滚动发布(rolling deploy)期间前端不中断。默认replicaCount: 1
  • inferenceCapability(查询侧 embedding 模型服务器):embedding 流量在小规模下"轻且突发",所以 request 降到 500m/3Gi(默认 1000m/3Gi),保留 3000m/10Gi 的 limit 作为突发余量。Chart 注释也确认了这种设计:"embedding 工作突发性强:适度的 CPU request 让 Pod 能在小节点上被调度,limit 则提供查询期 embedding 的突发余量"。
  • indexCapability(索引侧 embedding 模型服务器):同样降至 500m/3Gi request、3000m/6Gi limit(默认 request 1000m/3Gi、limit 6000m/6Gi)。
  • celery_beat / celery_worker_monitoring / celery_worker_primary:协调类单例(singleton)在生产中只消耗个位数毫核,所以 request 统一降到 250m,内存按各自角色保留(beat 512Mi、monitoring 512Mi、primary 2Gi——primary 要处理主队列任务,默认 request 就是 2Gi)。
  • celery_worker_scheduled_tasks 副本 = 0:这个 worker 是 Craft 调度任务的专用执行器(headless executor,长期运行 LLM + 沙箱工具调用,见 values.yaml 的说明)。不用 Craft/沙箱功能就关掉,能省下一份常驻资源;启用则恢复为 1。
  • opensearch:如果文档索引在集群内(opensearch.enabled: true,默认即开启),把 OpenSearch 压到 1000m/4Gi request、2000m/8Gi limit(默认 2000m/4Gi request、4000m/8Gi limit)。

采用外部数据面(external data plane)时,这一整套配置的 requests 合计约6.9 vCPU / ~22 GiB,恰好放进一台 8 vCPU / 32 GiB 节点。

Medium 档:生产部署的收敛形态

200–1,000 用户、约 50 万–200 万文档的典型规模。这是绝大多数生产集群最终收敛到的形态:

webserver: replicaCount: 3 api: autoscaling: enabled: true minReplicas: 2 maxReplicas: 6 targetCPUUtilizationPercentage: 70 targetMemoryUtilizationPercentage: null # see Principles # 2 replicas so concurrent connector backfills don't starve each other and # one bad fetch doesn't take out all ingestion. celery_worker_docfetching: replicaCount: 2 # If your document index is in-cluster — working sets at this scale run # 5–6Gi+ (off-heap; keep heap at the default ~4g): opensearch: resources: requests: {cpu: 2000m, memory: 6Gi} limits: {cpu: 4000m, memory: 12Gi} persistence: size: 128Gi # existing PVCs must be expanded manually # Pin to the dedicated index node group if you provisioned one — see the # placement note in the Large section. nodeSelector: eks.amazonaws.com/nodegroup: vespa-node-group tolerations: - key: vespa-dedicated operator: Equal value: "true" effect: NoSchedule

要点拆解:

  • api HPAenabled: true后,replicaCount被 HPA 接管(模板逻辑见 templates/api-deployment.yaml 中的if not .Values.api.autoscaling.enabled分支)。min 2 / max 6、CPU 目标 70%;targetMemoryUtilizationPercentage: null让 HPA 模板不渲染内存指标,避免"空闲 RSS 贴住内存 request 导致 HPA 钉死在 max"的陷阱。
  • celery_worker_docfetching 副本 = 2:文档抓取并发进行时,两个副本互相不饿死;且单个坏连接(bad fetch)不会拖垮全部摄取管道。默认副本为 1,内存默认 request 2Gi / limit 16Gi 保持不动。
  • opensearch:该规模下工作集(working set)达到 5–6 Gi 以上(且是堆外的),容器内存升到 6Gi/12Gi,堆保持默认 ~4g;持久卷从默认 64Gi 扩到 128Gi——注意已有 PVC 不会被升级自动扩容,需要手动扩展;nodeSelector+tolerations将 OpenSearch 钉到专用索引节点组(前提是你真的在 Terraform 里创建了它,见下文 Large 片段说明)。

Large 档:全组织规模与持续 re-index

1,000+ 用户、数百万文档,且经常执行全量 re-index 的场景:

webserver: replicaCount: 3 api: # Generous CPU limit: bursty agent work (deep research, code interpreter) # exhausting the CFS quota stalls /health and causes liveness kills. resources: requests: {cpu: 1000m, memory: 2Gi} limits: {cpu: 4000m, memory: 8Gi} autoscaling: enabled: true minReplicas: 4 maxReplicas: 12 targetCPUUtilizationPercentage: 70 targetMemoryUtilizationPercentage: null # Two embedders with high CPU limits — see Principles on pegged embedders. indexCapability: replicaCount: 2 resources: requests: {cpu: 4000m, memory: 3Gi} limits: {cpu: 12000m, memory: 6Gi} celery_worker_docfetching: replicaCount: 2 celery_worker_docprocessing: replicaCount: 2 resources: requests: {cpu: 500m, memory: 2Gi} limits: {cpu: 1000m, memory: 18Gi} # Metadata-sync throughput: one light worker drains ~800 tasks/min, which # means multi-day backlogs after resyncs of multi-million-doc document sets. celery_worker_light: replicaCount: 3 celery_worker_user_file_processing: replicaCount: 2 resources: requests: {cpu: 500m, memory: 512Mi} limits: {cpu: 2000m, memory: 4Gi} # If your document index is in-cluster: opensearch: resources: requests: {cpu: 2000m, memory: 12Gi} limits: {cpu: 4000m, memory: 16Gi} opensearchJavaOpts: "-Xmx6g -Xms6g" persistence: size: 512Gi # Pin the index to the dedicated document-index node group created by the # terraform module. The toleration only makes the tainted node *eligible* # — the nodeSelector is what actually keeps OpenSearch (and its page # cache) off the general-purpose pool. EKS labels each node with its node # group name automatically; adjust the value if you renamed the group, and # on non-EKS infrastructure label the node yourself and select on that. nodeSelector: eks.amazonaws.com/nodegroup: vespa-node-group tolerations: - key: vespa-dedicated operator: Equal value: "true" effect: NoSchedule

关键设计逻辑:

  • api:保留 1000m/2Gi 的 request,但把 CPU limit 提到 4000m(默认 3000m)、内存 limit 提到 8Gi。原因:deep research、code interpreter 等 agent 型任务的突发负载一旦耗尽 CFS 配额,就会卡住/health并触发 liveness 杀 Pod;HPA 抬到 min 4 / max 12,仍只使用 CPU 目标。
  • indexCapability 副本 = 2、limit 12 CPU:两个 embedder 分摊大型 re-index 的 embedding 压力,且各自持有高 CPU limit,避免长时间顶满限流而饿死 docprocessing 心跳(对应原则 4)。
  • celery_worker_docprocessing:副本 2,内存 limit 从默认 12Gi 抬到 18Gi——文档处理阶段(解析、切块、生成 embedding)是内存大户。
  • celery_worker_light 副本 = 3:元数据同步吞吐的硬数据——单个 light worker 大约每分钟能消化 800 个任务,因此在数百万文档的文档集重同步(resync)后,单副本会导致数天的积压。这条注释直接量化了"为什么需要 3 副本"。
  • celery_worker_user_file_processing 副本 = 2:用户上传文件处理队列,双副本避免单点。
  • opensearch:工作集继续增长,容器内存到 12Gi/16Gi;这次把堆提到-Xmx6g -Xms6g(Xms=Xmx,保持一致);持久卷 512Gi。
  • 节点放置的坑(重要):toleration 只是让 Pod有资格被调度到带vespa-dedicated=true污点的节点;真正把 OpenSearch(连同它的 page cache)挡在通用节点池之外的是nodeSelector。EKS 会自动为每个节点打上节点组名称标签(eks.amazonaws.com/nodegroup),如果你重命名了节点组就同步改这个值;非 EKS 基础设施则需要自己给节点打标签并据此选择。

改用托管文档索引(Managed OpenSearch)

如果使用托管 OpenSearch 域(AWS OpenSearch Service 等),配置方式完全不同:

  • 在 values 中设置opensearch.enabled: false,并在 configMap 中配置OPENSEARCH_HOST指向托管域(values.yaml 中注释说明了这条路径);
  • 跳过上文所有opensearch:——它们只对集群内 StatefulSet 生效;
  • 域的大小改由 Terraform 决定:在onyx模块中设置enable_opensearch = trueopensearch_instance_type/opensearch_instance_count等变量(variables.tf);
  • 此时 Terraform 创建的专用索引节点组(vespa node group)没有东西可跑——把vespa_node_instance_types缩到一个小实例,甚至用vespa_node_enabled = false直接不创建该节点组(见 Terraform README 与 variables.tf)。

如何应用与验证

  1. 创建自己的 values 文件:把上面对应档位的片段合并进my-values.yaml(例如small-values.yaml),不要修改 Chart 自带的 values.yaml。
  2. 部署helm upgrade --install onyx deployment/helm/charts/onyx --namespace onyx -f my-values.yaml(路径按实际仓库位置调整)。
  3. 验证调度可行性:先算 requests 总量再对节点规格——如 small 档约 6.9 vCPU / ~22 GiB requests 对应 8 vCPU / 32 GiB 单节点;medium/large 档则依赖节点组的 min/max 容量。
  4. 观察 HPAkubectl get hpa确认 api-server 按 CPU 在 min/max 间伸缩,且没有因内存指标被钉死。
  5. re-index 前检查:计划大规模批量 re-index 前,确认 indexCapability 的 CPU limit 充足并评估是否加副本,避免触发索引停滞看门狗。

总结

Onyx 的容量规划遵循"Terraform 定基础设施、Chart 定工作负载"的双层模型:先用size档位把 AWS 侧的节点、RDS、Redis、OpenSearch 域配置到位,再用本指南的 values 片段把集群内的工作负载安排进这些节点。四条生产原则(request/limit 分工、api-server 横向扩容、OpenSearch 堆外内存、embedder 限流连锁反应)贯穿始终,是你在默认值之外做任何调优时的判断依据。需要深入源码细节时,可继续阅读 values.yaml(全部默认值与注释)、templates/api-hpa.yaml(HPA 渲染逻辑)以及 deployment/terraform/modules/aws/README.md(基础设施档位明细)。

【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 6:17:17

基于PLC智能网关的智能物料分拣物联网系统

一、方案背景随着电子商务与智能制造的快速发展&#xff0c;物流及生产车间对物料分拣的效率与准确性提出了更高要求。传统的人工分拣方式劳动强度大、错误率高&#xff0c;已难以满足连续大批量的生产需求。某大型物流分拣中心的核心工序——物料自动分拣&#xff0c;长期依赖…

作者头像 李华
网站建设 2026/9/10 6:16:30

SpringBoot+Vue毕业设计系统:可运行、可答辩、可扩展

简介&#xff1a;本资源是一套面向计算机专业本科生的毕业设计完整交付包&#xff0c;聚焦宠物领养业务场景&#xff0c;解决传统人工管理中信息不规范、审核效率低、数据安全性弱等实际问题。系统采用SpringBoot后端Vue前端MySQL数据库的主流技术栈&#xff0c;涵盖用户管理、…

作者头像 李华
网站建设 2026/9/10 6:16:16

ZIP压缩全攻略:从右键创建到命令行、7-Zip进阶与报错排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 6:15:47

打印监控存档为何成为数据泄露重灾区?权限控制与加密基线

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 6:15:40

Qt音视频播放实战:从环境配置到QMediaPlayer核心类

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华