IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> cmdb事件推送实现jumpserver资产分组同步 -> 正文阅读

[系统运维]cmdb事件推送实现jumpserver资产分组同步

在这里插入图片描述

前言

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 /F
D:\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 HttpResponse
from .common.main import main
from .zabbix.main import zabbix_main
from .jumpserver.main import jumpserver_main
import json
import logging

logger = logging.getLogger('log')

# Create your views here
def 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.py
import logging
from .hostidentifier_cmdb import hostidentifier
from .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 redis
import json
import hashlib
import 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操作

(1)jumpserver操作入口


import logging
from django.conf import settings
from urllib import request
import json
from .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 logging
from django.conf import settings
import json
import uuid
import 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一侧就可以管理主机资源,不仅节省了我们跨平台处理的时间,而且规范了我们基础设施的管理。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-07-16 11:42:51  更:2021-07-16 11:44:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 16:36:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码