本篇讲 “故障自动维修流程”里 “环境初始化”这个环节。
初始化的问题—环境不一致
可能大家会觉得,环境初始化有什么好说的,不就是跑一堆设置系统参数的脚本么? 事实上,设置环境很容易,但是要保证环境设置正确会遇到很多问题。
环境不一致影响业务的case
先来看我们对业务sre 的访谈,因“环境设置不正确”导致业务受损的case有很多,如下所示,
-
因超线程未开启,导致服务在流量高峰时性能不足,产生请求拒绝
-
因QoS未设置,导致跨机房查询数据时,响应延迟飙高,大面积拖慢了了用户访问速度
-
因未设置ssd磁盘内核参数,导致磁盘处于低性能状态,影响业务读取速度
-
因网卡多队列未正确设置,导致单个cpu被打满,产生拒绝请求
-
因基础agent版本不一致,影响变更、数据配送任务,产生了脏数据
-
因core pattern 未正确设置,业务程序出core打满磁盘,拉长了止损时间
-
因环境缺失/版本不符导致业务程序依赖异常,产生请求拒绝, 如mysql/hadoop client 缺失, python/perl 版本过老
-
因内核网络、内存参数未正确设置,导致业务出现性能颠簸问题,产生间歇性请求拒绝,排查成本高
上述case,都是因部分机器环境未正确设置导致的,也就是机器环境存在“不一致”的情况。
环境不一致的原因
为什么会不一致?我们分析了各个业务初始化脚本集合,得到的结论是:“硬件/系统多样、业务需求差异化、初始化流程不统一不规范” 这3个因素综合作用导致了“环境不一致”。
1、硬件/系统多样
机器硬件不一样,设置某个功能的命令是不一样的。
比如开启超线程,戴尔机器和惠普机器不一样,这导致同一个功能,业务sre会写出多个脚本, 例如 cpu_ht_dell.sh, cpu_ht_hp.sh;
同样道理,系统发行版不一样,开机启动、参数文件位置、内核参数的设置方式有可能不一样,对于同一个需求,就会存在多个脚本,长期下来,几乎无法维护。
2、业务需求差异化
不同的业务类型,通常会根据自身需要,调优设置各种参数。
如接入层机器,需设置tcp内核参数,包括缓冲区大小、拥塞窗口大小;
存储层机器,需设置内核换页、磁盘调度策略、shm参数;
计算密集型业务机器,需开启超线程,QoS优先级设置为高;
这些差异化的存在,使得各个业务sre小组都维护着一套自己的初始化脚本集合,很难共用、复用。
3、初始化流程不统一、不规范
业务sre执行初始化时,没有统一规范,初始化的执行方式多样(pssh/ansible/部署系统),而且没有强制性检查。
由于环境初始化失败,不会影响服务的初期运行,只有在流量大的时候才会出现问题,如果执行初始化的sre经验不足或者不够细心,这些“环境初始化失败”的机器,也会投入使用,造成隐患。
怎么解决不一致
在自己动手解决问题之前,我们粗略地调研了业界的环境管理方案:puppet,存在以下问题,
-
puppet管理的资源中,有file, service, yum 等, 但不包括硬件,如BIOS、超线程、网卡多队列; 另外,关于service 这个资源,涉及到版本问题,需要和部署系统联动,puppet似乎没有提供相应的功能
-
puppet has its own configuration language, puppet 通过自成体系的配置语言来声明资源,控制任务的执行,这对我们来说是一个很大的学习成本,我们需要的是:低成本地使用已经存在的上百个脚本,而不是用别的语言重写它们。
-
puppet 是 C/S架构,意味着需要部署它自己的agent,在几万台机器的集群上部署一个新agent,风险性很高,需要经历漫长的审核、测试、运行验证过程
解决思路
所以,我们决定还是结合自身问题来解决,分以下几步走,
1、引入apply-check机制,规范初始化的执行和检查,保证交付质量
apply-check强制要求每一个初始化的执行和检查成对出现;
apply 即对文件或内存写入,check即对文件或内存读出并做对比判断,例如,
Item | Apply | Check |
超线程 | ipmitool raw 0x3e 0x20 0x00 0x00 0x00 | cat /proc/cpuinfo | grep -o ht | uniq |
这样,可以明确知道初始化是否成功。
2、根据机器品牌,部署硬件/BIOS/系统发行版相关命令工具
如图所示,超线程的初始化apply、check脚本分别软链到了相应厂商的实现脚本,这样就可以在执行时,无需关注机器厂商、系统的差异,直接调用,消除适配问题。
3、明确业务类型和初始化集合的关系
我们引入 Pool 的概念,每个Pool对应一个环境初始化集合,如下表所示,
Pool | 超线程 | 网卡多队列 | QoS | Tcp参数集 | Disk io参数集 | … |
Web | on | on | 高 | on | off | … |
计算 | on | on | 高 | on | off | … |
存储 | off | on | 高 | off | on | … |
通用 | off | on | 中 | off | off | … |
这样,给定一台机器,只要知道归属于哪个集群,就能通过调用相应的check来判断这机器的环境是否正确,是否一致。
解决环境不一致问题
做了上述优化之后,我们在机器重装系统流程中增加了apply-check的逻辑,可以保证环境一定是正确的,因为只有在所有初始化的check通过之后,系统才会交付。
对于存量机器,我们把环境不一致当作一种故障来处理,复用了硬件故障维修的流程框架。
环境不一致修复的工作流程,
-
环境检测: 每5分钟发起一次环境检测,即调用初始化的check脚本,获取当前时刻整个集群的环境不一致的机器列表,推送到工作流子系统
-
安全策略: 遍历机器列表,依次执行安全策略,过滤不符合要求的机器,得到一个可安全执行初始化脚本的机器列表
-
执行初始化: 根据机器所属pool,执行相应初始化apply脚本
-
检查初始化:根据机器所属pool,执行相应初始化check脚本,如果初始化正确,流程结束
-
如果初始化不正确,那么认为此机器存在硬件或系统级别的故障,生成repair_host流程,本流程结束。
(故障修复流程框架的详情请参阅 大规模机器集群-故障自动处理(一) )
通过这两点,逐步消除存量机器的环境不一致,同时保证新交付的机器一定是正确的。
在解决基础环境一致性问题之后,结合硬件故障自动维修,我们得到了一个能力,
输入: 任何一台机器,不管是否有故障,环境是否正确
输出: 无硬件故障,符合业务环境需求的可用机器
这为后续做机房建设,灾备重建打下了基础,下一篇会讲这部分内容。
排列文字,重组感受。
我是曲行人,日常写码,闲时写点儿文字,
如果你觉得有点意思,或者有点用,可以关注我,
我将在大脑里的思维原子做布朗运动时,输出文字。
公众号: qxren7
二维码: