前言 使用bitpoke的mysqloperator作为k8s的mysql服务,使用的版本v0。4。0, github地址:https:github。combitpokemysqloperator介绍 MysqlClusteroperator主要支持如下功能数据自动备份还原主从模式支持Prometheus数据监控问题产生 建立的mysql服务每隔一段时间就重启,事件的报错信息如下Readinessprobefailed:ERROR2003(HY000):CantconnecttoMySQLserveron127。0。0。1(111)binsh:line0:test:eq:unaryoperatorexpectedLivenessprobefailed:Gethttp:172。31。210。72:9125metrics:dialtcp172。31。210。72:9125:connect:connectionrefused定位问题 为什么心跳不通过? 貌似心跳机制不通过,查看pod信息 pod探针设置 心跳默认20秒不通过,就重启,看源码也没有心跳配置项,坑啊,不过这只是表象,到底是什么导致心跳不通过? mysqlCluster启动时,会启动4个容器metricesexporter,mysql,ptheartbeat,sidecar。看这4个容器的cpu,内存使用情况,发现mysql内存超过,如下: mysql内存使用情况 看最后状态,OOMKilled,而且当前内存使用率3。9G接近limit4G的设置。找到产生的问题原因了,是因为内存超了,被容器杀掉,导致心跳不通过报错重启 为什么内存使用这么高? 思考mysql使用内存高,可能跟mysql自身缓存有关系,查内存相关参数showvariableswherevariablenamein(innodbbufferpoolsize,innodblogbuffersize,innodbadditionalmempoolsize,keybuffersize,querycachesize); mysql配置信息 看到innodbbufferpoolsize设置得值特别大,这个参数设置只有主要缓存innodb表的索引,数据,插入数据时的缓冲,但默认是8M。 为什么innodbbufferpoolsize设置变得这么大? 翻翻mysqlCluster源码,跟innodbbufferpoolsize有关代码 default。go没有设置innodbbufferpoolsize,通过cluster。Spec。PodSpec。Resources。Requests。Memory配置项计算一个setinnodbbufferpoolsizeifnotsetinnodbBufferPoolSize:128mbMySQLdefaultvalueifmem:cluster。Spec。PodSpec。Resources。Requests。Memory();mem!nil!mem。IsZero(){varcErrerrorifinnodbBufferPoolSize,cErrcomputeInnodbBufferPoolSize(mem);cErrnil{setConfigIfNotSet(cluster。Spec。MysqlConf,innodbbufferpoolsize,humanizeSize(innodbBufferPoolSize))}}计算大小funccomputeInnodbBufferPoolSize(memresource。Quantity)(int64,error){availableMem:mem。Copy()percentRAM:0。75ifmem。Value()512mb{dontsetinnodbbufferpoolsizeleaveittomysqldefault(128M)return0,fmt。Errorf(memorytoosmalltocomputeinnodbbufferpoolsize:s,mem)}elseifmem。Value()1gb{RAM1gbbuffersizesettoRAM0。5availableMem。Sub(resource。MustParse(256Mi))percentRAM0。5}elseifmem。Value()4gb{RAM4gbbuffersizesettoRAM0。75availableMem。Sub(resource。MustParse(256Mi))percentRAM0。75}elseifmem。Value()4gb{RAM4gbbuffersizesettoRAM0。8availableMem。Sub(resource。MustParse(512Mi))percentRAM0。8}returnint64(float64(availableMem。Value())percentRAM),nil} 源码解析:没有设置innodbbufferpoolsize,则通过cluster。Spec。PodSpec。Resources。Requests。Memory大小的参数乘以系数,这里是0。75,所以是3G。 问题就在这里,为了保证资源独占,mysql设置时是requestlimit,因为自动计算导致innodbbufferpoolsize过大,最终导致oom,需要手动设置innodbbufferpoolsize,就手动设置2G吧mysqlConf:innodbbufferpoolsize:2147483648 设置innodbbufferpoolsize不生效? 设置后,pod不重启?参数没有生效设置。设另一个512M就生效了。尝试加入引号,作为字符串处理,配置开始生效。难道跟类型有关系?继续看相关源码 default。goinnodbBufferPoolSize:128mbMySQLdefaultvalueifmem:cluster。Spec。PodSpec。Resources。Requests。Memory();mem!nil!mem。IsZero(){varcErrerrorifinnodbBufferPoolSize,cErrcomputeInnodbBufferPoolSize(mem);cErrnil{setConfigIfNotSet(cluster。Spec。MysqlConf,innodbbufferpoolsize,humanizeSize(innodbBufferPoolSize))}} 看这个类型定义cluster。Spec。MysqlConf MysqlClusterSpectypeMysqlConfmap〔string〕intstr。IntOrString intstrtypeIntOrStringstruct{TypeTypeprotobuf:varint,1,opt,nametype,casttypeTypeIntValint32protobuf:varint,2,opt,nameintValStrValstringprotobuf:bytes,3,opt,namestrVal} 如果设置成数字,则整数是int32位 看int32位的长度 int32thesetofallsigned32bitintegers(2147483648to2147483647) 214748364721474836482g所以应该是配置报错,但没有抛出来而已 至此内存使用过大的问题,解决了,内存使用也降下来了结论mysqlCluster自动设置了innodbbufferpoolsize导致内存过高,超过Limit限制,被容器kill,反复重启,事件日志就是心跳连不上了,导致重启。k8s上有状态的服务。优点:操作快捷方便,普通开发人员都可以操作。缺点:刚起步,很多方面不够完善,包括文档。碰见问题,需要下源码查具体问题。