写点什么

从二十个严重的配置故障中我们能学到什么?

  • 2019-12-24
  • 本文字数:4293 字

    阅读完需:约 14 分钟

从二十个严重的配置故障中我们能学到什么?

配置故障是运维人员在工作中经常会遇到的问题,如何才能避免配置故障的发生呢?本文作者列出了自己职业生涯遇到的 20 个不同类型的配置故障,并分析了故障发生的原因,提出了相关的解决方法。

配置变更的痛点

时效性,很多配置变更的场景,其生效时间是有明确要求的,尤其是止损相关的操作。如流量调度的配置生效时间不超过 5min,这是由 SLA 所决定的。因为 5min 的生效要求,所以这类配置变更基本上不会进行灰度,直接就全量生效了。


动态化,在上下游关联关系的场景中,服务的 IP 地址列表和数量均会发生变化的,站在整个系统角度去看,可能每时每刻都会有服务因扩容、缩容、故障转移而产生 IP 列表的变化,加之这类配置是最终一致性的特性,因此,就很难对语义内容的正确性做及时准确的判断。


差异化,同一服务的不同实例或者不同集群间,配置会有一定的区别。以监控系统为例,因为每台机器上部署的服务组合不相同,那么每台机器上需要采集的内容就不相同,那相应的监控配置也会不同。许多的机器生效的配置不同,版本不同,那么要想检查哪些机器未生效最新配置,未完全生效配置,就有困难了。


碎片化,每个服务都需要配置管理,但现实却是大多数服务都是自己写的这套逻辑,且实现非常之简单。如果现实是建立在大多数服务自己实现配置管理的基础上,那么想要做到相对统一的标准规范,你就需要做各种对接和适配,开发各种外挂,持续处在一个较低的层次上。配置中心成熟的开源解决方案有很多,因此内部开发人员也少有动力基于现状写一套适配的方案,大家都会说推动改造是最好的,那改造之前呢怎么办呢

二十个严重的配置故障

笔者曾长期负责配置服务的运维工作,也经常参加公司的故障复盘会,感慨于配置故障影响的严重程度,因此将过去多年和配置相关的各种服务故障脱敏后进行罗列,希望对大家有所帮助。限于篇幅的关系,无法对每个 case 进行准确详尽描述,仅描述故障原因部分,因此阅读下面的 case,需要读者具备一定的相关背景才能更好的理解(本文中罗列的 case 较多,有内容不合适的地方,可直接联系笔者处理)


case1:在 WAF 中部署了配置错误的规则,其中一个规则包含有一个正则表达式,导致节点 100%CPU 占用。和 CloudFlare WAF 的故障是较为相似的


case2:某服务访问数据库错误,获取合法用户列表的结果为空值,该服务认为没有合法用户,将所有的用户请求全部封禁,导致系统完全不可用。和阿里云 20180627 的故障较为相似的


case3:每台物理机上均有一个单机部署器,单机部署器定期从服务端同步配置,用以在单机上部署需要的客户端列表。因为网络的问题,配置被截断,部署器只获取了上半部分配置,部署器基于此进行更新,所有未在配置中的服务被全部卸载,影响极为严重


case4:计算模块对加载的处理规则数量进行了限制,单个租户最大可处理 1000 条规则,经过几个月的使用后,某个租户的规则数超过 1000 条,计算模块全部 coredump


case5:服务启动前需要从远程加载相关配置,某次变更添加配置条目较多,服务请求配置超时后,不断重新启动,直至将配置中心打垮,进而影响多个业务,导致系统彻底崩溃


case6:Zookeeper 的 initlimit 设置为 5(意思是实例启动后可以有 10s 的时间来同步数据),该数值对于大部分集群来说,都没有问题,但是如果 ZK 集群的快照体积超过 1GB,那么节点重启后就可能无法在 10s 内同步完数据进而导致节点异常


