<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>项目 on 孙恒 · SRE / 数据基础设施</title><link>https://humeie.com/projects/</link><description>Recent content in 项目 on 孙恒 · SRE / 数据基础设施</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Mon, 20 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://humeie.com/projects/index.xml" rel="self" type="application/rss+xml"/><item><title>把手游发布从 1.5 小时压到 30 分钟</title><link>https://humeie.com/projects/release-pipeline-mcgg/</link><pubDate>Mon, 20 Jul 2026 00:00:00 +0000</pubDate><guid>https://humeie.com/projects/release-pipeline-mcgg/</guid><description>&lt;h2 id="问题"&gt;问题&lt;/h2&gt;
&lt;p&gt;《魔法战旗》海外服和《决胜巅峰》国服的一次常规发布要占掉 1.5 小时。最初的判断是构建和分发慢，但把每个阶段的耗时拆出来之后，结论反了：&lt;/p&gt;
&lt;p&gt;真正的时间都花在&lt;strong&gt;串行的人工确认&lt;/strong&gt;上。发布是分批次的，每批之间要等人工核对上一批的监控指标是否正常，确认了才敢继续。核对本身只要几分钟，但等人从别的事情里切回来、打开几个看板、逐个确认，中间的空档累积起来比所有机器操作的总和还长。&lt;/p&gt;
&lt;p&gt;这是一个典型的「优化错了对象」的陷阱——如果按最初的判断去优化构建速度，就算把构建做到零耗时，总时长也只能降到一小时出头。&lt;/p&gt;
&lt;h2 id="做法"&gt;做法&lt;/h2&gt;
&lt;p&gt;思路是&lt;strong&gt;把人工确认变成机器判定，人只在判定不通过时介入&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一步：把「正常」写成可执行的判定条件。&lt;/strong&gt;
原来的核对是经验性的——老手看一眼看板就知道对不对。要自动化，就得先把这份经验落成明确的指标阈值和判定逻辑：哪几个指标、看哪个时间窗、超过多少算异常、哪些波动是发布本身必然带来的正常抖动。这一步花的时间最长，也最容易被低估：它本质上是在给一群人的隐性判断做知识提取。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二步：批次间的等待改成自动观测窗口。&lt;/strong&gt;
每批发布完成后自动进入固定时长的观测期，期间持续拉取判定指标。全绿则自动继续下一批，任一条不满足则暂停并推送告警，附带具体是哪条指标、当前值、阈值。人被叫来的时候看到的是结论，不是一堆看板。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三步：把回滚也做成一条命令。&lt;/strong&gt;
自动化推进的前提是出错时能快速退回。回滚路径不可靠的话，没人敢让流程自己往下走——这一点比自动化本身更影响推进意愿。&lt;/p&gt;
&lt;h2 id="结果"&gt;结果&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;单次发布耗时从 1.5 小时降到 30 分钟。&lt;/li&gt;
&lt;li&gt;发布窗口不再必须占用一个完整的人力时段，值班同学可以并行处理别的事。&lt;/li&gt;
&lt;li&gt;判定条件被写成了配置，新项目接入时是填表而不是重新攒经验。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="事后看值得记下来的"&gt;事后看，值得记下来的&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;「慢」的归因经常是错的。&lt;/strong&gt; 大家凭直觉认为是机器慢，因为机器耗时是可见的、有日志的；人工等待是不可见的，没有人记录「我什么时候被叫来的」和「我什么时候真正开始看的」。要先把不可见的部分量化出来，才谈得上优化。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;自动化的阻力不在技术，在信任。&lt;/strong&gt; 判定逻辑写好之后，还跑了一段时间的「影子模式」——机器给判定，人照旧手工确认，两边比对。跑到人发现机器的判定和自己一致，才愿意把控制权交出去。这段并行成本是必要的，跳过它换来的是流程上线后没人敢用。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;隐性经验的显式化，本身就是交付物。&lt;/strong&gt; 阈值和判定逻辑写下来之后，价值不只是给自动化用——新人 onboarding 时不用再靠师傅带着看看板了。&lt;/p&gt;</description></item><item><title>端游云原生化改造：500 万/年成本是怎么省下来的</title><link>https://humeie.com/projects/cloud-native-lol/</link><pubDate>Fri, 10 Jul 2026 00:00:00 +0000</pubDate><guid>https://humeie.com/projects/cloud-native-lol/</guid><description>&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;p&gt;英雄联盟端游和无畏契约的服务端原本跑在虚拟机上，扩缩容靠工单，发布靠脚本。往云原生迁的动机有两个：一是弹性——游戏的负载曲线有极强的日周期和活动尖峰，固定容量意味着按峰值付费；二是交付效率——发布和回滚的流程需要标准化。&lt;/p&gt;
&lt;h2 id="成本这一块钱从哪省的"&gt;成本这一块，钱从哪省的&lt;/h2&gt;
&lt;p&gt;先说结论：&lt;strong&gt;500 万/年里的绝大部分来自纠正规格错配和回收闲置，不是靠削减业务申请的资源。&lt;/strong&gt; 这个区别很重要，因为「一刀切砍 requests」这种做法能在报表上立刻见效，但会把成本问题转化成稳定性问题，最后一次事故就赔回去了。&lt;/p&gt;
&lt;p&gt;拆开来看：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;规格错配。&lt;/strong&gt; 迁移前的资源申请普遍是按「上次出问题时的峰值 × 安全系数」估的，且一旦申请下来就不再回收。实际观测下来，相当一部分服务的 CPU 长期跑在申请量的很低区间，但内存却贴着上限——说明它需要的是内存型规格，却申请了计算型。换规格比缩容量安全得多：业务拿到的内存没少，只是不再为用不上的 CPU 付钱。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;闲置识别。&lt;/strong&gt; 有一类资源是「上线时申请、下线时忘记回收」。这类没有任何风险，纯粹是流程漏洞。做法是把资源和业务负载做关联，长期无流量、无请求、无变更的资源自动进入回收流程——先通知责任人，过期无响应再回收，保留一段时间的可恢复窗口。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;弹性机会。&lt;/strong&gt; 有清晰日周期的服务改成按时段伸缩。这里的关键是&lt;strong&gt;伸缩要保守、扩要激进&lt;/strong&gt;——扩容慢一点会掉用户，缩容慢一点只是多花点钱。两边的代价不对称，策略就不该对称。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;计费方式。&lt;/strong&gt; 长期稳定的基线负载用包年包月覆盖，波动部分用按量。这一项不改变任何技术配置，纯粹是采购结构调整，风险最低但也最容易被忽略——因为它不属于任何技术团队的 KPI。&lt;/p&gt;
&lt;h2 id="稳定性提升-60-是怎么来的"&gt;稳定性提升 60% 是怎么来的&lt;/h2&gt;
&lt;p&gt;云原生改造本身不自动带来稳定性，某些方面反而引入了新的失败模式（调度抖动、探针配置不当导致的误杀）。提升主要来自三件事：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;故障自愈。&lt;/strong&gt; 健康检查 + 自动重建覆盖掉了大量「重启就好」的问题。这类问题以前要走值班流程，平均恢复时间是分钟到十分钟级；自动化之后是秒级。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;发布过程可控。&lt;/strong&gt; 滚动发布加自动判定，坏版本在小批次就被拦住，而不是全量铺完才发现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;故障域隔离。&lt;/strong&gt; 把原来混部在同一批机器上的关键服务和非关键服务拆开，避免非关键服务的资源抢占影响核心链路。&lt;/p&gt;
&lt;h2 id="问题定位效率提升一倍"&gt;问题定位效率提升一倍&lt;/h2&gt;
&lt;p&gt;原来定位一个问题要跨好几个系统：监控看指标、日志平台查日志、CMDB 查拓扑、变更系统查最近改了什么。每个系统都要单独登录、单独按时间过滤。&lt;/p&gt;
&lt;p&gt;做法是把这些信息按「事件」维度聚合——给定一个时间点和一个服务，自动把该时间窗内的指标异常、错误日志、上下游拓扑、变更记录拉到一起。定位效率的提升不来自任何单个系统变强，而来自不用再手工做关联。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这套思路后来延伸成了我现在在做的&lt;a href="https://humeie.com/demo/rca/"&gt;告警根因分析&lt;/a&gt;——把关联做到位之后，下一步自然是让模型在这套上下文里直接给出根因判断。&lt;/p&gt;</description></item><item><title>两款数据库 Operator：从部署文档到声明式配置</title><link>https://humeie.com/projects/database-operator/</link><pubDate>Sun, 28 Jun 2026 00:00:00 +0000</pubDate><guid>https://humeie.com/projects/database-operator/</guid><description>&lt;h2 id="问题"&gt;问题&lt;/h2&gt;
&lt;p&gt;两款分布式数据库的部署原本靠一份很长的文档：几十个步骤，多个组件有严格的启动顺序，配置项之间有隐含约束（比如某个副本数必须和某个分片数匹配）。文档写得再细，人执行还是会错——错的地方还很分散，有人漏了一步，有人把顺序搞反，有人配置项填了个合法但不兼容的值。&lt;/p&gt;
&lt;p&gt;更麻烦的是&lt;strong&gt;出错之后不好查&lt;/strong&gt;。因为部署过程没有留下结构化的状态，只能靠翻日志倒推执行到哪一步、哪一步出了偏差。&lt;/p&gt;
&lt;h2 id="做法"&gt;做法&lt;/h2&gt;
&lt;p&gt;Operator 的核心价值不是「自动化部署」——脚本也能自动化。核心价值是&lt;strong&gt;把「期望状态」和「当前状态」都变成可查询的结构化数据&lt;/strong&gt;，然后让控制循环去消除两者的差距。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;把隐含约束写进 CRD 校验。&lt;/strong&gt; 配置项之间的约束原来只存在于文档的注意事项里，现在写成 OpenAPI schema 校验和 admission 逻辑。填了不兼容的值会在提交时被拒绝，而不是部署到一半才崩。这一项对「出错率降低 80%」的贡献最大——大部分部署失败根本不是执行错误，是配置本身就不合法。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;启动顺序交给状态机，不是交给 sleep。&lt;/strong&gt; 脚本化部署里常见的做法是「启动 A，睡 30 秒，启动 B」。这在慢环境里会失败，在快环境里会浪费时间。Operator 里改成显式的阶段状态：A 真正就绪了才推进到 B，就绪的判定是查询 A 的实际状态而不是等时间。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;状态可查询。&lt;/strong&gt; CR 的 status 字段暴露当前处于哪个阶段、每个组件的健康状况、上一次协调的结果和错误。查问题从「翻日志倒推」变成 &lt;code&gt;kubectl get&lt;/code&gt; 一眼看到。&lt;/p&gt;
&lt;h2 id="关于-operatorhubio-level-3"&gt;关于 OperatorHub.io Level 3&lt;/h2&gt;
&lt;p&gt;Operator 的成熟度分五级。Level 1 是能装，Level 2 是能升级，&lt;strong&gt;Level 3 是要支持完整的生命周期&lt;/strong&gt;——备份、恢复、故障转移、灾难恢复。&lt;/p&gt;</description></item></channel></rss>