技术岗招聘|开发·运维·测试·数据
24 subscribers
78 photos
52 links
技术岗招聘:开发、测试、运维、数据、安全,国内、海外到岗与远程,每条附岗位解读。招聘总站 @RemoteJobsHubCN · 联系 @BDHT1
Download Telegram
企业 AI 信任栈:OWNS、CALM 与 ORBIT 三层框架

企业 AI 落地失败,往往不是因为战略错误、平台没准备好或执行层出问题,而是组织把这三件事当成三个独立话题,交给三个团队、按三条时间线分别推进。作者 Vibhor Kumar 提出,这三者其实是同一个问题的三个层面:如何构建生产环境中可被信任的 AI 系统。

三个框架分别回答不同层级的问题:
OWNS 是战略决策层,在选型、采购、写 RFP 之前就要回答:谁掌握成本曲线和定价权、组织能否长期支撑该平台、监管与合规风险是否可控、系统能否承载事务、分析、向量检索、RAG 与 agentic 工作负载。
CALM(Changeability、Assurance、Leverage、Measurability)是平台就绪层,评估平台能否在不破坏的前提下演进、能否被有效治理、团队能否并行构建而不产生混乱、领导者能否用证据而非直觉判断平台在变好还是变坏。
ORBIT 是执行层,关注模型做出决策之后的事,围绕五个原则:Outbox First(意图在崩溃后是否存活)、Rate & Shared State(worker 扩缩前是否协调)、Background Is the Unit of Execution(工作是否独立于发起请求而存活)、Idempotency from Day One(重试是否安全)、Trace Everything(决策是否可追溯)。


三层构成递进关系而非菜单:OWNS 是审慎选择,CALM 是负责任地准备,ORBIT 是可靠执行。每层依赖前一层真正做好,失败模式各不相同——有战略无就绪是空想,有就绪无执行是架构表演,有执行无战略是昂贵的复杂度。

对工程团队来说,ORBIT 最贴近日常:丢失的意图、未协调的 worker、不安全的重试、无法解释的决策,这些失败模式应在设计时主动规避,而不是等事故复盘时才被发现。三个框架也可当作诊断工具,某一层的多个「否」答案,说明该层本身需要投入,而不是继续叠加 AI 能力。

#DevOps #运维 #企业AI #AI信任 #平台工程 #架构设计 #SRE #可靠性
@DevOpsTalkCN
PostgreSQL ACE 张晨:为什么敢自称“数据库恢复专家”

成为 PostgreSQL ACE 后,张晨解释了“PostgreSQL 数据库恢复专家”这个头衔的由来,以及 PDU 如何从离线抽取、WAL 挖掘,演进到碎片扫描和无数据字典恢复。

为什么敢自称专家

在西安邮电大学的活动中,张晨被问到“这么年轻怎么敢自称专家”。他的回答是:当你在某个领域相信没人做得比你好,直到有人站出来挑战你,就可以自称专家。目前还没有人在 PostgreSQL 非常规恢复领域质疑他的专业能力,所以他继续使用这个头衔。

PostgreSQL 非常规恢复缺什么

Oracle、MySQL、SQL Server 的恢复都有大量从业者,淘宝一搜一大把。PostgreSQL 非常规恢复则尴尬得多——很多人不知道哪些场景可恢复、哪些不可。网上搜相关场景,多数文章只是工具展示:罗列开源工具,告诉你什么情况试哪个。但准确率呢?可靠性呢?坦率说,没什么可夸的。大多数工具从数据库内核视角设计,很少有人真正考虑用户处境:事故现场实际发生了什么、还剩多少数据、如何判断能否恢复、如何有信心地导出尽可能多的数据。

为什么长期被忽视

主要原因是缺乏商业激励。PostgreSQL 用户既没有 Oracle 用户成熟的付费意愿,也没有 MySQL 在 LAMP 时代积累的海量用户。需求有限,自然缺乏持续投入的动力。张晨 2025 年初进入这个领域时,PostgreSQL 非常规恢复仍依赖社区开源生态的无序生长,没有真正属于它的方法论。

PDU 的演进

PDU 一步步走来:先是离线数据抽取,然后通过 WAL 数据挖掘恢复,最后是碎片扫描恢复和无数据字典恢复。张晨把遇到的案例、犯过的错误、可复用的经验都融入了 PDU。

开源、竞争与真正的壁垒

前两个能力已开源免费供大家使用。这确实会帮助潜在竞争者,但张晨从 PostgreSQL 开源生态受益良多,愿意回馈社区让良性循环继续。当然,自称专家也要留些核心技术在手——他确信在磁盘碎片扫描和无数据字典恢复方面,社区目前没人做得比他好。如果社区外有高手已经掌握这些技能并默默赚钱,他乐意私下交流切磋。


PDU 开源仓库:GitHub

