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('成功')
感謝老男孩教育的公開課視頻