查看原文
其他

cmdb事件推送实现jumpserver资产分组同步

木讷大叔爱运维 木讷大叔爱运维 2022-07-13




读完需 7 分钟

速读需 3 分钟 



前言

cmdb事件推送实现zabbix资产同步》一文实现了cmdb和zabbix的资产同步,接下来我们就离着《运维思索:cmdb打通zabbix、jumpserver探索》这个小目标就不远了。


言归正传,jumpserver的资产分组同步,即jumpserver的资产列表与cmdb的业务拓扑保持一致,按照业务--集群--模块的树形结构分布。



而cmdb和jumpserver的同步思路与前面基本保持一致,即:

  1. 主机标识更新

    只有当主机转移至相关模块时,才会触发业务、集群、模块(例如分别对应消金生产环境--运维平台--禅道)的节点创建;而在cmdb侧只创建空的集群、模块时不会触发jumpserver同步,以免导致创建空节点。

  2. 集群、模块删除操作

    cmdb只有在集群和模块下资产都为空的情况才能执行删除,这个策略和jumpserver一致,因此在主机标识更新保证资产粒度级别的分组一致后,删除操作就不是问题了。

  3. 主机导入

    腾讯蓝鲸实现vsphere虚拟机交付》一文我们通过蓝鲸标准运维已经实现了新建主机在jumpserver中创建、自动注册到cmdb,在保证主机上架流程前提下,我们可以认为所有的主机默认都是在cmdb和jumpserver中已经存在的,我们只需保证jumpserver资产分组和cmdb一致即可。


注意:由于时间的问题,我们本文只介绍“cmdb主机标识更新”触发的jumpserver资产分组同步。


目录结构

我们在gateway网关中,增加了jumpserver模块用于实现资产分组同步。

D:\work\blueking>tree gateway /FD:\WORK\BLUEKING\GATEWAY│ .gitignore│ README.md├─.vscode│ settings.json└─gateway │ manage.py ├─.vscode │ settings.json ├─gateway │ asgi.py │ settings.py │ urls.py │ wsgi.py │ __init__.py └─gw_cmdb │ admin.py │ apps.py │ models.py │ tests.py │ urls.py │ views.py │ __init__.py ├─common │ hostidentifier_cmdb.py │ main.py │ module_cmdb.py │ select_cmdb.py ├─jumpserver │ api.py │ main.py └─zabbix group.py host.py main.py template.py

其中:

common目录是与cmdb相关的模块:

  • main 接收事件推送网关推送过来的参数;

  • hostidentifier_cmdb  针对主机相关事件推送返回格式化参数;

  • module_cmdb 针对模块相关事件推送返回格式化参数;

  • select_cmdb   查询cmdb内容如集群、业务、操作系统等辅助信息;


jumpserver目录是与jumpserver相关的模块:

  • main 解析格式化参数,对jumpserver做相应的处理;

  • api是对按官方jumpserver api进行的重新封装,实现对节点、资产等的操作;


由于分组同步可以在不影响zabbix使用的情况下操作,因此我们在此着重介绍此功能。


分组同步


1

接收cmdb推送参数


cmdb事件推送将参数发送给网关,由views.py接收,json格式数据为:

其中:

  • obj_type,主机标识更新:hostidentifier

  • action, 主机动作:update

  • bk_biz_name ,业务名称:消金生产环境

  • bk_set_name,集群名称:运维平台

  • bk_module_name,模块名称:禅道

  • bk_host_innerip,主机ip:10.166.202.10


from django.http import HttpResponsefrom .common.main import mainfrom .zabbix.main import zabbix_mainfrom .jumpserver.main import jumpserver_mainimport jsonimport logging
logger = logging.getLogger('log')
# Create your views heredef cmdb_request(request): if request.method == 'POST': data = json.loads(request.body) logger.info('cmdb发送消息:{}'.format(data)) ## 整理cmdb数据 res=main(data) ##是否需要联动zabbix及jumpserver if res['result'] == 1: return HttpResponse("ok") else: logger.info(res) #zabbix同步 zabbix_request = zabbix_main(res) logger.info('zabbix 同步完毕:{}'.format(zabbix_request)) #jumpserver同步 jumpserver_request = jumpserver_main(res) logger.info('jumpserver 同步完毕:{}'.format(jumpserver_request)) return HttpResponse("ok") else: logger.info('本接口只支持POST模式') return HttpResponse("本接口只支持POST模式")


2

解析参数


(1)common将views接收的请求。

vim common/main.pyimport loggingfrom .hostidentifier_cmdb import hostidentifierfrom .module_cmdb import module_action
logger = logging.getLogger('log')
def main(data): result = {'result': 1,'data': 0} ## 模块操作 if data['obj_type'] == 'module': return module_action(data) ## 主机标识操作 elif data['obj_type'] == 'hostidentifier': if data['action'] == 'update' and data['event_type'] == 'relation' : logger.info("主机标识更新: {}".format(data)) return hostidentifier(data) else: logger.info("主机标识未知操作: {}".format(data)) else: logger.info("未知操作: {}".format(data)) return result

(2)主机标识解析

cmdb主机模块转移可能会触发多次请求,因此我们需要借助redis将请求进行去重。

