CMDB资产采集
Paramiko
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', key=private_key) # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() # 关闭连接 ssh.close()
SaltStack
1. 安装和配置
""" 1. 安装salt-master yum install salt-master 2. 修改配置文件:/etc/salt/master interface: 0.0.0.0 # 表示Master的IP 3. 启动 service salt-master start """
""" 1. 安装salt-minion yum install salt-minion 2. 修改配置文件 /etc/salt/minion master: 10.211.55.4 # master的地址 或 master: - 10.211.55.4 - 10.211.55.5 random_master: True id: c2.salt.com # 客户端在salt-master中显示的唯一ID 3. 启动 service salt-minion start """
2. 授权 salt-key -A 给所有的minion机授权
""" salt-key -L # 查看已授权和未授权的slave salt-key -a salve_id # 接受指定id的salve salt-key -r salve_id # 拒绝指定id的salve salt-key -d salve_id # 删除指定id的salve """
3. 执行命令
在master服务器上对salve进行远程操作
salt 'c2.salt.com' cmd.run 'ifconfig'
import salt.client local = salt.client.LocalClient() result = local.cmd('c2.salt.com', 'cmd.run', ['ifconfig'])
运维愿景
- 自动装机
- 配置管理
- 监控
- 堡垒机
- 资产管理【必备】
目前状况
- 目前很多公司还是:手动维护Excel表格
- 急需:资产自动采集并汇报入库
- 解决办法:CMDB - 配置管理数据库(资产管理)
如果实现自动采集?
1. Agent方式 API:Django接收数据并入库 程序:放置在每台服务器 应用场景:针对服务器较多的公司 2. SSH方式 API:Django接收数据并入库 程序:放在中控机 应用场景:针对服务器较少的公司 SSH方式有三种工具,paramiko、Fabric、Ansible,其中Fabric、Ansible内部原理也是通过paramiko来实现得。 paramiko安装:pip3 install paramiko 3. saltstack【python语言】 http://www.cnblogs.com/wupeiqi/articles/6415436.html API:Django接收数据并入库 应用场景:针对服务器较多的公司【推荐】 master: v = subprocess.getoutput('salt "*" cmd.run "ls"') saltstack内部原理是通过RPC来实现得消息队列 4. puppet【ruby语言】 内部原理:puppet客户端每30秒钟自动汇报数据给puppet服务端。 应用场景:主要是针对已经在使用puppet的公司。
CMDB实现目标:实现兼容Agent、SSH、saltstack 以上三种方式。
三层架构
数据访问层
业务处理层
UI展示层
原理草图:
一、CMDB项目大体攻略: 1.先建目录 bin #可执行文件 config #配置文件 lib #公共的模块 src #业务逻辑 2.配置文件 settings 一般都是大写,放自定制配值文件 自定义配置文件 默认配置文件 在lib里面写个目录conf在目录中建立一个config.py和global_settings.py第一个文件是放逻辑的,让自定义配置文件和默认配置文件结合起来, ****整合技巧 PS: import os os.environ['USER_SETTINGS']="config.settings" 3.开发插件(可插拔) 公司采集资产有差别 默认采集: basic #主机名,系统版本,系统类型 board #主板 cpu disk memory #内存 nic #网卡 定义插件: class xxxx(object): def process(self): return '1331321321321' 把这些插件都放到settings里面 4.向API获取发送数据 AGENT: 向API发送资产信息 SSH、SALT: 整个流程的开始应该是从API接口开始,先从这里拿到没有采集的主机列表获取未采集的主机列表:[c1.com,c2.com] for host in 主机列表: host采集资产,发送到API 二、为什么要开发CMDB Excel维护资产信息,资产变更时难以保证Excel表正确性;信息交换不方便 自动采集资产工具,目标:自动汇报,保存变更记录 最终目标:实现运维自动化 三、CMDB架构: 资产采集 API(两个功能:接收数据保存入库,对外提供数据接口比如有人访问指定的url就能拿到指定主机的详细信息都展示出来) 后台管理(对资产进行增删改查) 四、开发程序时你负责做什么 周期:将近三个月 三个人负责,我负责资产采集(那个简单说那个) 调研提出三种方案:agent paramiko saltstack 三种方案,三种都兼容,为了提高 扩展性,配置文件(自定义和默认)和中间件(反射)参考Django: 五、有没有遇到难题(技术的难题不是难题,业务的难题才是难题) Linux不太熟,命令都不知道该用啥 唯一标识:大问题,一开始用的是主板的SN号,当初我们认为他就是唯一标识, 物理机的话SN号是唯一的,openstack虚拟机和物理机的SN号是一样的 所以在实现运维自动化之前就要先做标准话,后来改为主机名,主机名不能重复,用主机名作唯一标识 主机名是唯一标识,依赖本地文件 六、最终流程: 标准化:主机名不重复,流程的标准化,装机的时候CMDB中主机名已经设定好了 服务器上的资产采集(AGENT): a.第一次采集,文件不存在或者内容为空,采集资产要把主机名写入文件,将采集信息发送到API b.第N次,采集资产,主机名从文件中获取, SSH和Salt不存在这种情况: 这个架构开始是从中控机获取没有采集过的主机名(主机名跟IP是绑定的),而流程一开始主机名已经被录入cmdb了
一、CMDB项目大体攻略:
1.先建目录
bin #可执行文件
config #配置文件
lib #公共的模块
src #业务逻辑2.配置文件
settings 一般都是大写,放自定制配值文件
自定义配置文件
默认配置文件
在lib里面写个目录conf在目录中建立一个config.py和global_settings.py第一个文件是放逻辑的,让二、自定义配置文件和默认配置文件结合起来,
****整合技巧
PS:
import os
os.environ['USER_SETTINGS']="config.settings"
3.开发插件(可插拔)
公司采集资产有差别
默认采集:
basic #主机名,系统版本,系统类型
board #主板
cpu
disk
memory #内存
nic #网卡
定义插件:
class xxxx(object):
def process(self):
return '1331321321321'
把这些插件都放到settings里面4.向API获取发送数据
AGENT:
向API发送资产信息
SSH、SALT:
整个流程的开始应该是从API接口开始,先从这里拿到没有采集的主机列表获取未采集的主机列表:[c1.com,c2.com]
for host in 主机列表:
host采集资产,发送到API
三、为什么要开发CMDB
Excel维护资产信息,资产变更时难以保证Excel表正确性;信息交换不方便
自动采集资产工具,目标:自动汇报,保存变更记录
最终目标:实现运维自动化
四、CMDB架构:
资产采集
API(两个功能:接收数据保存入库,对外提供数据接口比如有人访问指定的url就能拿到指定主机的详细信息都展示出来)
后台管理(对资产进行增删改查)
五、开发程序时你负责做什么
周期:将近三个月
三个人负责,我负责资产采集(那个简单说那个)
调研提出三种方案:agent paramiko saltstack 三种方案,三种都兼容,为了提高
扩展性,配置文件(自定义和默认)和中间件(反射)参考Django:
六、有没有遇到难题(技术的难题不是难题,业务的难题才是难题)
Linux不太熟,命令都不知道该用啥
唯一标识:大问题,一开始用的是主板的SN号,当初我们认为他就是唯一标识,
物理机的话SN号是唯一的,openstack虚拟机和物理机的SN号是一样的
所以在实现运维自动化之前就要先做标准话,后来改为主机名,主机名不能重复,用主机名作唯一标识
主机名是唯一标识,依赖本地文件
七、最终流程:
标准化:主机名不重复,流程的标准化,装机的时候CMDB中主机名已经设定好了
服务器上的资产采集(AGENT):
a.第一次采集,文件不存在或者内容为空,采集资产要把主机名写入文件,将采集信息发送到API
b.第N次,采集资产,主机名从文件中获取,
八、SSH和Salt不存在这种情况:
这个架构开始是从中控机获取没有采集过的主机名(主机名跟IP是绑定的),而流程一开始主机名已经被录入cmdb了九、为什么要进行API验证:
在数据传输过程中保证数据不被篡改,为了保证数据安全,数据只给通过验证的人看
十、API验证是如何设计的:
这个设计我借鉴了Tornado中的加密Cookie来实现的,根据client_key+time进行md5创建动态的KEY,总共有三个限制:第一个,是时间,如果时间超过服务端两秒直接return;第二个,把客户端的ctime取出来,和把事先存到服务端的字符串和客户端一样的那个字符串进行md5加密,用这个加密的结果和客户端发来的加密结果进行对比,如果一样就通过,否则就return;第三个,我们在服务端维护了一个字典,字典中放的是最近2s内访问的client_md5_ctime_key和客户时间+2s组成的键值对,如果穿过来的这个值在字典中有的话我们就return,在for循环查字典的时候顺便把超时的删掉,如果通过,就把他在放到字典里面。
还有一个问题就是如果黑客的网速比我快的话(外网会发生),会比我先到API这个时候我需要对我的请求进行加密,这个是借鉴的微信的加密方式,也就是AES加密方式。
saltstack 安装
CentOS7 安装 yum install https://repo.saltstack.com/yum/redhat/salt-repo-latest-2.el7.noarch.rpm -y yum install salt-master -y yum install salt-minion -y CentOS6 安装 yum install https://repo.saltstack.com/yum/redhat/salt-repo-latest-2.el6.noarch.rpm yum install salt-master -y yum install salt-minion -y
### saltstack技术入门与实践 #### 基本原理 SaltStack 采用`C/S`模式,server端就是salt的master,client端就是minion,minion与master之间通过`ZeroMQ`消息队列通信。 minion上线后先与master端联系,把自己的`pub key`发过去,这时master端通过`salt-key -L`命令就会看到minion的key,接受该minion-key后,也就是master与minion已经互信。 master可以发送任何指令让minion执行了,salt有很多可执行模块,比如说cmd模块,在安装minion的时候已经自带了,它们通常位于你的python库中,`locate salt | grep /usr/`可以看到salt自带的所有东西。 这些模块是python写成的文件,里面会有好多函数,如cmd.run,当我们执行`salt '*' cmd.run 'uptime'`的时候,master下发任务匹配到的minion上去,minion执行模块函数,并返回结果。 master监听4505和4506端口,4505对应的是ZMQ的PUB system,用来发送消息,4506对应的是REP system是来接受消息的。 具体步骤如下 ``` 1、Salt stack的Master与Minion之间通过ZeroMq进行消息传递,使用了ZeroMq的发布-订阅模式,连接方式包括tcp,ipc 2、salt命令,将cmd.run ls命令从salt.client.LocalClient.cmd_cli发布到master,获取一个Jodid,根据jobid获取命令执行结果。 3、master接收到命令后,将要执行的命令发送给客户端minion。 4、minion从消息总线上接收到要处理的命令,交给minion._handle_aes处理 5、minion._handle_aes发起一个本地线程调用cmdmod执行ls命令。线程执行完ls后,调用minion._return_pub方法,将执行结果通过消息总线返回给master 6、master接收到客户端返回的结果,调用master._handle_aes方法,将结果写的文件中 7、salt.client.LocalClient.cmd_cli通过轮询获取Job执行结果,将结果输出到终端。 ``` #### saltstack 安装 [saltstack install](http://repo.saltstack.com/#rhel) #### 修改minion配置文件 ``` [root@linux-node2 ~]# vim /etc/salt/minion master: 192.168.56.11 [root@linux-node2 ~]# vim /etc/salt/minion master: 192.168.56.11 [root@linux-node1 pki]# pwd /etc/salt/pki [root@linux-node1 pki]# tree . ├── master │ ├── master.pem │ ├── master.pub │ ├── minions │ ├── minions_autosign │ ├── minions_denied │ ├── minions_pre │ │ ├── linux-node1.example.com │ │ └── linux-node2.example.com │ └── minions_rejected └── minion ├── minion_master.pub ├── minion.pem └── minion.pub [root@linux-node1 pki]# salt-key -A [root@linux-node1 pki]# tree . ├── master │ ├── master.pem │ ├── master.pub │ ├── minions │ │ ├── linux-node1.example.com │ │ └── linux-node2.example.com │ ├── minions_autosign │ ├── minions_denied │ ├── minions_pre │ └── minions_rejected └── minion ├── minion_master.pub ├── minion.pem └── minion.pub ``` #### 远程执行 ``` [root@linux-node1 pki]# salt "*" test.ping linux-node2.example.com: True linux-node1.example.com: True [root@linux-node1 pki]# salt "*" cmd.run 'w' linux-node1.example.com: 07:20:24 up 17:10, 1 user, load average: 0.00, 0.01, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.56.1 07:04 0.00s 0.30s 0.26s /usr/bin/python /usr/bin/salt * cmd.run w linux-node2.example.com: 08:26:25 up 22:40, 2 users, load average: 0.15, 0.05, 0.06 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root tty1 Sat09 13:12m 0.02s 0.02s -bash root pts/0 192.168.56.1 08:09 13:53 0.04s 0.04s -bash ``` #### 配置管理 ##### YAML - 缩进: - 两个空格 - 不能使用tab键 - 缩进代表层级关系 - 冒号: - key: value - 短横线代表list #### satate模块 ``` # vim /etc/salt/master file_roots: base: - /srv/salt # mkdir /srv/salt # mkdir /srv/salt # cd /srv/salt # mkdir web # cd web # pwd /srv/salt/web # vim apache.sls apache-install: pkg.installed: - names: - httpd - httpd-devel apache-service: service.running: - name: httpd - enable: True # salt '*' state.sls web.apache [root@linux-node2 salt]# cd /var/cache/salt/ [root@linux-node2 salt]# tree . `-- minion |-- extmods |-- files | `-- base | `-- web | `-- apache.sls |-- pkg_refresh `-- proc `-- 20160605081351939477 # cat /var/cache/salt/minion/files/base/web/apache.sls apache-install: pkg.installed: - names: - httpd - httpd-devel apache-service: service.running: - name: httpd - enable: True # ps -ef|grep yum root 34129 34103 1 08:13 ? 00:00:00 /usr/bin/python /usr/bin/yum --quiet check-update root 34204 34149 0 08:14 pts/1 00:00:00 grep --color=auto yum # cd /srv/salt/ # vim top.sls base: 'linux-node1.example.com': - web.apache 'linux-node2.example.com': - web.apache # salt '*' state.highstate test=True # salt '*' state.highstate # lsof -i:4505 -n COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME salt-mast 24739 root 13u IPv4 4637762 0t0 TCP *:4505 (LISTEN) salt-mast 24739 root 15u IPv4 4640421 0t0 TCP 192.168.56.11:4505->192.168.56.11:48344 (ESTABLISHED) salt-mast 24739 root 16u IPv4 4640542 0t0 TCP 192.168.56.11:4505->192.168.56.12:53039 (ESTABLISHED) salt-mini 25378 root 25u IPv4 4640888 0t0 TCP 192.168.56.11:48344->192.168.56.11:4505 (ESTABLISHED) ``` #### 数据系统 ##### Grains 静态数据 当minion启动时收集的minion本地相关信息 ##### Pillar