CMDB

Posted 柳姑娘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CMDB相关的知识,希望对你有一定的参考价值。

资产采集的实现方案

1. agent模式
每一台服务器放一份agent程序,subprocess执行采集命令,requests提交数据
优点:简单,采集速度快
应用场景:机器多,性能要求降低

 


2. ssh模式
在服务器和API之间放置一台中控机 用ssh远程连接服务器 ,执行命令,获取结果,并发送给API
应用场景:机器少,性能要求高
优点:无agent 速度慢 ssh方式
例如:fabric ansible 封装了paramiko模块 批量执行命令

 3. salt模式

saltstack(python写的)
在服务器和API之间放置一台中控机,中控机和服务器上分别安装saltstack,中控机上的salt执行命令获取资产信息
master
salve/minion
应用场景:已经用了saltstack 机器多 比ssh速度快
原理:

  1 SaltStack 采用`C/S`模式,server端就是salt的master,client端就是minion,minion与master之间通过`ZeroMQ`消息队列通信。
  2 
  3 minion上线后先与master端联系,把自己的`pub key`发过去,这时master端通过`salt-key -L`命令就会看到minion的key,接受该minion-key后,也就是master与minion已经互信。
  4 
  5 master可以发送任何指令让minion执行了,salt有很多可执行模块,比如说cmd模块,在安装minion的时候已经自带了,它们通常位于你的python库中,`locate salt | grep /usr/`可以看到salt自带的所有东西。
  6 
  7 这些模块是python写成的文件,里面会有好多函数,如cmd.run,当我们执行`salt \'*\' cmd.run \'uptime\'`的时候,master下发任务匹配到的minion上去,minion执行模块函数,并返回结果。
  8 
  9 master监听4505和4506端口,4505对应的是ZMQ的PUB system,用来发送消息,4506对应的是REP system是来接受消息的。
 10 具体步骤如下
 11 
 12 ```
 13 1、Salt stack的Master与Minion之间通过ZeroMq进行消息传递,使用了ZeroMq的发布-订阅模式,连接方式包括tcp,ipc
 14 2、salt命令,将cmd.run ls命令从salt.client.LocalClient.cmd_cli发布到master,获取一个Jodid,根据jobid获取命令执行结果。
 15 3、master接收到命令后,将要执行的命令发送给客户端minion。
 16 4、minion从消息总线上接收到要处理的命令,交给minion._handle_aes处理
 17 5、minion._handle_aes发起一个本地线程调用cmdmod执行ls命令。线程执行完ls后,调用minion._return_pub方法,将执行结果通过消息总线返回给master
 18 6、master接收到客户端返回的结果,调用master._handle_aes方法,将结果写的文件中
 19 7、salt.client.LocalClient.cmd_cli通过轮询获取Job执行结果,将结果输出到终端。
 20 ```
 21 
 22 #### saltstack 安装
 23 
 24 [saltstack install](http://repo.saltstack.com/#rhel)
 25 
 26 #### 修改minion配置文件
 27 ```
 28 [root@linux-node2 ~]# vim /etc/salt/minion
 29 master: 192.168.56.11
 30 [root@linux-node2 ~]# vim /etc/salt/minion
 31 master: 192.168.56.11
 32 [root@linux-node1 pki]# pwd
 33 /etc/salt/pki
 34 [root@linux-node1 pki]# tree
 35 .
 36 ├── master
 37 │   ├── master.pem
 38 │   ├── master.pub
 39 │   ├── minions
 40 │   ├── minions_autosign
 41 │   ├── minions_denied
 42 │   ├── minions_pre
 43 │   │   ├── linux-node1.example.com
 44 │   │   └── linux-node2.example.com
 45 │   └── minions_rejected
 46 └── minion
 47     ├── minion_master.pub
 48     ├── minion.pem
 49     └── minion.pub
 50 [root@linux-node1 pki]# salt-key -A
 51 [root@linux-node1 pki]# tree
 52 .
 53 ├── master
 54 │   ├── master.pem
 55 │   ├── master.pub
 56 │   ├── minions
 57 │   │   ├── linux-node1.example.com
 58 │   │   └── linux-node2.example.com
 59 │   ├── minions_autosign
 60 │   ├── minions_denied
 61 │   ├── minions_pre
 62 │   └── minions_rejected
 63 └── minion
 64     ├── minion_master.pub
 65     ├── minion.pem
 66     └── minion.pub
 67 ```
 68 
 69 #### 远程执行
 70 ```
 71 [root@linux-node1 pki]# salt "*" test.ping
 72 linux-node2.example.com:
 73     True
 74 linux-node1.example.com:
 75     True
 76 [root@linux-node1 pki]# salt "*" cmd.run \'w\'
 77 linux-node1.example.com:
 78      07:20:24 up 17:10,  1 user,  load average: 0.00, 0.01, 0.05
 79     USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
 80     root     pts/0    192.168.56.1     07:04    0.00s  0.30s  0.26s /usr/bin/python /usr/bin/salt * cmd.run w
 81 linux-node2.example.com:
 82      08:26:25 up 22:40,  2 users,  load average: 0.15, 0.05, 0.06
 83     USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
 84     root     tty1                      Sat09   13:12m  0.02s  0.02s -bash
 85     root     pts/0    192.168.56.1     08:09   13:53   0.04s  0.04s -bash
 86 ```
 87 
 88 #### 配置管理
 89 ##### YAML
 90 
 91 - 缩进:
 92   - 两个空格
 93   - 不能使用tab键
 94   - 缩进代表层级关系
 95 
 96 - 冒号:
 97   - key: value
 98 
 99 - 短横线代表list
100 
101 #### satate模块
102 ```
103 # vim /etc/salt/master
104 file_roots:
105   base:
106     - /srv/salt
107 # mkdir /srv/salt
108 # mkdir /srv/salt
109 # cd /srv/salt
110 # mkdir web
111 # cd web
112 # pwd
113 /srv/salt/web
114 # vim apache.sls
115 apache-install:
116   pkg.installed:
117     - names:
118       - httpd
119       - httpd-devel
120 
121 apache-service:
122   service.running:
123     - name: httpd
124     - enable: True
125 
126 # salt \'*\' state.sls web.apache
127  [root@linux-node2 salt]# cd /var/cache/salt/
128 [root@linux-node2 salt]# tree               
129 .
130 `-- minion
131     |-- extmods
132     |-- files
133     |   `-- base
134     |       `-- web
135     |           `-- apache.sls
136     |-- pkg_refresh
137     `-- proc
138         `-- 20160605081351939477 
139 # cat /var/cache/salt/minion/files/base/web/apache.sls 
140 apache-install:
141   pkg.installed:
142     - names:
143       - httpd
144       - httpd-devel
145 
146 apache-service:
147   service.running:
148     - name: httpd
149     - enable: True   
150 # ps -ef|grep yum
151 root      34129  34103  1 08:13 ?        00:00:00 /usr/bin/python /usr/bin/yum --quiet check-update
152 root      34204  34149  0 08:14 pts/1    00:00:00 grep --color=auto yum
153 
154 # cd /srv/salt/
155 # vim top.sls
156 base:
157   \'linux-node1.example.com\':
158     - web.apache
159   \'linux-node2.example.com\':
160     - web.apache
161 # salt \'*\' state.highstate test=True
162 # salt \'*\' state.highstate
163 
164 # lsof -i:4505 -n
165 COMMAND     PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
166 salt-mast 24739 root   13u  IPv4 4637762      0t0  TCP *:4505 (LISTEN)
167 salt-mast 24739 root   15u  IPv4 4640421      0t0  TCP 192.168.56.11:4505->192.168.56.11:48344 (ESTABLISHED)
168 salt-mast 24739 root   16u  IPv4 4640542      0t0  TCP 192.168.56.11:4505->192.168.56.12:53039 (ESTABLISHED)
169 salt-mini 25378 root   25u  IPv4 4640888      0t0  TCP 192.168.56.11:48344->192.168.56.11:4505 (ESTABLISHED)
170 ```
171 
172 #### 数据系统
173 
174 ##### Grains
175 静态数据 当minion启动时收集的minion本地相关信息
View Code

4. puppet(ruby)每30分钟连接一次master,执行一次ruby脚本

场景:公司现在在使用puppet

 

 代码流程:

资产采集部分

     采集资产subprocess,
     兼容性(agent,ssh,salt),
     正则或字符串方法(插件)


1 配置文件:默认配置和自定义配置

2 开发可插拔插件(每个公司采集的资产信息不同)
 
  配置--路径--对应插件(中间件的设计模式)
  插件-反射----init文件(从配置文件中获取插件信息)--pluginmanage (获取和执行插件)
  给插件设置统一的方法process (返回对应信息)

3 解决兼容问题
  方法一:设置基类(做扩展时麻烦)
  方法二:给process传参 commond     在commod函数中先做判断

4    插件的构造方法执行之前自定制一些操作
     @classmethod
     def initial(cls)
        .....
        return cls()
     错误堆栈信息:try  except

     测试模式:debug
      
5 向API发送数据
  从API获取未采集资产
View Code

 

问题:

唯一标识:

周期:2-3个月,3个人
你负责做什么?
  3处借鉴了Django源码的设计模式:
   
     1 默认配置和自定义配置
     2 中间件---插件做成可插拔的模式,增加采集资源的插件时,只要写一个类(命令+结果格式化)
              在配置文件中写上路径,就可以采集资源的信息
             用到了反射
  遇到的难题:唯一标识


1  唯一标识
      所有物理硬件上的标识不能作为唯一标识
           主板SN号:虚拟机的SN号可能相同
           IP地址会变
           Mac地址不准确
 标准化:
   --主机名不重复,作为唯一标识
   --流程标准化
            --资产录入,机房,机柜,机柜位置
            --装机时,需要将服务信息录入CMDB
            --资产采集   

 最终流程:标准化:主机名不重复。流程标准化:装机同时,主机名在cmdb中设置

 步骤:
   agent:
       a. 装系统,初始化软件cmdb,运行cmdb
               --通过命令获取主机名
               --写入本地指定文件
       b. 将资产信息发送到API
       c.获取资产信息
              -本地文件主机名!= 命令获取的主机名(按照文件中的主机名)
              -本地文件住居明==命令获取的文件主机名
   ssh/salt:
       中控机:获取未采集主机名列表
View Code

 

线程池:

 1 2 线程池
 2   提高并发
 3   python2: 进程池
 4   python3:线程池 进程池
 5   代码示例:
 6      from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
 7     
 8      def task(i)
 9          print(i)
10 
11      p=ThreadPoolExecutor(10)
12      for row in range(100)
13           p.submit(task,row)
View Code

 API验证:


为什么要做API验证?
        数据传输过程中,保证数据不被篡改
如何设计?
            --和Tornado中的加密Cookie类似
            --客户端创建动态key md5(key+time)|time
            --服务端 添加限制
                    -- 时间限制
                    -- 算法规则限制
                    -- 已访问记录 2s
                  ps :黑客窃取数据后,速度比正常汇报速度快,解决方法:数据加密 crypto模块 AES

 1 #API验证
 2 # 发令牌  静态, 隐患:易被他人截取
 3 
 4 import requests
 5 key=\'ncjfsvnjsflbvfjslgbvhglbhfbh\'
 6 response=requests.get(\'http://127.0.0.1:8000/api/asset/\',headers={\'openkey\':key})
 7 print(response.text)
 8 
 9 # 改良 动态令牌   隐患:易被他人截取
10 import time
11 import requests
12 import hashlib
13 #
14 ctime=time.time()
15 key=\'vmkdsf;nvfglnbglbngjflbn\'
16 new_key=\'%s|%s\'%(key,ctime)
17 
18 m=hashlib.md5()
19 m.update(bytes(new_key,encoding=\'utf8\'))
20 md5_key=m.hexdigest()
21 
22 md5_time_key=\'%s|%s\'%(md5_key,ctime)
23 response=requests.get(\'http://127.0.0.1:8000/api/asset/\',headers={\'openkey\':md5_time_key})
24 print(response.text)
25 
26 #解决方法
27 #   ---记录已发送的md5_time_key
28 #   ---时间限制:将10s以外的排除
29 #   将两个限制结合起来
30 
31 #隐患:黑客网速快
32 # 不管:搭建内网
33 # 管:数据加密
研究过程

 

最终代码

 1     def post_asset(self,server_info):
 2         #数据加密
 3         server_info=json.dumps(server_info)
 4         server_info=self.xxxxxx(server_info)
 5         #API验证
 6         ctime=time.time()
 7         key=\'vmkdsf;nvfglnbglbngjflbn\'
 8         new_key=\'%s|%s\'%(key,ctime)
 9 
10         m=hashlib.md5()
11         m.update(bytes(new_key,encoding=\'utf8\'))
12         md5_key=m.hexdigest()
13 
14         md5_time_key=\'%s|%s\'%(md5_key,ctime)
15 
16         response=requests.get(
17             url=settings.API,
18             headers={\'openkey\':md5_time_key,\'Content-Type\':\'application/json\'},
19             data=server_info)
20         # response = requests.get(settings.API,headers={\'openkey\': md5_time_key,},json=server_info)
21         return response.text
客户端

 

 1 def api_confirm(func):
 2     def wrapper(request):
 3             api_key_record = {}
 4             client_md5_time_key = request.META.get(\'HTTP_OPENKEY\')
 5             client_md5_key, client_time = client_md5_time_key.split(\'|\')
 6             client_time = float(client_time)
 7             server_time = time.time()
 8 
 9             # 第一关 排除超过10秒的请求
10             if server_time - client_time > 10:
11                 return HttpResponse(\'你网络太慢了吧,重新发\')
12             # 第二关:匹配MD5值
13 
14             temp = "%s|%s" % (settings.AUTH_KEY, client_time,)
15             m = hashlib.md5()
16             m.update(bytes(temp, encoding=\'utf-8\'))
17             server_md5_key = m.hexdigest()
18             if server_md5_key != client_md5_key:
19                 return HttpResponse(\'修改时间了吧,你还嫩点\')
20 
21             # 将过期的MD5值记录删除
22             for k in list(api_key_record.keys()):
23                 v = api_key_record[k]
24                 if server_time > v:
25                     del api_key_record[k]
26 
27             # 第三关:检查此MD5值10秒之内是否访问过
28             if client_md5_time_key in api_key_record:
29                 return HttpResponse(\'是你,是你,就是你,heck\')
30             else:
31                 api_key_record[client_md5_time_key] = client_time + 10
32             return func(request)
33     return wrapper
服务端(装饰器)

 

数据库设计 

 

  1 from django.db import models
  2 
  3 
  4 class UserProfile(models.Model):
  5     """
  6     用户信息
  7     """
  8     name = models.CharField(u\'姓名\', max_length=32)
  9     email = models.EmailField(u\'邮箱\')
 10     phone = models.CharField(u\'座机\', max_length=32)
 11     mobile = models.CharField(u\'手机\', max_length=32)
 12 
 13     class Meta:
 14         verbose_name_plural = "用户表"
 15 
 16     def __str__(self):
 17         return self.name
 18 
 19 
 20 class AdminInfo(models.Model):
 21     """
 22     用户登陆相关信息
 23     """
 24     user_info = models.OneToOneField("UserProfile")
 25     username = models.CharField(u\'用户名\', max_length=64)
 26     password = models.CharField(u\'密码\', max_length=64)
 27 
 28     class Meta:
 29         verbose_name_plural = "管理员表"
 30 
 31     def __str__(self):
 32         return self.user_info.name
 33 
 34 
 35 class UserGroup(models.Model):
 36     """
 37     用户组
 38     """
 39     name = models.CharField(max_length=32, unique=True)
 40     users = models.ManyToManyField(\'UserProfile\')
 41 
 42     class Meta:
 43         verbose_name_plural = "用户组表"
 44 
 45     def __str__(self):
 46         return self.name
 47 
 48 
 49 class BusinessUnit(models.Model):
 50     """
 51     业务线
 52     """
 53     name = models.CharField(\'业务线\', max_length=64, unique=True)
 54     contact = models.ForeignKey(\'UserGroup\', verbose_name=\'业务联系人\', related_name=\'c\')
 55     manager = models.ForeignKey(\'UserGroup\', verbose_name=\'系统管理员\', related_name=\'m\')
 56 
 57     class Meta:
 58         verbose_name_plural = "业务线表"
简易的CMDB服务端

CMDB资产管理

CMDB介绍

CMDB

cmdb简介和入门

CMDB项目管理