import redisimport jsonimport hashlibimport logging
logger = logging.getLogger('log')
r = redis.StrictRedis(host='127.0.0.1',port=6379,db=1)
## 模块变更获取主机所有模板定制分组def hostidentifier(data): ##定义数据格式 datajson= {'tex_id': '','action': data['action'],'obj_type': data['obj_type'],'data': {'cur_data': {'ip': '','group': []},'bk_host_id':data['data']['cur_data']['bk_host_id'],'pre_data': 'None'},'result': 1} ## 获取主机组信息,并清理记录reids去除重复会话 for i in data['data']: datajson['data']['cur_data']['ip'] = i['cur_data']['bk_host_innerip'] grouplist = i['cur_data']['associations'] for j in grouplist: groupname = grouplist[j]['bk_biz_name']+"_"+grouplist[j]['bk_set_name']+"_"+grouplist[j]['bk_module_name'] datajson['data']['cur_data']['group'].append(groupname) datajson['tex_id']= hashlib.md5((data['request_id']+ i['cur_data']['bk_host_innerip']).encode('utf-8')).hexdigest() rkey = r.hget('cmdb',datajson['tex_id']) logger.info(rkey) if rkey is None: r.hset('cmdb',datajson['tex_id'],json.dumps(datajson['data'])) datajson['result'] = 0 logger.info(datajson) return datajson


3

jumpserver操作


当common将cmdb事件的参数解析后,就可传给jumpserver模块进行相应的分组同步操作了。


(1)jumpserver操作入口


import loggingfrom django.conf import settingsfrom urllib import requestimport jsonfrom .api import Assets
logger = logging.getLogger('log')
def jumpserver_main(data): """ jumpserver api入口函数,只对主机标识更新响应 """ if data['obj_type'] == 'hostidentifier': if data['action'] == 'update': cur_data = data['data']['cur_data'] assets = Assets(cur_data) assets.perform() else: logger.info("主机标识未知操作: {}".format(data)) else: logger.info("未知操作: {}".format(data))
return data

(2)jumpserver api操作

import loggingfrom django.conf import settingsimport jsonimport uuidimport requests
logger = logging.getLogger('log')
class HTTP: server = settings.JUMPSERVER_BASEURL
@classmethod def get(cls, url, params=None, **kwargs): url = cls.server + url headers = settings.JUMPSERVER_HEADERS kwargs['headers'] = headers res = requests.get(url, params, **kwargs) return res
@classmethod def post(cls, url, data=None, json=None, **kwargs): url = cls.server + url headers = settings.JUMPSERVER_HEADERS kwargs['headers'] = headers res = requests.post(url, data, json, **kwargs) return res
@classmethod def put(cls, url, data=None, **kwargs): url = cls.server + url headers = settings.JUMPSERVER_HEADERS kwargs['headers'] = headers res = requests.put(url, data, **kwargs) return res
class Node(object):
def __init__(self, *args): self.id = '' self.name = None self.group = args self.full_value = "/Default"
def exist(self): url = '/api/v1/assets/nodes/' logger.info('group Is {}'.format(self.group)) for item in self.group[0].split('_'): self.name = item params = {'value': self.name} res = HTTP.get(url, params=params) res_data = res.json() if res.status_code in [200, 201] and res_data: self.id = res_data[0].get('id') self.full_value = res_data[0].get('full_value') logger.info('节点已存在 {}'.format(self.full_value)) else: self.create() return self.id
def create(self): url = '/api/v1/assets/nodes/' + str(self.id) + '/children/' data = { 'id': str(uuid.uuid1()), 'value': self.name, 'full_value': self.full_value } if self.full_value == "/Default": url = '/api/v1/assets/nodes/' logger.info('url Is {}'.format(url)) logger.info('data Is {}'.format(data)) res = HTTP.post(url, json=data) res_data = res.json() if res.status_code in [200, 201] and res_data: self.id = res_data.get('id') self.full_value = res_data.get('full_value')            logger.info('节点创建成功: {}'.format(res_data))          else: logger.info('节点创建失败:{}'.format(res_data))
return self.id
def delete(self): pass
def perform(self): self.exist() return self.id
class Assets(object): def __init__(self, *args): self.id = None self.node = None self.nodeid = [] self.hostname = None self.platform = None self.ip = args[0].get('ip') self.group = args[0].get('group') def exist(self): url = '/api/v1/assets/assets/' params = { 'ip': self.ip } res = HTTP.get(url, params) res_data = res.json() if res.status_code in [200, 201] and res_data: self.id = res_data[0].get('id') self.hostname = res_data[0].get('hostname') self.platform = res_data[0].get('platform')            logger.info('资产查询成功: {}'.format(res_data))          self.update() else: self.create()
def create(self): pass
def update(self): url = "/api/v1/assets/assets/" + self.id + "/" params = { 'hostname': self.hostname, 'ip': self.ip, 'platform': self.platform, 'nodes': self.nodeid } res = HTTP.put(url, json.dumps(params)) res_data = res.json() if res.status_code in [200, 201] and res_data: self.id = res_data.get('id')            logger.info('资产更新成功: {}'.format(res_data))          else: logger.info('资产更新失败:{}'.format(res_data))
def perform(self): for group in self.group: self.node = Node(group) self.nodeid.append(self.node.perform()) self.exist() logger.info('nodeid Is {}'.format(self.nodeid))


4

操作


(1)cmdb侧主机转移模块

(2)解析过程

(3)最终效果

总结

通过事件推送网关我们初步实现了cmdb和jumpserver的分组同步,我们只需要在cmdb一侧就可以管理主机资源,不仅节省了我们跨平台处理的时间,而且规范了我们基础设施的管理。



cmdb事件推送实现zabbix资产同步

事件推送网关:让cmdb告别“花瓶”

运维思索:cmdb打通zabbix、jumpserver探索

腾讯蓝鲸实现vsphere虚拟机交付

蓝鲸实现虚拟机交付-跳板机管理(JUMP)

蓝鲸实现虚拟机交付-配置平台(CMDB)



你与世界

只差一个

公众号




您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存