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对应的数据行从数据库中删掉