这是学习笔记的第 1782篇文章
之前总结过一版元数据稽核的内容。
随着数据的沉淀和数据的录入过程中的不规范,发现元数据存在越来越多的问题。 元数据都不能作为参考的话,那后期的工作就步履维艰了。
运维平台元数据稽核小结
所以和同事花了不少时间在梳理元数据的问题,有时候梳理的时候都有些凌乱,有很多之前设计的时候没有重视的问题,现在通过其他方式都暴露出来了。
比如有的数据库架构根据映射关系显示是两个主库匹配到了一个从库,结果仔细查了一圈,另外一个IP地址是VIP,有的服务器按照配置看起来是级联复制,但是Slave配置是有问题的,有的服务器有多个网卡,业务有的用第一个网卡,有的用第二个网卡;有的服务器已经标识下线,但是通过远程工具还可以正常连接;有的服务器仍在线,但是服务却无法连接;有的服务器可以连接,但是数据库的用户配置不规范,实例无法实现自动化登录;有的节点是单点实例,没有备份也没有从库。
诸如此类的问题,看起来很细碎,每一个都要确认好,然后还希望能够成为一种通用的检查方法。梳理的时候痛苦,但是整理后关系理清楚以后,有一种豁然开朗的感觉。
在问题没有成为故障之前,我们有无数种可以弥补的措施,一旦问题上升为故障,这个影响力和前期的技术债就会是雪崩式涌来。
所以用了多个维度去梳理元数据之后,我觉得需要通过循序渐进的方式来梳理,而不是通过一种一刀切的方式来梳理达到所有的目标。
我初步设计了如下的巡检流程:
1.服务可用性检查
故障服务器
不可连接实例
2.vip映射
3.多网卡信息补充
4.主从状态检查
第一个阶段里,如果服务器不可访问,后续的流程都不用走了。如果实例可用,后续可以继续检查实例层面的IP配置等。通过这些筛选,能把很多潜在的问题都扼杀在摇篮里面。手工去组织映射元数据的方式只是一种手段,不能够成为一种通用的解决方案。
检测服务可用性,比如发送一个简单的命令,hostname等等,只要正常返回即可。
检测实例是否可连接,可以使用类似 mysql -uxxx -pxxxx -hxxx -Pxxx的方式来批量连接
这些都是相对简单的任务,我们为了对批量任务管理,可以使用celery来对接完成。
vip映射的逻辑相对简单。打个比方,对于如下的输出提取出VIP的信息。
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 00:50:56:ab:be:c7 brd ff:ff:ff:ff:ff:ff
inet 102.130.121.249/23 brd 102.130.121.255 scope global eth0
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 00:50:56:b2:a4:ea brd ff:ff:ff:ff:ff:ff
inet 102.130.124.74/24 brd 102.130.124.255 scope global eth1
inet 102.130.124.194/24 scope global secondary eth1
可以使用如下命令来搞定
/sbin/ip addr|grep "global secondary"|awk '{print $2}'|sed 's/\/24//g'
对于额外的IP信息的提取,比如当前的IP是102.130.121.249,我们希望得到另外一个网卡的IP 102.130.124.74
eth0 Link encap:Ethernet HWaddr 00:50:56:AB:BE:C7
inet addr:102.130.121.249 Bcast:102.130.121.255 Mask:255.255.254.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1871938004 errors:0 dropped:0 overruns:0 frame:0
TX packets:1754205747 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:144094791451 (134.1 GiB) TX bytes:2058225946528 (1.8 TiB)
eth1 Link encap:Ethernet HWaddr 00:50:56:B2:A4:EA
inet addr:102.130.124.74 Bcast:102.130.124.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:649521673 errors:0 dropped:0 overruns:0 frame:0
TX packets:581542004 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:49920592684 (46.4 GiB) TX bytes:652537532662 (607.7 GiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:87679527 errors:0 dropped:0 overruns:0 frame:0
TX packets:87679527 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:73056037373 (68.0 GiB) TX bytes:73056037373 (68.0 GiB)
可以使用如下的命令来筛查,这个地方还是要输入原来的IP过滤掉。
/sbin/ifconfig|grep inet|grep -v 127.0.0.1|grep -v $1|awk '{print $2}'|awk -Faddr: '{print $2}'
对于主从状态的检查是一个重要环节,直接秀出检查逻辑。这里会判断四种状态:
主库,从库,级联节点,单实例
#!/bin/env bash
. /etc/profile
. ~/.bash_profile
function initTools() {
UBIN="/usr/bin"
which="${UBIN}/which"
mysql=`${which} mysql`
echo=`${which} echo`
}
function initVars() {
instanceport=$1
instancepassword="xxxxxxxx"
instanceuser="dba_admin"
scriptspath="/home/dba_mysql/scripts/tmp"
}
function getSlaveDetails() {
slaveiothread=`${mysql} -u${instanceuser} -p${instancepassword} -h127.0.0.1 -P${instanceport} -e "show slave status\G" 2>/dev/null| grep -w 'Slave_IO_Running' | sed 's/^[ ]*//g' `
slavesqlthread=`${mysql} -u${instanceuser} -p${instancepassword} -h127.0.0.1 -P${instanceport} -e "show slave status\G" 2>/dev/null | grep -w 'Slave_SQL_Running' | sed 's/^[ ]*//g' `
if [ "${slaveiothread}" != 'Slave_IO_Running: Yes' ] ; then
${echo} "Slave_Error"
else
if [ "${slavesqlthread}" != 'Slave_SQL_Running: Yes' ] ; then
${echo} "Slave_Error"
elif [ "${slavesqlthread}" = 'Slave_SQL_Running: Yes' ] ; then
${echo} "Slave"
fi
fi
}
function getReplicationDetails() {
repl_flag=`${mysql} -u${instanceuser} -p${instancepassword} -h127.0.0.1 -P${instanceport} -e "show processlist" 2>/dev/null| grep -w 'dba_repl' | wc -l `
if [ ${repl_flag} -eq 0 ]; then
${echo} "Master_Conf_Error"
elif [ ${repl_flag} -eq 1 ]; then
${echo} "Master"
fi
}
## MAIN
initTools
initVars $1
conn_chk=`${mysql} -u${instanceuser} -p${instancepassword} -h127.0.0.1 -P${instanceport} -e "select 1" 2>/dev/null | wc -l `
masterflag=`${mysql} -u${instanceuser} -p${instancepassword} -h127.0.0.1 -P${instanceport} -e "show slave hosts;" 2>/dev/null| wc -l `
slaveflag=`${mysql} -u${instanceuser} -p${instancepassword} -h127.0.0.1 -P${instanceport} -e "show slave status;" 2>/dev/null| wc -l `
#echo $masterflag
#echo $slaveflag
if [ $conn_chk -eq 0 ]; then
echo "Conn_Error"
exit 1
fi
if [ $? -ne 0 ] ; then
${echo} "command Error"
exit 1;
fi
if [[ ${masterflag} -ge 1 && ${slaveflag} -ge 1 ]] ; then
master_chk=`getReplicationDetails`
slave_chk=`getSlaveDetails`
#echo $master_chk
#echo $slave_chk
if [[ ${master_chk} = 'Master' && ${slave_chk} = 'Slave' ]];then
${echo} "RelayDB"
elif [[ ${master_chk} != 'Master' ]];then
echo ${master_chk}
elif [[ ${slave_chk} != 'Slave' ]]; then
echo ${slave_chk}
fi
elif [[ ${masterflag} -ge 1 && ${slaveflag} -eq 0 ]] ; then
getReplicationDetails
elif [[ ${masterflag} -eq 0 && ${slaveflag} -ge 1 ]] ; then
getSlaveDetails
elif [[ ${masterflag} -eq 0 && ${slaveflag} -eq 0 ]] ; then
${echo} "SingleDB"
else
${echo} "Result_Error"
这些检查工作随着服务器数量的增加,人工,脚本检查的代价会越来越高,可以借助任务调度来实现平滑的检测。代价方式和你去检查一台服务器差不多。
一下午跑了2000多个任务,反复调试,总算把元数据的部分理清楚了。