CMDB项目
运维愿景
- 自动装机
- 配置管理
- 监控
- 堡垒机
- 日志监控
- 资产管理【必备】
为什么开发CMDB?
- 囧境:Excel维护资产信息,资产变更时难以保证Excel表正确性;信息交换不方便。
- 目标:自动采集资产工具,自动汇报,保存变更记录。
- 最终目标:实现运维自动化
了解CMDB架构
a. cmdb架构大概分为三部分:
- 资产采集
- API(接受数据保存入库,对外提供数据接口)
- 后台管理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1. Agent方式 API:Django接收数据并入库 程序:放置在每台服务器 应用场景:针对服务器较多的公司 2. SSH方式 API:Django接收数据并入库 程序:放在中控机 应用场景:针对服务器较少的公司 SSH方式有三种工具,paramiko、Fabric、Ansible,其中Fabric、Ansible内部原理也是通过paramiko来实现得。 paramiko安装:pip3 install paramiko 3. saltstack【python语言】 http://www.cnblogs.com/wupeiqi/articles/6415436.html API:Django接收数据并入库 应用场景:针对服务器较多的公司【推荐】 master: v = subprocess.getoutput('salt "*" cmd.run "ls"') saltstack内部原理是通过RPC来实现得消息队列 4. puppet【ruby语言】 内部原理:puppet客户端每30秒钟自动汇报数据给puppet服务端。 应用场景:主要是针对已经在使用puppet的公司。
b. 主要负责内容: 资产采集
- 三种方案方案:agent、paramiko、saltstack。
- 为了提高扩展性,参考了Django的配置文件和中间件(反射)
- 异常:错误堆栈信息
c. 开发期间遇到得难题(坑):
- 唯一标识【标准化】
CMDB实现目标:实现兼容Agent、SSH、saltstack 以上三种方式。
简易实现方式:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# #################### Agent,每一台服务器一份 #################### # import subprocess # v1 = subprocess.getoutput('ipconfig') # value1 = v1[20:30] # # v2 = subprocess.getoutput('dir') # value2 = v2[0:5] # # # 连接数据库,写到数据库 # # url = "http://127.0.0.1:8000/asset.html" # import requests # # response = requests.post(url,data={'k1':value1,'k2':value2}) # print(response.text) # #################### saltstack ########################## # v = subprocess.getoutput('salt "*" cmd.run "ls"') # #################### Paramiko,中控机放一份 #################### """ - 远程连接服务器,执行命令,获取结果 - 将结果发送API 192.168.11.98 """ import paramiko # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname='192.168.11.98', port=22, username='wupeiqi', password='123') # 执行命令 stdin, stdout, stderr = ssh.exec_command('ls') # 获取命令结果 result = stdout.read() # 关闭连接 ssh.close() value = result[0:10] print(value) url = "http://127.0.0.1:8000/asset.html" import requests response = requests.post(url,data={'k1':value,'k2':value}) print(response.text)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.shortcuts import render,HttpResponse def asset(request): if request.method == "POST": print(request.POST) # 写入到数据 return HttpResponse('1002') else: return HttpResponse('姿势不对')
开发周期:
两三个月
提高扩展性:
参考Django:配置,中间件(反射)
有没有遇到难题:
难题,不应该是技术问题,技术问题都可以攻破。难题应该是业务问题。
- 错误堆栈信息
- Linux不太熟悉
- 唯一标识
唯一标识
- 主机名是唯一标识,依赖本地文件
注意:不建议使用主板SN,虚拟机中的SN号会重复,例如openstack等。
- 流程:
装机前,录入主机名、机房、机柜、机柜位置等信息。 装机时,将服务信息录入CMDB,c1.com。 资产采集:c1.com。
- 步骤:
a. 装系统,初始化软件(CMDB),运行CMDB: - 通过命令获取主机名 - 写入本地指定文件 b. - 将资产信息发送到API c. 获取资产信息: - 判断本地文件主机名和命令获取的主机名是否一致(如果不一致,按照文件中的主机名)
- 最终流程:标准化:主机名不重复;流程标准化(装机同时,主机名在cmdb中设置)
- 服务器资产采集(Agent):
a. 第一次:文件不存在,或内容为空; 采集资产: - 主机名写入文件 - 发送API b. 第N次:采集资产,主机名:文件中获取
服务器资产采集(SSH或Salt):
中控机:获取未采集主机名列表:【c1.com】
- 代码:
server_info = PluginManager().exec_plugin() hostname = server_info['basic']['data']['hostname'] certname = open(settings.CERT_PATH,'r',encoding='utf-8').read().strip() if not certname: with open(settings.CERT_PATH,'w',encoding='utf-8') as f: f.write(hostname) else: server_info['basic']['data']['hostname'] = certname
为什么要进行API验证:
在数据传输过程中保证数据不被篡改,为了保证数据安全,数据只给通过验证的人看
API验证是如何设计的:
这个设计我借鉴了Tornado中的加密Cookie来实现的,根据client_key+time 进行MD5创建动态的KEY,总共有三个限制:第一个,是时间,如果时间超过服务端两秒直接return;第二个,把客户端的ctime取出来,和把事先存到服务端的字符串和客户端一样的那个字符串进行md5加密,用这个加密的结果和客户端发来的加密结果进行对比,如果一样就通过,否则就return;第三个,我们在服务端维护了一个字典,字典中放的是最近2s内访问的client_md5_ctime_key和客户时间+2s组成的键值对,如果传过来的这个值在字典中有的话我们就return,在for循环查字典的时候顺便把超时的删掉,如果通过,就把他放到字典里面。
还有一个问题就是如果黑客的网速比我们快的话(外网会发生),会比我们先到API这个时候我们需要对请求进行加密,这个是借鉴微信的加密方式,也就是AES加密方式。
subprocess参考文档:python基础之常用模块
参考博客:http://www.cnblogs.com/wupeiqi/articles/4786871.html
http://www.cnblogs.com/wupeiqi/articles/4556300.html
http://www.cnblogs.com/nulige/p/6703160.html
http://www.hairuinet.com/python/201704111/index.html