背景:
搭建运维自动化平台【服务器管理和远程控制】
- 自动装机
- 配置管理系统(装什么软件、什么版本)
- 监控系统(值班运维、业务运维、开发)
- 代码发布平台(rsync,git / svn 、比特流)
- 服务器管理(避免人工手动记录维护服务器资产、samb服务【多个运维人员手动维护】;精确、及时了解资产情况;部门合作之间数据交互更方便 (API 数据接口))
目标:
- 自动采集服务器硬件资产信息
- 表报
- API(给其他系统提供数据)
架构设计:
- 采集资产【每台服务器上安装的客户端,agent,定时任务每天凌晨2点】
- API【入库和比较创建变更日志】
- 后台管理部分
要点:
资产管理
- shell命令,和运维同学配合完成,给你命令,负责解析和程序
- requests模块,使用代码实现发送HTTP请求
- 高度可扩展,可插拔式插件,参考Django源码中的中间件(settings配置)。
- 配置文件,为了让用户使用方便,将默认配置文件,放在内部;只让用户做常用配置。
- 继承和传参方式显示:兼容ssh、agent、salt三种方式
- traceback
API:
后台管理:
- 中控端(服务器端主要流程)
#---------------- 中控端(或服务器端)执行主干框架 ------------------ #--------- 流程-----------要点 ------------------ run # script.start() #os.environ 临时设置全局变量的值: os.environ[\'USER_SETTINGS\'] = \'conf.settings\' # ↓↓ # ↓↓ script # start() # from lib.config import settings # 导入设置 # config中 __init__(导入config的同时,会执行其 __init__ ) 中的设置: for item in dir(global_settings): if item.isupper(): k = item v = getattr(global_settings, item) setattr(self, k, v) # 导入用户自定义设置 user_setting_path = os.environ.get(\'USER_SETTINGS\') im_s = importlib.import_module(user_setting_path) for item in dir(im_s): if item.isupper(): k = item v = getattr(im_s, item) if k == "PLUGIN_ITEMS": # 以用户自定义设置为基础,有就添加,没有就新增。同样,这里可以设置忽略某些不希望用户自定义的字段 self.PLUGIN_ITEMS.update(v) else: setattr(self,k,v) settings = Settings() # 先导入全局设置,再导入用户编辑的设置,如果有冲突,用户的设置会覆盖全局的设置,优先级更高 # ↓↓ # ↓↓ client class BaseClient # 线程池 class AgentClient from concurrent.futures import ThreadPoolExecutor # 线程池 class SaltSshClient from concurrent.futures import ProcessPoolExecutor # 进程池 #agent obj = PluginManager(host) #进程池、线程池 使用方法完全一样 server_dict = obj.execute_traversal() #salt host_list = self.get_host_list() # 获取未采集的列表 pool = ThreadPoolExecutor(10) # 线程池 for host in host_list: pool.submit(self.func, host) # ↓↓ # ↓↓ class PluginManager(): def execute_traversal(self): # 逐条信息挨个执行 Traversal——遍历 def execute_cmd(self, cmd): # 每条数据应该怎么获取(有三种配置方式) # 可扩展 # 高度可扩展,可插拔式插件,参考Django源码中的中间件 from src.plugins import PluginManager # PluginManager 写在 plugins 的 __init__ 中 module_path, cls_name = v.rsplit(\'.\', maxsplit=1) module = importlib.import_module(module_path) cls = getattr(module, cls_name) # 取出每条配置信息,将最后的类名和之前的路径分割,通过路径导入类,通过反射执行 # ↓↓ # ↓↓ client class BaseClient class AgentClient #发送: class SaltSshClient # Form表单和默认 ajax 提交: k=v&k=v, # 请求头: content-type: application/x-www-form-urlencoded # 后台:request.POST, application/x-www-form-urlencoded 根据 k=v&k=v, 这种结构解析。 # 定义请求头: $.ajax({ url:\'xxx\', headers:{\'content-type: application/json\'}, data:JSON.stringfy({k1:1,k2:"xx",k2:[1,2,3,4],}) }) # 后台:数据都在 request.body 中,是 json 字符串。 # ↓↓ # ↓↓ # ------------ 数据传到服务端 -------------------------
详细技术要点:
一、配置文件:
二、三种控制服务器的方式
- Agent【*】 (主要执行者是服务器)无中控,服务器中安装 Agent,主动上报信息,速度快,但是占用服务器较多资源,适合服务器数量庞大的公司。
- SSH【**Ansible或Fabric,】(主要执行者是中控),中控通过ssh远程连接服务器,发送命令获取结果,在传回数据。速度很慢,但是不占用服务器资源,适合服务器较少的公司。
- SaltStack【***公司是有自动化工具】(中控、服务器都有代码),有中控,中控将命令传入执行队列,之后在等待队列中等待回传的结果,得到结果后传回信息。所有服务器都在等待命令队列的命令,所有服务器都能获取到队列的所有命令。速度较快。