#DevOps #运维 #PostgreSQL #数据库恢复 #PDU #WAL #数据救援 #开源
@DevOpsTalkCN
PostgreSQL 的 integer_datetimes:一个永远为 on 的参数

每个 PostgreSQL 连接在握手时都会收到服务器宣告的 integer_datetimes 参数。自 10.0 起,这个参数只有一个可能的值:on。它是个只读的预设参数,报告日期/时间类型的内部表示方式。

timestamp 和 timestamptz 用 64 位整数存储,从 2000-01-01 午夜起按微秒计数,整个范围内精度都是微秒级。替代方案是双精度浮点,从同一纪元起按秒计数——浮点数和计时是糟糕的组合:精度在纪元附近是微秒级,越远离越差,而且大多数秒的小数部分没有精确的二进制表示,导致算术运算时数值偏移,不同路径计算的 timestamp 做相等比较全靠运气。

整数格式在 7.x 时代作为编译选项引入,8.4 成为默认构建方式,10.0 时 Tom Lane 移除了 --disable-integer-datetimes,成为唯一选项。提交信息说得很直白:复制协议把时间戳字段定义为整数,浮点构建上转换代码有多个 bug,内部浮点泄漏到线上字段,而没人发现说明根本没人跑浮点构建。

那为什么每个客户端还要被告知这个参数?答案是二进制线上格式。文本模式下 timestamp 是字符串,没人关心服务器怎么存;二进制模式下,线上 8 字节就是存储格式——int64 微秒,或曾经的 float8 秒。客户端猜错不会报错,只会得到错误的时间戳。服务器在连接开始时就通过 ParameterStatus 消息声明 integer_datetimes,二进制驱动的解码器据此选择。

旧格式唯一还能咬人的地方是 pg_upgrade:它比较两个集群的 pg_controldata 中 "Date/time type storage" 行,不匹配就拒绝运行。今天构建的集群全是整数格式,幸存下来的浮点构建集群(8.4 前手工编译,或 10.0 前用逃生舱构建)完全无法 pg_upgrade,只能 dump 和 restore。


这个参数没有可设置、可监控的东西。它存在是因为 8.0 协议承诺了它,驱动在解码二进制 timestamp 前仍会检查;移除它会破坏工作正常的客户端,只为省几字节启动流量。所以每次连接仍以服务器郑重宣告一个 2017 年就结束的争论结果开场——答案是 on,而且永远是 on。

#DevOps #运维 #PostgreSQL #数据库 #参数解析 #协议兼容 #pgupgrade
@DevOpsTalkCN
选错分区键,PostgreSQL 分区白做

分区常被当成性能开关:大表一分,慢查询就快了。但有一种情况是,你费劲把大表拆成干净的分区,慢查询却依旧慢。表是分区了,什么都没变好。这时候,问题几乎总出在分区键上。

分区机制本身不难,PostgreSQL 处理得很好。选哪一列做分区键才是关键决策,而且表一大,这个决定基本无法回头。核心就一句话:分区裁剪只在查询过滤分区键时才生效。键选对了,PostgreSQL 只读一个小分区;选错了,它照样读全表,只不过现在是读散落在众多子表里的全表,可能比原来那张大表还慢。

所以真正的问题不是"该不该分区",而是"我的重要查询过滤什么列,能不能按它分区"。提交前快速自查:拉出表上最频繁、最昂贵的十条查询,看 WHERE 子句。如果几乎都过滤同一列或同一小组列,那就是候选键;如果过滤十种不同列,分区只会帮到其中一部分查询,对其他的毫无作用。

Hash 分区是重灾区。它的卖点是均匀分布:取一个多值的列做 hash,PostgreSQL 把行分散到固定数量的分区。但关键不是不同值的数量,而是行在这些值上的分布。多租户 SaaS 表里可能有几百个租户,看着分布很好,但真实客户群是倾斜的——少数大租户产生大部分行。Hash 按值分布,不按数据量分布,于是几个大租户被 hash 进两三个分区,堆了 80% 的数据,其余分区几乎空着。你做了分区的工作,却保留了本想消除的热点。

Hash 只在键天然均匀时是好工具:UUID 主键、无业务含义的代理 ID、真正均匀分布的客户 ID。在倾斜列上,它只分散了标签,没分散负载。

修正倾斜键的办法不是更聪明的 hash,而是选一个与表实际查询方式、数据增长方式对齐的键。两种模式覆盖大部分真实场景:无自然顺序的均匀分布用 hash 均匀键;按时间查询、随时间增长的表用 range 时间戳分区。时间序列和事件负载里,按时间 range 分区还能让老化数据变成廉价的分区删除,而不是一次 I/O 密集的 DELETE。

分区键不是普通调优旋钮,而是 schema 承诺。加一个新 range 分区很容易,可以用 pg_partman 建规则或计划。但改 hash 分区数量是另一回事:模数(hash 桶数量)决定了每个现有行的位置,改了就得重排所有行,意味着复制整张表,通常要停机或做复杂的在线迁移。换分区列更是整表重建。表小的时候便宜,等它攒了几十亿行再改就痛苦了——而这恰恰是最需要分区正确的时候。

