IT運維,指的是對已經搭建好的網絡,軟件,硬件進行維護。運維領域也是細分的,有硬件運維和軟件運維。php
硬件運維主要包括對基礎設施的運維,好比機房的設備,主機的硬盤,內存這些物理設備的維護。前端
軟件運維主要包括系統運維和應用運維,系統運維主要包括對OS,數據庫,中間件的監控和維護,這些系統介於設備和應用之間,應用運維主要是對線上業務系統的運維。python
平常運維工做是比較繁瑣的,研發同窗會常常須要到服務器上查日誌,重啓應用,或者是說今天上線某個產品,須要部署下環境。這些雜事是傳統運維的大部分工做。mysql
在部署某應用後,應用不能訪問,就會聽到開發人員說,在個人環境運行很好的,怎麼部署到測試環境後,就不能用了,由於各種環境的類庫不統一
還有一種極端狀況,運維人員習慣不一樣,可能憑本身的習慣來安裝部署軟件,每種服務器上運行軟件的目錄不統一。linux
想一想運維人員須要登錄到服務器上執行命令,部署程序,不只效率很低,而且很是容易出現人爲的錯誤,一旦手工出錯,追溯問題將會很是不容易。nginx
常常會收到不少報警信息,多數是無用的報警信息,形成運維人員常常屏蔽報警信。
另外若是應用的訪問速度出了問題,老是須要從系統、網絡、應用、數據庫等一步步的查找緣由。web
資產管理,服務管理常常記錄在excel、文本文件或者wiki中,不便於管理,老員工由於比較熟,不注重這些文檔的維護,只有靠每次有新員工入職時,資產纔可以更正一次。面試
針對傳統運維的痛點,咱們能夠知道自動化運維須要支持哪些功能sql
運維自動化最重要的就是標準化一切docker
CMDB是全部運維工具的數據基礎
Agent方式,能夠將服務器上面的Agent程序做定時任務,定時將資產信息提交到指定API錄入數據庫。
其本質上就是在各個服務器上執行subprocess.getoutput()
命令,而後將每臺機器上執行的結果,返回給主機API,而後主機API收到這些數據以後,放入到數據庫中,最終經過web界面展示給用戶。
優勢:速度快
缺點:須要爲每臺服務器部署一個Agent程序
場景:服務器多的時候
中控機經過Paramiko(py模塊)登陸到各個服務器上,而後執行命令的方式去獲取各個服務器上的信息。
優勢:無Agent
缺點:速度慢
場景:服務器少的時候
若是在服務器較少的狀況下,可應用此方法
import paramiko # 建立SSH對象 ssh = paramiko.SSHClient() # 容許鏈接不在know_hosts文件中的主機 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 鏈接服務器 ssh.connect(hostname='c1.salt.com', port=22, username='root', password='123') # 執行命令 stdin, stdout, stderr = ssh.exec_command('df') # 獲取命令結果 result = stdout.read() # 關閉鏈接 ssh.close()
此方案本質上和第二種方案大體是差很少的流程,中控機發送命令給服務器執行。服務器將結果放入另外一個隊列中,中控機獲取將服務信息發送到API進而錄入數據庫。
優勢:快,開發成本低
缺點:依賴於第三方工具
a.公司要作自動化運維相關的系統,CMDB是必作的一個項目
b.以前採起的是Excel表格進行管理數據,所以修改數據的話會變的很亂
2.CMDB的架構是什麼?
agent、ssh類、salt-stack
數據採集
a.參考了Django的配置文件的設置(整合了自定義的配置文件以及默認的配置文件)
b.參考了Django的中間件的寫法和用法,完成了一套可插拔式的採集插件
數據分析
數據展現(圖表展現)
a.linux的命令不熟悉 -->百度或者問運維
b.字符串導模塊 -->importlib
c.溝通問題(產品經理)
d.惟一標識問題
一、 5~6個月
1個月:調研 排期 溝通 設計方案 選擇方案
1~2個月:先上一個1.0版本(不要求代碼寫的多好,要求寫的快,最主要的功能都要有)
2~3個月:不斷的迭代項目(包括需求增長,代碼的迭代,前端的展現剛開始用的原生的js第二次升級迭代使用Vue,本身寫接口(drf))
二、通常後端2-3我的 前端1我的
三、創業公司:幾十臺
post的數據獲取
若是header:content-type:application/x-www-form-urlencoded
request.body纔會將數據封裝給request.POST方法
a.requests.post(settings.API_URL,data=json.dumps(res))
b.requests.post(settings.API_URL,json=res)
核心代碼:
hostnameList = self.get_hostnames() from concurrent.futures import ThreadPoolExecuyor p = ThreadPoolExecuyor(10) for hostname in hostnameList: p.submit(self.task,hostname)
如今的作法:
取SN做爲惟一標識,來 獲取老的數據
改進的作法:
1.業務邏輯解決:若是公司不採集虛擬機的信息,直接用sn
2.用hostname作惟一標識
agent須要遵照的步驟:
a.裝機完成以後,須要給每一臺服務器分配一個惟一的主機名 b.將分配好的主機名錄入到web管理系統中 #所以,在沒有收集資產的狀況下,數據庫中已經錄好了主機的主機名 c.將採集的客戶端代碼放到服務器的某一個目錄下面,而後開始定時執行代碼腳本 b.開始第一次採集 #將主機名(c1.com)記錄到一個文件中 e.將服務器分配給開發用 f.12點開始收集資產信息,11.59,修改了主機名,c1.com-->c2000.com,彙報數據的時候,永遠以第一次採集的文件中的主機名爲標準
第一種方式:
服務器
server_token = "bdsjabfjsldabjfdsnbajfndjakfnjdsanfjd" client_token = requests.META.get("HTTP_TOKEN") if server_token != client_token: return HttpResponse("非法用戶")
客戶端
import requests client_token = "bdsjabfjsldabjfdsnbajfndjakfnjdsanfjd" res = requests.get('http://127.0.0.1:8000/api/',headers={"Token":client_token})
第二種方式
加密和加鹽
if server_time - client_time > 5: return HttpResponse('你超時了') tmp = "%s|%s" % (server_token, client_time) m = hashlib.md5() m.update(bytes(tmp, encoding='utf-8')) server_md5 = m.hexdigest() if client_md5 != server_md5: return HttpResponse('數據被修改了') if client_md5_token in key_record: return HttpResponse('已經被訪問過了') else: key_record[client_md5_token] = client_time + 10 return HttpResponse('很是重要的信息')
api:接受採集到的數據
backend:後臺數據管理展現界面
repository:專門管理db數據表的
from django.db import models # Create your models here. class UserProfile(models.Model): name = models.CharField(verbose_name=u'姓名', max_length=32) email = models.EmailField(verbose_name=u'郵箱') phone = models.CharField(verbose_name=u'座機', max_length=32) mobile = models.CharField(verbose_name=u'手機', max_length=32) password = models.CharField(verbose_name=u'密碼', max_length=64) class Meta: verbose_name = '用戶表' verbose_name_plural = verbose_name def __str__(self): return self.name class UserGroup(models.Model): name = models.CharField(max_length=32, unique=True) users = models.ManyToManyField(to='UserProfile') class Meta: verbose_name = '用戶組表' verbose_name_plural = verbose_name def __str__(self): return self.name class BusinessUnit(models.Model): name = models.CharField(verbose_name=u'業務線', max_length=64, unique=True) contact = models.ForeignKey(to='UserGroup', verbose_name=u'業務聯繫人', related_name='c') manager = models.ForeignKey(to='UserGroup', verbose_name=u'系統管理員', related_name='m') class Meta: verbose_name = '業務線表' verbose_name_plural = verbose_name def __str__(self): return self.name class IDC(models.Model): name = models.CharField(verbose_name=u'機房', max_length=32) floor = models.IntegerField(verbose_name=u'樓層', default=1) class Meta: verbose_name = '機房表' verbose_name_plural = verbose_name def __str__(self): return self.name class Tag(models.Model): name = models.CharField(verbose_name=u'標籤', max_length=32, unique=True) class Meta: verbose_name = '標籤表' verbose_name_plural = verbose_name def __str__(self): return self.name class Server(models.Model): device_type_choices = ( (1, '服務器'), (2, '交換機'), (3, '防火牆'), ) device_status_choices = ( (1, '上架'), (2, '在線'), (3, '離線'), (4, '下架'), ) device_type_id = models.IntegerField(verbose_name=u'服務器類型', choices=device_type_choices, default=1) device_status_id = models.IntegerField(verbose_name=u'服務器狀態', choices=device_status_choices, default=1) cabinet_num = models.CharField(verbose_name=u'機櫃號', max_length=30, null=True, blank=True) cabinet_order = models.CharField(verbose_name=u'機櫃中序號', max_length=30, null=True, blank=True) idc = models.ForeignKey(to="IDC", verbose_name=u'IDC機房', null=True, blank=True) business_unit = models.ForeignKey(to='BusinessUnit', verbose_name=u'屬於的專業線', null=True, blank=True) tag = models.ManyToManyField(to='Tag') hostname = models.CharField(verbose_name=u'主機名', max_length=128, unique=True) sn = models.CharField(verbose_name=u'SN號', max_length=64, db_index=True) manufacturer = models.CharField(verbose_name=u'製造商', max_length=64, null=True, blank=True) model = models.CharField(verbose_name=u'型號', max_length=64, null=True, blank=True) manager_id = models.GenericIPAddressField(verbose_name=u'管理IP', null=True, blank=True) os_platform = models.CharField(verbose_name=u'系統', max_length=16, null=True, blank=True) os_version = models.CharField(verbose_name=u'系統版本', max_length=32, null=True, blank=True) cpu_count = models.IntegerField(verbose_name=u'CPU個數', null=True, blank=True) cpu_physical_count = models.IntegerField(verbose_name=u'CUP物理個數', null=True, blank=True) cpu_model = models.CharField(verbose_name=u'CPU型號', max_length=128, null=True, blank=True) create_at = models.DateTimeField(auto_now_add=True, blank=True) class Meta: verbose_name = '服務器表' verbose_name_plural = verbose_name def __str__(self): return self.hostname class Disk(models.Model): slot = models.CharField(verbose_name='插槽位', max_length=8) model = models.CharField(verbose_name=u'磁盤型號', max_length=32) capacity = models.CharField(verbose_name=u'磁盤容量GB', max_length=32) pd_type = models.CharField(verbose_name=u'磁盤類型', max_length=32) server_object = models.ForeignKey(to='Server', related_name='disk') class Meta: verbose_name = '硬盤表' verbose_name_plural = verbose_name def __str__(self): return self.slot class NIC(models.Model): name = models.CharField(verbose_name=u'網卡名稱', max_length=128) hwaddr = models.CharField(verbose_name=u'網卡mac地址', max_length=64) netmask = models.CharField(max_length=64) ipaddrs = models.CharField(verbose_name=u'ip地址', max_length=256) up = models.BooleanField(default=False) server_object = models.ForeignKey(to='Server', related_name='nic') class Meta: verbose_name = '網卡表' verbose_name_plural = verbose_name def __str__(self): return self.name class Memory(models.Model): slot = models.CharField(verbose_name=u'插槽位', max_length=32) manufacturer = models.CharField(verbose_name=u'製造商', max_length=32, null=True, blank=True) model = models.CharField(verbose_name=u'型號', max_length=64) capacity = models.FloatField(verbose_name=u'容量', null=True, blank=True) sn = models.CharField(verbose_name=u'內存SN號', max_length=64, null=True, blank=True) speed = models.CharField(verbose_name=u'速度', max_length=16, null=True, blank=True) server_object = models.ForeignKey(to='Server', related_name='memory') class Meta: verbose_name = '內存表' verbose_name_plural = verbose_name def __str__(self): return self.slot class AssetRecord(models.Model): assert_object = models.ForeignKey(to='Server', related_name='ar') content = models.TextField(null=True) creator = models.ForeignKey(to='UserProfile', null=True, blank=True) create_at = models.DateTimeField(auto_now_add=True) class Meta: verbose_name = '資產記錄表' verbose_name_plural = verbose_name def __str__(self): return "%s-%s-%s" % ( self.assert_object.idc.name, self.assert_object.cabinet_num, self.assert_object.cabinet_order) class ErrorLog(models.Model): assert_object = models.ForeignKey(to='Server', null=True, blank=True) title = models.CharField(max_length=16) content = models.TextField() create_at = models.DateTimeField(auto_now_add=True) class Meta: verbose_name = '錯誤日誌表' verbose_name_plural = verbose_name def __str__(self): return self.title
磁盤清洗:
增:新的slot有,老的slot沒有,將新的slot插入到數據庫中
刪:新的沒有,老的有,將老的slot對應的數據行從數據庫中刪掉