运维平台元数据稽核小结
数据库运维中的元数据建设都是重中之重,如果元数据不具有参考的价值,那么后续的操作都会受到影响,但是元数据的建设也应该是分成几个步子来走,首先得能够收集到元数据或者元数据的录入,数据有了后续做规范和标准化才有依据,否则还没开始接入数据就设定一大堆的规范和标准,接入的时候难免开始就会有一种排斥感;其次,数据的收集不能一次性追求最完整,最系统,一定是能够抓住重点,逐步来落实,否则刚开始设定的规范,到了后期集成的时候反复调整反复改,谁都受不了;有了数据,逐步来落实质量,这个过程就是逐步规范化的过程,这个过程中要把握的就是通用和定制的粒度,统一的模板,但是数据的意义可能会有所差别,这个平衡度就是关键。
假设到了现在,你已经收录了很多的元数据信息,也在这个过程中发现了一系列的问题,我们是时候来做一些稽核的工作了。
比如你看到的一个元数据列表类似下面的形式,假设有9个数据库实例,其实这个阶段你也会犯嘀咕,要拍胸脯说元数据妥妥的,那是主观片面的,我们怎么来验证,或者怎么发现元数据问题来修复。
当然你可以想出很多的可能,越多的可能会让你偏离中心,所以也需要做到收敛。
因为所有的实例都可以通过中控访问,所以第一层验证就是ssh是否可达。
所以很快写了一个后台程序来扫描,结果发现20%的服务器存在ssh通信的问题。
看起来数据很惊人,经过确认,发现是一部分的用户属主不一样,比如mysql我们使用dba_mysql用户,Redis使用dba_redis用户,不能一概而论,其他有问题的数据库也是这种情况,所以经过确认和修复,这个指标下降到了2%。
第二个阶段是对已有的元数据信息做确认,那些不可访问的实例是否已经下线或者后期做了迁移,这个阶段非常重要,直接关乎到数据质量。
所以确认之后,发现这个比例降到了1%。
当然到了这个时候,看起来元数据已经差不多了,剩下的1%的很快就可以确认了。工作量相对来说就很清晰了。
第三个阶段其实是对于未知问题的把握,比如我们的元数据库中录入了100个实例,但是可能某个服务器上另外又部署了2个实例,在元数据中可能遗漏了。或者说服务器上运行着5个实例,但是在元数据里面是6个实例,因为之前做的都是ssh是否可达的校验,这一层的校验目前还是空白。
所以零零散散的拼接起来,大体就是下面的几类问题了。
整个对比就是一个全面的比较,元数据就是一个列表,系统中抓取的信息也是一个列表,两个列表互相对比,就能够得到一些差异的数据。
所以这个阶段的工作相对会有一点难度,但是经过这个维度的对比,整个过程思路会更加清晰,而且结果也具有说服力。
我写了如下的两段程序来完成这个基本的工作。
def cmdb_info_batch(request):
return_dict = {}
for vm_ip_addr_s in Cmdb_server.objects.filter(server_status=1).values("server_ip_addr").distinct():
vm_ip_addr = vm_ip_addr_s['server_ip_addr']
db_instance = Cmdb_server.objects.filter(server_ip_addr=vm_ip_addr)[0:1]
if len(db_instance) > 0:
db_type = db_instance[0].server_db_type
else:
db_type = 'others'
ansible_user = get_ansible_user(db_type)
result = ansible_adhoc(ansible_user, vm_ip_addr, "shell", 'date', True)
if len(result['success']) > 0:
print('success:',result['success'])
Cmdb_server.objects.filter(server_ip_addr=vm_ip_addr).update(
server_status=1,
)
if len(result['unreachable']) >0:
print('unreachle:',result['unreachable'])
Cmdb_server.objects.filter(server_ip_addr=vm_ip_addr).update(
server_status=2,
)
if len(result['failed']) >0:
print('failed:',result['failed'])
return return_response(request, 'cmdb/cmdb_info_ext_list.html', return_dict)
def instance_detect_batch(request):
return_dict = {}
for vm_ip_addr_s in Cmdb_server.objects.filter(server_status=1,server_db_type='MySQL').values("server_ip_addr").distinct():
vm_ip_addr = vm_ip_addr_s['server_ip_addr']
result = ansible_adhoc('dba_mysql', vm_ip_addr, "script", '/home/dba_mysql/scripts/get_mysql_info_by_host.sh', True)
#print(result)
if len(result['success']) > 0:
script_db_ports = []
for script_db_port in result['success'][vm_ip_addr]:
db_port = script_db_port.split(' ')[0]
script_db_ports.append(int(db_port))
cmdb_ports = []
for cmdb_port in Cmdb_server.objects.filter(server_ip_addr=vm_ip_addr).values("server_db_port"):
cmdb_ports.append(cmdb_port['server_db_port'])
if len(script_db_ports) > 0:
print(vm_ip_addr,'script_db_ports',script_db_ports, 'is missing in cmdb_db_ports',cmdb_ports,',result:',A_Missing_From_B(script_db_ports,cmdb_ports))
if len(cmdb_ports) > 0:
print(vm_ip_addr,'cmdb_db_ports',cmdb_ports, 'is missing in script_db_ports',script_db_ports,',result:',B_Missing_From_A(script_db_ports,cmdb_ports))
if len(result['unreachable']) > 0:
print('unreachle:',result['unreachable'])
if len(result['failed']) >0:
print('failed:',result['failed'])
return return_response(request, 'cmdb/cmdb_info_ext_list.html', return_dict)
其中涉及到两个列表对比的部分,代码可以参考:
def union_A_AND_B(listA, listB):
return list(set(listA).union(set(listB)))
def A_Missing_From_B(listA, listB):
return list(set(listB).difference(set(listA)))
def B_Missing_From_A(listA, listB):
return list(set(listA).difference(set(listB)))
def main():
listA = [1, 2, 3, 4, 5, 7]
listB = [3, 4, 5, 6, 7]
A_Missing_From_B(listA, listB)
B_Missing_From_A(listA, listB)
一段代码校验后的输出如下:
(u'192.168.xxx.xx', 'script_db_ports', [4323, 4359, 4360], 'is missing in cmdb_db_ports', [4308, 4320, 4322, 4323, 4325, 4350, 4352, 4358, 4359, 4360, 4367, 4377, 4600, 7379, 7380, 7386, 7391, 7392, 7397, 7398, 7399], ',result:', [4320, 4352, 4322, 4325, 4358, 7399, 7392, 7398, 4367, 7379, 7380, 4377, 4600, 4308, 7386, 7391, 4350, 7397])
(u'192.168.xx.xx', 'cmdb_db_ports', [4308, 4320, 4322, 4323, 4325, 4350, 4352, 4358, 4359, 4360, 4367, 4377, 4600, 7379, 7380, 7386, 7391, 7392, 7397, 7398, 7399], 'is missing in script_db_ports', [4323, 4359, 4360], ',result:', [])
可以看到在这个测试环境里,有差不多18个实例没有收录到元数据中,至于具体的信息可以进一步确认,总体来说,到了这个阶段,可以说元数据是基本值得信赖的了。
最后还有一步是最难的,就是需要确认哪些没有收录到元数据中,但是确认存在的实例。这个工作如果满分是五星,可以打到四星了。
对于这个方案,你们有什么好的思路,欢迎提出来。