提交前过一遍清单:确认前十查询过滤你计划分区的列;检查候选键上的实际数据分布,别只看不同值数量;按访问模式匹配策略——均匀键用 hash,时间驱动用 range,小固定类别集用 list;在数据量有代表性的生产环境副本上测试,一万行的行为说明不了十亿行的行为;分区数量控制在几十到几百个,几千个小分区会带来自己的规划器和维护开销。


键选对了,换来的是几年的余量:查询快、归档便宜、能一个分区一个分区地做维护。选错了,换来一次迁移。好在这是可判断的决策,不是猜——工作负载告诉你键,数据分布告诉你策略,真实数据量的测试告诉你对不对,而且是在表还小、答案还便宜的时候。
@DevOpsTalkCN
把 SageMaker HyperPod 集群接入 AWS DevOps Agent 做自动故障排查

大规模 ML 训练集群动辄数百上千 GPU 实例、跑上数天甚至数周,硬件故障、节点生命周期变化、容量波动、负载异常会全天候涌进事件流。HyperPod 自带的自愈层能自动检测并替换故障 GPU,但配置错误、容量等待、重复硬件故障、Pod 卡 CrashLoopBackOff 这类情况仍需要人判断。AWS DevOps Agent 能以只读方式接入集群事件流,自动完成分类、根因分析和结论邮件通知。

这套方案通过 CloudFormation 一键部署,事件驱动和定时巡检两条路径并行:EventBridge 接收 HyperPod 集群事件,webhook bridge Lambda 过滤噪声后签名推送;另有每 15 分钟一次的 Kubernetes 状态审计,只在发现真实问题时才触发。DevOps Agent 通过两个自定义 skill 学习 HyperPod 运维模型,输出 Monitor(恢复中)、Escalate(需人工介入)、Resolved(已自动恢复)三类结论邮件。

关键设计是只读边界:Agent 不授予 SSM、SSH 或任何对集群的写权限,所有修复动作仍由 HyperPod 自愈层或运维人员执行,爆炸半径为零。邮件结论会附上事件时间线和根因分析,例如 GPU NVLink 故障、生命周期脚本启动失败、容量不足等典型场景。检测条件可通过修改定时审计 Lambda 扩展,Agent 的推理逻辑则用纯英文 skill 文件调整,无需改代码。


对运维团队来说,这套方案解决的是"半夜被事件流淹没"的问题——常规硬件故障交给 HyperPod 自愈,需要人决策的异常由 Agent 自动归类并给出建议,邮件通知替代 7×24 盯屏。部署前提是集群已接入 EventBridge,且愿意维护一套 CloudFormation 模板和两个 skill 文件。

#DevOps #运维 #AWS #SageMakerHyperPod #DevOpsAgent #EventBridge #CloudFormation #Kubernetes #EKS #故障排查
@DevOpsTalkCN
把团队知识库接进 IDE:Kiro 用 MCP 连 Bedrock Knowledge Bases

开发时查架构决策记录、API 规范或编码标准,通常要切到 wiki 搜半天,再切回编辑器改代码,一次上下文切换就是十几分钟。Kiro 这个 agentic IDE 通过 MCP 协议把 Amazon Bedrock Knowledge Bases 接进编辑器,让开发者直接用自然语言查团队文档,答案带引用来源。

这套方案解决四个具体问题:上下文切换(不用离开编辑器查文档)、知识碎片化(文档散落多个系统)、新人生效慢(熟悉文档结构要几天)、合规滞后(代码评审时才暴露规范违反)。

实现上,官方 awslabs.bedrock-kb-retrieval-mcp-server 做桥接:Kiro 通过 MCP 连本地子进程,服务端调用 Bedrock Knowledge Bases 的 Retrieve API(不是 RetrieveAndGenerate),用 Titan Text Embeddings v2 做向量检索,返回带引用的段落。

已有 Knowledge Base 的团队不用重建,给现有 KB 打上 mcp-multirag-kb=true 标签,MCP 服务器会自动发现,多个 KB(API 文档、架构决策、runbook)可以一起打标,Kiro 跨库查询。从零开始的话,示例仓库提供完整 AWS CDK 应用,一键部署 S3 存储桶、OpenSearch Serverless 向量库和 Bedrock Knowledge Base,几分钟搞定。

典型场景:问"我们的错误处理模式是什么"直接返回团队定的异常类结构;问"Orders API 要什么认证"直接给出 OpenAPI spec 里的 JWT scope 和限流要求;还能在 CI/CD 里用 Kiro CLI 跑无头查询,PR 评审时自动校验代码是否符合安全规范。


Kiro 自带的 Steering 文件(静态项目规则)和 Agent Skills(工作流指引)管行为,Knowledge Bases 存组织知识,MCP 是连接层——三者分工不同,这套方案是互补不是替代。适合文档量大、靠人记不住的团队。