case7:Agent 上传给服务端的数据包出现了异常,在头部信息中,100KB 的体积变成了无限大,然后后端模块就按照该值进行内存分配,因为超过 Ulimit 的限制,所以 coredump 了,一部分服务器异常后,Agent 继续将请求发送给剩余的服务器,直到集群全部被打死为止


case8:通过配置服务获取下游服务列表,运维人员误将服务下所有实例从配置中删除,而该服务也未使用系统提供的熔断阈值,导致从配置服务中获取该服务列表为空,其他依赖服务加载了该配置后,导致服务整体故障


case9:新上架的交换机未添加完整的 ACL 规则,导致线下服务请求到线上集群中


case10:用户提交了语法结构不正确的配置,然后该配置下发到了后端,所有加载该配置的后端模块全部 coredump 了,后端模块使用了通用的语法校验库,但和前端使用的校验库不同


case11:后端服务异常后,触发了自动降级(通过修改 Nginx 的配置文件来实现),修改配置文件出现了逻辑错误,该配置通过了语法校验并立即进行了全量自动更新,导致集群整体崩溃


case12:将某台服务器上的 stats.conf 文件同步到全部 nginx 集群上,忽略了 allow 字段的 ip 地址不同,致使 lvs 认为监听的后端 nginx 全部故障,系统直接出默认页面了


case13:批量删除线上服务器的日志,因路径中包含特殊字符,运维系统未能很好的处理该字符,只保留了特殊字符前的路径,导致线上服务器根目录被清空


case14:配置项结尾多了特殊字符,导致策略匹配全部失败。原因是 windows 下的文本文件换行符是\r\n,linux 下的换行符是\n,在 linux 下 vim 打开 windows 的文本文件,在行尾会显示^M 字符


case15:通过配置服务获取下游服务列表,因下游服务列表包含了四万多个 IP 地址,导致获取超时,服务继续使用过期的下游列表,而该过期的下游列表中无效实例逐渐增加,最后导致服务连续重试到无效实例,流量被丢弃


case16:配置中心对外提供配置下载服务,其 LB 的负载均衡策略使用了随机策略,因下载集群规模超过百台机器,配置更新需要一定时间,在此期间,请求配置中心获取的配置会不停的在新旧版本之间变化,导致相关的服务被不停的卸载,升级,无法提供服务


case17:配置中心的负载均衡策略使用了 Ip_hash 策略,部分下载集群数据未更新,导致被分配到这些集群的服务,无法获取最新配置,且多次重试依然无效,导致流量统计始终缺少 20%的流量,对收入造成严重的损失


case18:高防回源携带的头部字段中新增的内容与源站 iis 配置不兼容,导致回源请求被拒绝


case19:named 服务在重载配置时,产生了新的进程但老进程没有正常退出,服务请求数据时,将请求打到了老 named 的进程,该进程的配置没有更新,导致用户拿到的结果不符合预期。类似的问题,nginx 也有,在很多开源软件上也都有存在


case20:自研 nginx 的扩展来实现 upstream 的定位,hash 桶的大小设置为 1024,因 ip 重复个数较多,超过了 hash 桶的大小,导致 hash 分桶策略不断的进行 rehash 任务,请求全部被卡死

故障改进

对于上述的故障,我们从加强测试,加强数据校验,集群隔离,灰度发布,缓存和熔断六个维度来看各个 case 的适用性,结果如下图所示。


加强测试加强校验集群隔离灰度发布缓存熔断
case1适用适用适用
case2适用适用适用适用
case3适用适用适用适用
case4适用适用
case5适用适用适用
case6适用适用
case7适用适用适用
case8适用适用适用
case9适用适用
case10适用适用适用适用适用
case11适用适用适用
case12适用适用适用适用
case13适用适用适用
case14适用适用适用
case15适用适用
case16适用
case17适用
case18适用适用
case19适用适用
case20适用适用
17137764


