CMDB项目介绍及简单架构实现
1 CMDB介绍
属于运维自动化项目
1.1 传统运维缺点
- 日常工作繁琐
- 应用运行环境不统一
- 部署效率低
- 无用报警信息多
- 资产管理和应用管理混乱
-
- EXCEL表格记录服务器的资产非常麻烦,会导致服务器的记录越来越乱
1.2 运维自动化可以运维标准化
- OS的选择统一化,同一个项目使用同样的OS系统所需要的各类软件
- 软件安装标准化,例如JAVA虚拟机,php,nginx,mysql等各类应用软件需所需要的版本,安装目录,数据存放目录,日志存放目录等
- 应用包目录统一标准化,及应用命名标准化
- 启动脚本统一目录和名字,需要变化的部分使用参数传递
- 配置文件标准化,需要变化的部分使用参数传递
- 日志输出,日志目录,日志名字标准化
- 应用生成的数据要实现统一的目录存放
- 主机/虚拟机命名的标准化,虚拟机管理使用标准化模板
- 使用docker比较容易实现软件运行的环境标准化
1.3 公司的基本组织架构
- 业务部门
- UI设计
- 开发
- 前端:HTML,CSS,JS,VUE.js
- 后端:不分离项目,接口(Djiango开发)
- 运维
- 项目部署
- 服务器管理(网关)
- 测试
- 功能测试
- 性能测试
- 压力测试而
2 CMDB实现
2.1 项目架构
网站 <-------->数据库 <------------> API <--------------服务器资产
2.2 paramiko模块简单使用
用于远程链接和操控服务器
安装:
pip3 iinstall paramiko
基于用户名密码远程执行
import paramiko # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname='192.168.100.101', port=22, username='root', password='redhat') # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() # 关闭连接 ssh.close() print(result)
执行结果
基于用户名密码上传下载文件
import paramiko transport = paramiko.Transport(('192.168.100.101',22)) transport.connect(username='root',password='redhat') sftp = paramiko.SFTPClient.from_transport(transport) #将本地的test_paramiko_file.txt文件上传到服务器的/tmp下 sftp.put('test_paramiko_file.txt','/tmp/test_paramiko_file.txt') transport.close()
检查服务器/tmp目录
下载结果
密钥连接
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/ningherui/.ssh/id_rsa') # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname='192.168.100.101', port=22, username='root', pkey=private_key) # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() # 关闭连接 ssh.close() print(result.decode('utf-8')) print('--------------------------') print(result.decode('utf-8')[0:9])
执行结果
3 CMDB的简单实现
3.1 创建APP
创建一个autoserver的Django项目,并在这个项目中创建两个App(api和web)
ningherui@ningherui-Lenovo-YOGA-720-15IKB:~/PycharmProjects/autoserver$ python3 manage.py startapp api
ningherui@ningherui-Lenovo-YOGA-720-15IKB:~/PycharmProjects/autoserver$ python3 manage.py startapp web
3.2 开发一个简单的api
配置路由分发
/home/ningherui/PycharmProjects/autoserver/autoserver/urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url,include urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('api.urls')), ]
在api的APP下创建urls
/home/ningherui/PycharmProjects/autoserver/api/urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url,include from api import views urlpatterns = [ url('get_data', views.get_data), ]
定义views上网get_data
/home/ningherui/PycharmProjects/autoserver/api/views.py
from django.shortcuts import render,HttpResponse # Create your views here. def get_data(request): print(request.GET) print(request.POST) return HttpResponse('成功')
运行autoserver的项目
访问http://127.0.0.1:8000/api/get_data 返回成功
3.3 基于paramiko开发脚本收集服务器资产信息
编写一个脚本,定期执行获取服务器的资产信息
import requests def get_server_info(hostname): """ 获取服务器信息 :return: """ import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/ningherui/.ssh/id_rsa') # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname=hostname, port=22, username='root', pkey=private_key) # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() # 关闭连接 ssh.close() #对资产信息进行筛选,筛选出需要的数据 return result.decode('utf-8')[0:9] def run(): #获取服务器的信息 info = get_server_info('192.168.100.101') print('连接远程服务器获取资产信息:',info) #将服务器信息发送到API平台(负责入库) # http://127.0.0.1:8000/api/get_data #需要import requests result = requests.get( url='http://127.0.0.1:8000/api/get_data', params={'host':'192.168.100.101','info':info} ) print('把资产信息发送到API',result.text) if __name__ == '__main__': run()
执行
查看autoserver的程序也收到请求
[09/Feb/2021 04:51:09] "GET /api/get_data?host=192.168.100.101 HTTP/1.1" 200 6 <QueryDict: {'host': ['192.168.100.101']}> <QueryDict: {}> [09/Feb/2021 04:52:30] "GET /api/get_data?host=192.168.100.101 HTTP/1.1" 200 6 [09/Feb/2021 04:55:29] "GET /api/get_data?host=192.168.100.101&info=Filesyste HTTP/1.1" 200 6 <QueryDict: {'host': ['192.168.100.101'], 'info': ['Filesyste']}> <QueryDict: {}>
表示get请求发送成功
3.4 测试POST功能
import requests def get_server_info(hostname): """ 获取服务器信息 :return: """ import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/ningherui/.ssh/id_rsa') # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname=hostname, port=22, username='root', pkey=private_key) # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() # 关闭连接 ssh.close() #对资产信息进行筛选,筛选出需要的数据 return result.decode('utf-8')[0:9] def run(): #获取服务器的信息 info = get_server_info('192.168.100.101') print('连接远程服务器获取资产信息:',info) #将服务器信息发送到API平台(负责入库) # http://127.0.0.1:8000/api/get_data #需要import requests # result = requests.get( # url='http://127.0.0.1:8000/api/get_data', # params={'host':'192.168.100.101','info':info} # ) result = requests.post( url='http://127.0.0.1:8000/api/get_data', data={'host':'192.168.100.101','info':info} ) print('把资产信息发送到API',result.text) if __name__ == '__main__': run()
执行有CSRF认证,403错误
使用装饰器跳过csrf的认证
/home/ningherui/PycharmProjects/autoserver/api/views.py
from django.shortcuts import render,HttpResponse from django.views.decorators.csrf import csrf_exempt # Create your views here.
#http请求头:content-type(请求数据格式)
#有时候当不能使用request.GET 和request.POST获取时,可以使用request.body获取 @csrf_exempt def get_data(request): print(request.GET) print(request.POST) return HttpResponse('成功')
再次执行,成功
查看autoserver结果
<QueryDict: {}> <QueryDict: {'host': ['192.168.100.101'], 'info': ['Filesyste']}> [09/Feb/2021 05:15:26] "POST /api/get_data HTTP/1.1" 200 6
获取数据之后,需要把数据放入数据库,使用web页面显示
3.5 配置web页面功能
配置web路由
/home/ningherui/PycharmProjects/autoserver/autoserver/urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url,include from web import views urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('api.urls')), path('index/', views.index), ]
配置web的view
/home/ningherui/PycharmProjects/autoserver/web/views.py
from django.shortcuts import render # Create your views here. def index(request): """ 后台管理首页 :param request: :return: """ return render(request,'index.html')
开发indexl.html页面,删除autoserver本来的templates,在web下创建新的templates,并创建一个新的index.html
/home/ningherui/PycharmProjects/autoserver/web/templates/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>你好,世界</h1> </body> </html>
访问http://127.0.0.1:8000/index/
这时并不能直接访问,找不到页面,需要在autoserver中注册APP
/home/ningherui/PycharmProjects/autoserver/autoserver/settings.py
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'api.apps.ApiConfig', 'web.apps.WebConfig' ]
再次访问http://127.0.0.1:8000/index/
4 CMDB实现过程
中控机通过Paramiko(py模块)登录到各个服务器上,然后执行命令的方式去获取各个服务器上的信息
优点:无Agent 缺点:速度慢
CMDB由三部分组成,分别是:后台管理,API接口部分,采集资产部分
采集资产:
- 通过paramiko模块基于ssl创建连接,并进行远程命令的执行,以此获取服务器的资产信息然后再进行资产信息的筛选(结构化),然后将资产信息通过api接口发送到服务端
API接口:
- 接收采集的资产信息,并负责入库.
- 资产变更记录处理
- 给第三方程序提供接口
后台管理: 为运维或运维经理提供交互,管理资产,数据统计报表等
5 使用json格式传输数据
Django开发的Request数据读取
- 读取request.body,原始数据:username=ajex&password=asdc
- Django读取Content-Type请求头,如果请求头是application/x-www-form-urlencodes,那么django就会解析request.body的数据,生成一个QueryDict对象(类似与字典),然后将字典赋值给request.POST
request.POST.get('username')
request.POST.get('password')
代码如下:
/home/ningherui/PycharmProjects/djangoProject1/paramiko_module/paramiko_study/app.py
import requests def get_server_info(hostname): """ 获取服务器信息 :return: """ import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/ningherui/.ssh/id_rsa') # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname=hostname, port=22, username='root', pkey=private_key) # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() # 关闭连接 ssh.close() #对资产信息进行筛选,筛选出需要的数据 return result.decode('utf-8')[0:9] def run(): #获取服务器的信息 info = get_server_info('192.168.100.101') print('连接远程服务器获取资产信息:',info) #将服务器信息发送到API平台(负责入库) # http://127.0.0.1:8000/api/get_data #需要import requests # result = requests.get( # url='http://127.0.0.1:8000/api/get_data', # params={'host':'192.168.100.101','info':info} # ) # result = requests.post( # url='http://127.0.0.1:8000/api/get_data', # data={'host':'192.168.100.101','info':info} # ) #使用json格式数据传输 result = requests.post( url='http://127.0.0.1:8000/api/get_data', json={'host': '192.168.100.101', 'info': info} ) print('把资产信息发送到API',result.text) if __name__ == '__main__': run()
/home/ningherui/PycharmProjects/autoserver/api/views.py
from django.shortcuts import render,HttpResponse from django.views.decorators.csrf import csrf_exempt # Create your views here. @csrf_exempt def get_data(request): print(request.body) #序列化和反序列化 data_str = request.body.decode('utf-8') import json data_json = json.loads(data_str) print(data_str,type(data_str)) print(data_json) print(request.GET) print(request.POST) host= request.POST.get('host') info = request.POST.get('info') #获取数据之后,把他们放到数据库,然后使用web的APP展示数据 return HttpResponse('成功')
结果如下:
Quit the server with CONTROL-C. b'{"host": "192.168.100.101", "info": "Filesyste"}' {"host": "192.168.100.101", "info": "Filesyste"} <class 'str'> {'host': '192.168.100.101', 'info': 'Filesyste'} <QueryDict: {}> <QueryDict: {}>
views修改为
import json from django.shortcuts import render,HttpResponse from django.views.decorators.csrf import csrf_exempt # Create your views here. @csrf_exempt def get_data(request): print(request.body) #序列化和反序列化 content = request.body.decode('utf-8') server_info_dict = json.loads(content) print(server_info_dict) #获取数据之后,把他们放到数据库,然后使用web的APP展示数据 return HttpResponse('成功')
感谢老男孩教育的公开课视频