#DevOps #运维 #Kiro #MCP #Bedrock #KnowledgeBases #RAG #Amazon #IDE #向量检索
@DevOpsTalkCN
KubeCon 北美 2026 议程公布,新增 AI 推理与 Agent 专场

KubeCon + CloudNativeCon 北美 2026 将于 11 月 9-12 日在盐湖城举行,完整议程已上线。今年新增 AI Inference + Agentic 专场,聚焦 Kubernetes 上的 AI 推理、Agent 工作流、GPU 调度、模型服务与生产级 AI 可观测性,涉及 vLLM、KServe、Ray 和 OpenTelemetry 等项目。

平台工程专场关注内部开发者平台、自助服务与自动化实践;安全专场覆盖供应链安全、身份与运行时防护、漏洞管理和策略执行。CNCF 调查显示,82% 的容器用户在生产环境运行 Kubernetes,66% 使用生成式 AI 的组织依赖它。CNCF 执行董事 Jonathan Bryce 表示,从训练模型转向生产运行是当前真正的工程挑战。

值得关注的议程亮点:
• 专场演讲:Kubernetes Solutions for Agent-Shaped Problems(Google 的 Tim Hockin 与 Dmitry Berkovich)
• 平台工程:How EarnIn Brought Testing to the Full CNCF Stack(EarnIn 的 Priya Namasivayam)
• 安全:Gone in 60 Minutes: Effectively Close the Exploitable Window with Detection as Code(ARMO 与 fusioncore.ai)
• 11 月 9 日联合活动:ArgoCon、BackstageCon、Cloud Native AI + Inference Day、CiliumCon、WasmCon


标准注册截止 9 月 2 日;Dan Kohn 奖学金提供免费注册或差旅资助,差旅申请截止 9 月 13 日,注册奖学金申请截止 10 月 4 日。

#DevOps #运维 #KubeCon #CNCF #Kubernetes #AI推理 #Agent #平台工程 #云原生安全 #vLLM #KServe #OpenTelemetry #eBPF #Cilium #Argo #Backstage
@DevOpsTalkCN
LFX 导师计划:从写文档到上手部署可观测系统

一位前端工程师加入 LFX 导师计划,原以为只是写三个月文档,结果几周后就在 AWS EC2 上部署 OpenTelemetry Collector、排查机器间网络问题、定位看似健康却不出指标的管道。这段经历让他从零基础接触可观测性,到独立构建和排障系统。

他部署的系统架构是:多个 EC2 实例跑 Django 应用,每个应用旁部署 OpenTelemetry Collector,另有一台专用 EC2 跑 Prometheus 作为指标后端,所有实例以 Prometheus 格式导出指标。

最大的挑战不在单个工具,而在组件间的交互:EC2 因网络限制无法互通、Collector 运行但不导出数据、管道静默丢弃遥测、本地正常但 AWS 部署失败。多数故障是"沉默"的——指标缺失、管道断裂、服务看似健康实则不可达。

导师制核心是自主性:导师给方向和反馈,但不替学员解决问题。讨论方案背后的推理过程比方案本身更有价值。一次测试平台无法自动化部署且有时限,团队讨论后改用替代方案并成功。


这段经历最大的转变不是学会某个工具,而是理解系统是必须被设计成能扛住故障的管道。
产出:
• 合并进 OpenTelemetry 文档的改进
• Prometheus 与 OpenTelemetry 互操作文档
• 非 Kubernetes 环境可观测性部署的蓝图提案

#DevOps #运维 #LFX #CNCF #OpenTelemetry #Prometheus #可观测性 #AWS #EC2 #导师计划
@DevOpsTalkCN
Postgres 多租户 BYOK 列加密:用 pgcrypto 实现客户自管密钥

B2B SaaS 场景下,多租户共享表结构,部分敏感列需要按租户加密。仅靠磁盘加密不够——客户要求自带密钥(BYOK),即使整个数据库泄露,只要客户侧密钥不泄露,敏感数据仍然安全。本文用 pgcrypto 演示了按组织维度做列级加密的完整方案。

设计约束很明确:所有组织共用表,行按 organization_id 归属;敏感列按组织用各自密钥加密;密钥存放在 AWS KMS,应用在查询时获取,数据库本身不持有密钥;非 BYOK 租户走同一套代码路径。方案采用信封加密:KMS 持有每组织的 KEK(客户自有、可吊销),应用在内存中短暂持有 DEK,DEK 由 KEK 加密后存于 KMS,使用时调用 KMS Decrypt 解包后直接传入查询。KMS 看不到数据,Postgres 只在查询执行期间接触 DEK,明文 DEK 仅存在于应用内存、随请求生命周期结束。

演示 schema 中,organizations.kms_key_arn 标识组织是否启用 BYOK,orders.secret 存 BYOK 行的密文,非 BYOK 行存明文做对比。生产环境建议列一律存密文,非 BYOK 租户用平台托管密钥。