假设笔者的给出的改进方案是正确的,对统计结果做如下分析:


  • 加强测试,从有效性来说,该方案可以搞定 85%的故障,如边界值的问题,异常输入的问题,特殊字符串的问题等。但是对于部分场景,加强测试可以搞定,但成本非常高,例如 WAF 的规则问题,不同的用户,配置的规则不同,如果要在测试阶段解决,那就需要对所有用户的所有规则进行测试,且要有足够丰富的请求组合,这时候,可行但成本很高。还有,加强测试虽然可以解决很多问题,但没有从本质上彻底消除问题,且依赖于测试团队的经验和能力,结果并不可控。

  • 加强校验,从有效性来说,该方案可以搞定 65%的故障,以 case2 获取空值的故障来讲,对请求结果进行校验,完全可以避免该问题,且这是程序机制天然具备的,并不依赖于人的经验和能力,因此效果更好。另外,加强校验,并非局限于对空值的校验,还包括配置文件完整性的校验,数据包合法性的校验,配置文件的版本、时间戳、更新时间的校验,对特殊字符串容错的能力,还提供一些故障场景下的兜底访问策略,同时还可以将配置变更的信息以 http 接口进行暴露,便于监控。美中不足之处在于,如果对每个模块分别实现上述的功能,那成本太高了。

  • 集群隔离,笔者之前最为推荐的能力建设内容之一,本次居然只能解决 35%的故障,究其原因,主要在于很多业务虽然隔离部署,但依赖了相同的配置文件,且大部分是高频热加载的,因此集群隔离在此处,略显苍白。

  • 灰度发布,这也是笔者最为推荐的能力建设内容之一,本次也只能解决 35%的故障,主要是因为大部分的配置变更是没有灰度发布的,直接靠程序的定时轮询热加载,因此灰度在此,也略显苍白。


综合来看,三个建议:


  • 将校验,缓存,熔断等相关的能力合并在一起,在通用的配置服务中实现,会是比较好的方案,退而求其次,如果没有通用的配置服务,也应该具备这些能力。

  • 将配置变更尽可能的视为一种上线,涵盖从版本提交,代码检查,测试,灰度发布,效果监控等各个环节,也能够更好的保障稳定性,毕竟很多配置是最终一致性,而非强一致性的,因此,用时间来换取稳定性,也是值得的

  • 将强一致性转为最终一致性,问题就不会那么棘手了。以账号密码变更为例来说明,账号密码变更是强一致性要求的,但是如果通过新增一组账号密码逐步进行替换,全部替换完毕后删除旧的账号密码,则就将强一致性转为最终一致性了。


还有兜底建议:


  • 通过资源限制+SSH+Puppet 多种方式的互备,确保任何场景下,不论是 sshd 异常,还是 cpu 打满,都能够通过批量操作服务器快速止损,决不要出现无法登录服务器的惨剧

场景化建议

热加载配置的场景,尽量使用配置中心这种解决方案,类似于上文的加强校验,缓存,熔断等等,都是标配能力了,而且一旦发现了潜在的隐患,通过升级 lib 库,大家都能避免发生同类问题,效果极好。当然,你得用好才行,胡乱使用 zookeeper,最后导致各种故障,然后怪罪于 zookeeper 有问题,人家很冤枉啊。


需要通过重载配置文件才能生效的场景,则尽量使用集群隔离+灰度发布+加强校验的解决方案,以 DNS 为例说明,不同的 zone 由不同的集群来处理请求,每类 zone 再按需实现同城多活/异地多活,并新增小流量集群,尽量杜绝跨集群的变更操作,对每次变更都要进行严格的自动化校验,并分批次灰度生效,通过提升实时监控能力来降低批次间的时间间隔,进而减少故障的发生。


在整理上面资料的同时,配置故障让我联想到和无性繁殖有些类似,文末的参考资料中附带了香蕉和咖啡树的故事,有兴趣的读者可以看看。


扩展阅读:


香蕉可能要灭绝?还不是第一次?香蕉:救救孩子吧…


为什么英国人对茶情有独钟而不是喜欢咖啡?背后原因你一定想不到


2019-12-24 09:402220

评论 3 条评论

