前几天Pacemaker+Corosync的PostgreSQL HA集群发生了两次故障,再次提醒了HA的部署要谨慎,维护要细致。
系统是基于Pacemaker+Corosync的PostgreSQL 1主2从 HA集群。在数据库上执行一个delete.从500w的表里删除13w条记录,发现Master挂了。 然后自动起来,再执行这个SQL,再次挂。究竟怎么回事呢?
后来查了Pacemaker的日志,发现是expgsql RA的monitor发生超时,导致expgsql RA重启PostgreSQL。(迁移阈值是3,可以重启3次,超过3次就会发生主从切换。)
/var/log/messages
corosync.log中发现在发生超时前,系统负载很高。
/var/log/cluster/corosync.log
系统是4核机,上面的输出表明系统已经超载,进入限流模式。后面甚至有负载达到49的记录。
限流模式是Pacemaker的一种保护措施,进入限流模式后Pacemaker会减少自身可以并发执行的job数。 在High CPU load下,限流模式会限制同时只能有1个job在跑。正常情况下,允许同时运行的最大job数是CPU核数的2倍。
https://github.com/ClusterLabs/pacemaker/blob/master/crmd/throttle.c
获取CPU LOAD的方式为取/proc/loadavg中第一行的1分钟负载。
至于负载阈值,有3个负载级别,不同阈值有不同的因子(throttle_load_target)
对应的阈值分别为 load-threshold * throttle_load_target
load-threshold为集群参数,默认值为80%
判断是否超过阈值的方法是用调整后的CPU负载(上面的CPU LOAD除以核心数)和阈值比较
除了CUP负载,Pacemaker还有IO负载的比较,但是相关函数存在多处错误,实际上无效。 无效也好,如果下面这个问题解决了后面会有相反的bug导致会误判高IO负载。
不能肯定限流和这次故障是否有必然的联系。但是在限流下,Pacemaker执行job的能力弱了,系统负载又高,会增大monitor相关job得不到及时的CPU调度进而发生超时的概率。实际的罪魁祸首还应该是高负载及超时判断方法。
搜索后发现有人遇到过类似问题,处理办法就是增大monitor的超时时间。
https://bugs.launchpad.net/fuel/+bug/1464131
https://review.openstack.org/#/c/191715/1/deployment/puppet/pacemaker_wrappers/manifests/rabbitmq.pp
一方面修改增大monitor的超时时间。在线修改的方法如下:
另一方面,发现系统负载过重,经常跑到100%的CPU,即使没有HA这档子事也是个不稳定因素。 通过修改应用,迁移大部分的读负载到SLave上,有效减轻了Master的压力。
GitHub遇到过类似的故障,由于迁移到Master负载过高,进而Percona Replication Manager的健康检查失败进行了切换,切换后新主的缓存是冷的,负载同样过高,又切回去。 (幸运的是我们的方案有3次迁移阈值的保护,不会立刻切。)GitHub权衡后的对策居然是放弃自动切换,只能由人工发起。
另,Pacemkaer的论坛有几件高负载导致corosync token超时的问题,同样由于相关job不能及时得到OS调度所致,该问题虚机上容易发生,特别是有超分的情况下,解决办法是加大token超时时间。
系统配置的同步复制,正常情况下2个Slave应该一个是sync,另一个是async。 但是,某个时间发现2个Slave都是async,这对应用系统暂无影响,但是万一这时Master挂了会影响HA切换。 查看Master上的rep_mode.conf配置文件,发现synchronous_standby_names是空。
vi /var/lib/pgsql/tmp/rep_mode.conf
于是,手工修改为node2,再reload一下就OK了。
至于什么原因导致的,又仔细查看了一下RA脚本,未发现疑点,而现场已经不在,无从查起,只能等下次遇到再说。