读取模式分两种:单组织查询是常见路径,应用从 KMS 解包 DEK 后传入查询,每请求一次 KMS 调用(缓存 DEK 则每会话一次),是性能最优的 fast path;跨组织混合查询(管理视图、分析任务)可用 CTE 携带多个密钥,LEFT JOIN 让非 BYOK 行自然落入 kms_key_arn IS NULL 分支。

错误密钥行为值得注意:pgp_sym_decrypt 用错密钥会直接抛错而非返回乱码,这是 PGP 格式自带完整性校验的特性,不会静默返回错误数据。


生产落地有几个关键细节:DEK 必须作为绑定参数传入,绝不能拼进 SQL 文本,否则可能泄露到日志、trace 或会话元数据;加密状态应记录在行级别而非依赖组织当前 BYOK 设置,因为租户可能后续启用、停用或轮换密钥;非 BYOK 组织也要分配平台托管 DEK,保证敏感列始终以密文存储;密钥轮换要提前规划,租户换密钥时旧行需要明确处理方案;性能影响需实测,尽量只加密真正敏感的列。

PostgreSQL 自带 pgcrypto 扩展足以支撑多租户敏感数据的按租户加密,无需引入额外加密服务。

#DevOps #运维 #PostgreSQL #pgcrypto #BYOK #AWSKMS #数据加密 #多租户
@DevOpsTalkCN
AI 让漏洞发现变快,响应计划必须跟上

漏洞发现的速度已经超过团队修复能力,CVE 目录也跟不上 AI 的发现量。M-Trends 报告估计平均利用时间已到负七天,意味着利用先于补丁出现。响应和修复时间必须压缩,风险接受也变得更难向董事会和审计解释。

对任何代码库而言,这是激增而非无尽洪流。代码有限,AI 发现的漏洞大多属于已知类别、有已知修复方式。难点不在漏洞有多罕见,而在数量。

四步计划:扫描、排序、修复、兜底

扫描阶段要把所有发现汇入一处管理。CVE 发现是常规部分,新工作在于非 CVE 发现——扫描需纳入 CVE 目录之外的漏洞数据,包括 AI 发现的缺陷,并接入同一套处理和修复流程。只管理 CVE 的工具对这一类新发现是盲的。

排序阶段有三个关键信号:漏洞包是否实际加载进内存运行、能否被网络访问或暴露触达、资产被攻破是否有真实业务影响。前两个只能在线上环境测量。团队应聚焦分析产出的短清单,并信任辅助排序的工具——降级处理是主动决策,只有团队信任过滤器才站得住。

修复阶段不能手工逐个处理。在根上修:补一次基础镜像,而不是修补每个实例。自动化所有权和分派,让发现自动路由到对应团队。能用自动修复就用,生成的 PR 和配置变更能提升修复吞吐。在生产前拦截:不需要上线的就在准入控制器或流水线里挡住。还要熟悉其他杠杆——切断易受攻击工作负载的网络访问也是修复,往往比等补丁快。组织层面需要真正把这件事排上优先级,用业务驱动的指标争取支持。

最后为漏洞被利用做计划。修不完的,运行时是安全网。利用后的行为无论入口多新颖都相似:提权、侦察、取密钥。不必识别利用本身,抓住利用与业务影响之间的窗口就能保护组织。实践中要监控工作负载的失陷指标,测量检测和响应速度并找出瓶颈,用 AI 代理处理过多告警或夜间覆盖不足,把响应推到离数据源更近的位置,提前建好遏制剧本、升级路径和业务通知流程。人手或技能不足时,用服务商或 agentic SOC 工具补充。


发现已经规模化,响应也必须跟上。
@DevOpsTalkCN
IntervalStyle:改的是解析,不只是输出格式

PostgreSQL 的 IntervalStyle 参数常被当成纯输出格式偏好,但它同样改变 interval 的输入解析方式。默认值是 postgres,上下文为 user,自 8.4 起随 interval 输入输出重构引入。四种风格中,sql_standard 和 iso_8601 各藏一个坑。

sql_standard 会悄悄翻转数据符号

SQL 标准要求 interval 每个字段同号,前导负号作用于整个值;而 PostgreSQL 传统上各字段独立符号。IntervalStyle 决定歧义字面量按哪套规则解析:

```
SET IntervalStyle = 'postgres';
SELECT extract(epoch from interval '-1 2:03:04');
-- -79016(负一天,加 2:03:04)

SET IntervalStyle = 'sql_standard';
SELECT extract(epoch from interval '-1 2:03:04');
-- -93784(负一天,减 2:03:04)
```

同一字面量,两种结果,相差四小时多。sql_standard 是四种风格里唯一改变输入含义的,且恰好命中人们随手写的写法。防御办法:负 interval 的每个字段都显式加符号,'-1 days -2:03:04' 在任何设置下含义一致。