发布
用户头像
多级缓存也应该是配置类服务的一种兜底能力
2022-05-30 21:30
回复
用户头像
需要把改进能力放在case后面进行下标注,让大家在当时就能够认可改进内容,从而认可统计结果

2020-04-13 19:16
回复
用户头像
google在2020.03.26的服务故障可以更新进来
2020-04-13 19:13
回复
没有更多了
发现更多内容

面试官:你还有什么想问我的?

老张

面试 面试经验

万界星空科技生产管理MES系统在卫浴企业中的应用

万界星空科技

制造业 生产管理系统 mes 万界星空科技 卫浴工厂

云监控告警2.0:革新传统告警机制,引领智能化监控新时代

天翼云开发者社区

云计算 云监控 告警系统

兼容互认证+1!TDengine 与 Tapdata Live Data Platform 成功通过测试

TDengine

tdengine 时序数据库

在Java中如何优雅的停止一个线程?可别再用Thread.stop()了!

快乐非自愿限量之名

Java 编程 开发

火山引擎VeDI:A/B实验如何应用在APP推荐系统中?

Geek_2d6073

人工智能大模型原理与应用实战:自动驾驶技术的飞跃

百度开发者中心

人工智能 自动驾驶 大模型

语言大模型的浮点运算分配优化策略

百度开发者中心

人工智能 机器翻译 语音识别 大语言模型

SD-WAN——企业云网融合的优选

Ogcloud

SD-WAN SD-WAN组网 SD-WAN服务商 SDWAN

阿里巴巴中国站获得1688商品详情 API(1688.item_get)快速抓取电商数据

技术冰糖葫芦

API API 测试

【论文速读】| MOCK:上下文依赖引导的内核模糊测试

云起无垠

陌陌技术分享:陌陌IM在后端KV缓存架构上的技术实践

JackJiang

即时通讯;IM;网络编程

深入了解美国数据库服务器的特点与使用方法,助你更高效地管理网站数据

一只扑棱蛾子

美国服务器 美国数据库服务器 数据库服务器

SAE自动驾驶分级介绍

EquatorCoco

人工智能 自动驾驶 机器学习

Pytest参数化用例(单参数,多参数,用例重命名,笛卡尔积)

测试人

软件测试 测试开发 pytest

获取1688商品详情API:步骤与代码示例

Noah

面试官:说说反射的底层实现原理?

王磊

Java 面试

商品智能化 如何节约真金白银?

第七在线

欢迎来到 Mint Forest:Mint Your Tree,兑换你的 $MINT!

NFT Research

blockchain web3、

基于仿真的飞机ICD工具测试

DevOps和数字孪生

航空航天 飞机 ICD

MySQL的varchar水真的太深了——InnoDB记录存储结构

砖业洋__

varchar innodb行格式 dynamic行格式 varchar最大16383

武汉LUG报名开启!这次我们来到了华中科技大学,3月23日(周六)来见面吧!

nn-30

实例带你了解GaussDB的索引管理

华为云开发者联盟

数据库 后端 华为云 华为云GaussDB 华为云开发者联盟

让LED显示屏更加节能,刻不容缓!

Dylan

环境 性能损耗 LED显示屏 全彩LED显示屏 led显示屏厂家

云审计与大数据审计:区别、优势与应用场景

天翼云开发者社区

云计算 大数据 数据处理 云审计 大数据审计

美股交易系统搭建

GangguHK

知识|基于混合模式的多余度飞控全数字仿真系统研究

DevOps和数字孪生

航空航天 飞控全数字仿真系统

线上机器 swap 过高导致告警

不在线第一只蜗牛

开发 swap

MYSQL 主从不一致的原因分析

不在线第一只蜗牛

MySQL 数据库

SaaS应用加速:提高企业办公效率,解决业务挑战

Ogcloud

SaaS 网络加速 SaaS应用 SaaS应用加速

如何在数据库中存储小数:FLOAT、DECIMAL还是BIGINT?

EquatorCoco

数据库 oracle

从二十个严重的配置故障中我们能学到什么?_软件工程_焦振清_InfoQ精选文章