iso_8601 的坑在输出端

对混合符号 interval,PostgreSQL 输出负号设计符,如 P-1Y-2M3DT-4H-5M-6S。基础 ISO 8601 没有负时长(带符号时长是 8601-2:2019 的扩展),严格解析器会拒绝这种输出。interval 可能为负时,切到 iso_8601 并不能换来互操作性。

改风格影响所有文本协议客户端

大多数驱动默认走文本格式返回结果,interval 列以字符串到达,驱动用写死的代码解析——几乎都只认 postgres 风格。node-postgres 的解析器只懂 postgres 风格,文档明确要求改过就改回来。按库或按角色设 iso_8601 让某个 API 端点好看,其他所有读 interval 的客户端会在没人动过的代码里解析出错。(二进制格式不受影响,风格只存在于文本表示。)


建议

服务端保持 postgres,把它当会话级参数用。导出或 API 需要 ISO 8601 时长时,在产生数据的事务里 SET LOCAL IntervalStyle = 'iso_8601',或在应用层格式化。sql_standard 绝不要设到比会话更广的范围——它改的是输入含义,不只是输出长相。负 interval 每个字段都写符号,不发送歧义数据,任何设置都无法曲解它。

#DevOps #运维 #PostgreSQL #IntervalStyle #数据库 #参数调优
@DevOpsTalkCN
独立部署让测试失真,开源工具如何用观测替代手工维护

微服务独立部署让集成测试的 mock 数据快速过期,测试可能通过,但验证的却是几个月前的旧行为。这不是代码质量问题,而是覆盖时效性问题——测试写得好,但测错了对象。

20 个服务、每个每周部署两次,生产环境每周产生 40 次潜在的 mock 失效事件。上游加个字段、改个错误码、调整认证头,下游 mock 就悄悄失真,没有任何可见信号。靠平台团队手工追踪每个上游部署并更新 mock,在交付压力下必然失效。这是结构性问题,需要结构性解法。

传统工具如 Testcontainers、WireMock、Pact 都很有价值,但共同局限是:行为假设在某个时间点编码后就开始老化。观测式工具则从实时行为中推导假设,跑一次捕获会话就能同时刷新所有集成测试假设,维护成本不再与上游部署频率成正比。

三种开源工具的实现路径差异明显:

Keploy 用 eBPF 捕获真实流量,直接解决独立部署的时效问题,最贴近生产行为。

Microcks 可导入真实 API 流量,适合已有流量记录的团队。

VCR 系(go-vcr、VCR.py)录制真实 HTTP 响应供回放,实现简单但需注意录制内容的时效管理。

在 CI/CD 中定时刷新 fixture,能让集成测试跟上频繁变更的微服务。建议平台团队先从少数高风险集成边界试点,再逐步推广到全架构。


对线上环境的意义:如果你们正被"测试全绿但上线就炸"困扰,且服务数量已多到手工维护 mock 跟不上节奏,观测式测试值得试点。从两三个关键依赖边界开始,用真实流量替代手工假设,能显著减少因 mock 过期导致的线上事故。

#DevOps #运维 #云原生 #微服务 #集成测试 #Keploy #Microcks #Pact #WireMock #Testcontainers #eBPF #CICD
@DevOpsTalkCN
别把 GPU 当 Web Pod 调度

Kubernetes 默认把 GPU 当成不透明的整数资源来调度,一个 Pod 独占整卡,但推理负载往往只用掉十几到三十几个百分点的算力。集群看起来排满了,账单却按整卡在涨——"已调度"和"已利用"之间的落差,就是云原生 AI 预算悄悄漏掉的地方。问题不在 GPU 贵,而在拿无状态 Web 服务的默认模式去套最贵、最不可替代的计算单元。

共享一张卡,有三种不同工具

- 时间切片(time-slicing):纯软件方案,驱动按毫秒级轮转上下文,几乎支持所有 NVIDIA 卡,ConfigMap 即可开启。但没有内存、故障隔离,也没有算力保证,适合开发、笔记本和低优先级突发推理。
- MPS:多进程上下文复用,内核在不同 SM 上并发执行,吞吐和延迟优于时间切片,但同样无内存隔离,故障隔离弱,一个客户端崩溃可能拖垮邻居。
- MIG:硬件级分区,单卡最多 7 个隔离实例,各自独立内存、算力和故障域。需要 Ampere 或更新架构(A100/H100 等),T4/V100 不支持。配置静态、需提前规划,适合不可信租户或需要可预测 QoS 的场景。

配置 MIG 切片后,调度器终于能按资源属性而非整数计数来分配,例如 nvidia.com/mig-1g.5gb: "1" 表示申请一个 5GB 的 MIG 切片而非整卡,四副本可共享一张物理卡。

更长期的方案是动态资源分配(DRA)。Kubernetes v1.34(2025 年 9 月发布)中 DRA 核心框架 GA,调度器首次能原生表达"要一个具备这些属性的设备"而非整数。但注意:框架虽稳定,细粒度共享能力(可消费容量、扩展资源映射)在该版本仍是 alpha 或 beta,DRA 方向正确,但还不能完全替代 device plugin。


按因果信号扩缩容,别盯 CPU

GPU 推理 Pod 里 CPU 是去相关代理——加速器干重活,CPU 只做 tokenize、HTTP 和批处理。CPU 30% 时 GPU 可能已 100%、KV cache 打满、请求在队列堆积,HPA 却读着"健康"无动于衷。应改用因果信号:队列深度是领先指标,GPU 利用率(DCGM exporter 采集到 Prometheus)是同步护栏。KEDA 是标准机制,因为信号在 Pod cgroup 之外、HPA 够不着,且它能缩到零。用 backlog 决定副本数,用 GPU 百分比做上限。教程里抄来的 5% 阈值只是演示值,真实 serving 应看 70–80%。

冷启动税,没人提前算

共享和 scale-to-zero 的代价是冷启动——LLM 冷启动不是容器重启,多 GB 权重要加载进 VRAM,从本地 NVMe 读大模型可能耗时数十秒,还没算 CUDA graph capture。此时别急着上 lazy-pull 镜像快照:推理负载启动几秒内就要读几乎整个镜像(CUDA 库和权重),按需拉取只是把卡顿从拉取挪到首次推理。AWS 给 EKS 推的"并行"拉取模式就是承认这点——更快的全量下载,而非懒加载。结构性解法是停止把模型权重塞进容器镜像,并维持一个小的热基线,减少启动延迟和 GPU 浪费。

#DevOps #运维 #Kubernetes #GPU #NVIDIA #MIG #DRA #KEDA #LLM #云原生
@DevOpsTalkCN
Kubernetes 按整卡调度 GPU,LLM 推理吃大亏

Kubernetes 默认把 GPU 当整数资源调度:Pod 申请 nvidia.com/gpu: 1 就独占整卡,哪怕模型只用了一小块显存。实测中八卡节点每张卡都显示 Allocated 1/1,利用率却只有 10% 左右——7B 模型在 80GB 显存里只用了约六分之一。这不是调参问题,是资源模型的问题:调度器只数卡,不知道你的模型需要 14GB 而卡有 80GB,也不知道两个 Pod 本可共存。

单纯开自动扩缩容只会把浪费线性放大。HPA 能拉起更多整卡 Pod,Karpenter 能拉起更多整卡节点,但装箱的容器形状就是错的。

三种共享单卡的方式,差别很大

NVIDIA GPU Operator 提供三种机制,选错要么损失吞吐、要么让租户互相影响:

• 时间切片(time-slicing):纯软件,驱动按毫秒级轮转上下文切换。几乎支持所有 NVIDIA GPU(T4/V100/L40S/A100/H100),用 ConfigMap 配 replicas: N 即可让一张卡变成四张。代价:无内存隔离、无故障隔离、无算力保证,一个 Pod OOM 可能拖垮整卡。适合笔记本、开发环境、低优先级突发推理。

• MPS:CUDA MPS 服务端多路复用进程上下文,内核在不同 SM 上"并发"跑,延迟更低、利用率更高。但依然没有内存隔离,故障隔离较弱,且是三者中在 Kubernetes 里最不成熟的。适合你掌控所有租户、追求吞吐的场景。

• MIG:唯一硬件级分区,把一张卡切成最多 7 个隔离实例,各自有独立显存、SM 和故障域。真正的隔离——租户在自己的切片里崩溃不影响整卡。代价:仅 Ampere 及更新架构(A100/H100/H200/B 系列,T4/V100 不行),且 profile 是静态的,重配置要排空 GPU。GPU Operator 配 mig.strategy=mixed 后,MIG 实例以 nvidia.com/mig-1g.5gb 这类完整资源名暴露,Pod 可以直接按名申请切片。

LLM 推理 Pod 应按有状态对待

权重加载是没人预算的隐性成本:典型冷启动要 60–120 秒,140GB BF16 模型从本地 NVMe 加载到 H100 约 40–50 秒,再加 25–30 秒 CUDA graph 捕获——本地盘加载就超一分钟,还没算拉镜像。所以 minReplicas: 0 意味着每次流量恢复都要付这笔延迟。

KServe 的 InferenceService 可以同时解决两件事:用 MIG 切片共享硅片,把权重加载当状态水合而非廉价重启。把 nvidia.com/gpu: "1" 换成 nvidia.com/mig-1g.5gb: "1" 就能从独占 80GB H100 变成让六个租户共享同一张卡;storageUri: "pvc://model-cache/..." 用节点本地缓存缩短权重加载,initialDelaySeconds: 60 避免权重没加载完就被标记 Ready。


核心教训:别再把整张昂贵 GPU 自动分配给只需要一小块的负载。Kubernetes 的 Dynamic Resource Allocation(DRA)提供了更细粒度的设备感知调度方式,值得关注。

#DevOps #运维 #Kubernetes #GPU #NVIDIA #MIG #MPS #LLM #KServe #DRA
@DevOpsTalkCN
Dragonfly 轻量部署:去掉 Manager 和数据库,一条 Helm 命令搞定镜像分发

Dragonfly 用 P2P 加速文件与容器镜像分发,但标准安装要部署 Scheduler、Seed Client、Client 之外,还得有 Manager 做动态配置,背后挂 MySQL 和 Redis。对单集群、只想解决镜像拉取时 registry 过载的场景,这套太重了。

轻量部署模式去掉了 Manager、MySQL 和 Redis,Scheduler 作为唯一协调组件,整个安装用一条 Helm 命令完成。本文讲清轻量架构怎么运作,并在本地 kind 集群里跑通。

传统部署里 Manager 是控制面,提供 Web 控制台、OpenAPI 集成(如 registry 触发的预热)、多 P2P 集群管理,并把动态配置分发给 Scheduler 和 Client,状态存 MySQL,Redis 做缓存和异步任务分发。单集群只做 P2P 分发时,真正需要的其实只有动态配置——也就是 YAML 里的调度限制、黑名单、Client 发现 Scheduler 的端点。去掉 Manager 地址后,Scheduler 和 Client 可以脱离数据库后端独立运行。

轻量部署用两个原生 Kubernetes 原语替代 Manager:ConfigMap 和 headless Service。manager.addr 未设置时,Scheduler 和 Client 从本地 /etc/dragonfly/dynconfig.yaml 加载动态配置,该文件由 Helm chart 通过 ConfigMap 挂载;文件不存在则启动时生成默认值。Scheduler 的 dynconfig.yaml 定义集群级调度参数,比如 seed peer 并发上传上限 loadLimit: 2000、候选父节点数 candidateParentLimit: 3、过滤父节点数 filterParentLimit: 15、peer 并发上传上限 loadLimit: 200。配置按 refreshInterval(默认一分钟)周期性重载,ConfigMap 更新后无需重启 Pod 即可生效,这些参数也暴露为 Helm values(scheduler.dynconfig、seedClient.dynconfig、client.dynconfig),保持声明式、GitOps 对齐。

Client 发现 Scheduler 的方式也变了:Manager 模式下 Client 查 Manager 找 Scheduler,轻量模式下 Client 的 dynconfig.yaml 直接指向 Scheduler 的 headless Service 地址(dragonfly-scheduler.dragonfly-system.svc.cluster.local:8002),dfdaemon 进程通过 DNS 解析出所有 Scheduler Pod IP,逐个健康检查并过滤不健康实例。Scheduler StatefulSet 扩缩容后,Client 自动通过 DNS 发现新端点。Scheduler 跑在静态 IP(如集群外)时,可用 scheduler.addrs 显式定义列表,非空时优先于 addr。

集群内落地三个工作负载:Scheduler(StatefulSet)协调跨 peer 的任务调度和分片分发;Seed Client(StatefulSet)作为 P2P 网络根 peer,直接从源仓库下载内容;Client(DaemonSet)跑在每个节点,dfinit 配置 containerd 把镜像拉取路由到本地 peer client。这套架构升级时无需数据库备份或迁移脚本,状态存在本地磁盘缓存,可按需从源重建。


三种部署模式对比:轻量部署只装 Scheduler、Seed Client、Client,适合单集群、边缘或 CI/CD 管道;轻量 + Redis(scheduler.database.redis.addrs)支持持久化任务和缓存元数据保留;带 Manager 的完整部署提供 Web 控制台、OpenAPI、多集群管理和 API 触发的预热。功能差异上,黑名单、任务分发、dfctl 预热三种模式都支持;持久化任务和持久化缓存任务需要 Redis;OpenAPI 预热、Web 控制台、OpenAPI 集成、个人访问令牌只有 Manager 模式才有。Helm chart 默认禁用 Manager、MySQL 和 Redis,轻量部署就是默认基线。

kind 集群跑通步骤:先建多节点集群(一个 control-plane 加两个 worker),预拉 dragonflyoss/scheduler、client、dfinit 三个镜像并 load 进 kind 节点,再写 charts-config.yaml 配置镜像和 metrics,dfinit 开启并指向 containerd 配置路径、proxyAllRegistries 设为 true,最后 helm repo add dragonfly 后 helm install 部署,验证四个 Pod 启动成功(每 worker 节点一个 Client、一个 Scheduler、一个 Seed Client)。

对单集群或边缘场景,这套轻量部署把组件砍到最少,升级不用管数据库,配置走 ConfigMap 热更新,值得一试。

#DevOps #运维 #Dragonfly #P2P #Kubernetes #Helm #镜像分发 #CNCF #containerd
@DevOpsTalkCN