大多时,在使用pillar我们都是直接用的SLS文件存储数据,但其实pillar可以支持多种数据存储方式,例如: mysql、mongo、json等等;这些都可以在官网或者代码中看到ext_piilar的代码;
pillar支持的数据存储模块列表地址:http://docs.saltstack.com/en/latest/ref/pillar/all/index.html#all-salt-pillars
需求:
先说说为什么会有这个需求,某些时候我们需要把pillar数据存储在CMDB中,或者去拉取CMDB的数据提供pillar使用,这个时候再去编辑pillar下的SLS文件就有点不优雅了;ext_pillar就是解决这个问题,它作为pillar数据映射和数据存储(CMDB)的一个枢纽。
最近在写代码发布,需要用到pillar数据(平台上提供一个版本号,代码url,在打包完代码推送到repo时,把版本号更新到pillar数据上,供saltstack调取),就想起了ext_pillar这个事儿,OMS运维平台用到了MySQL数据库,就想直接使用这个模块;在接触的时候,有点淡淡的忧伤,文档真少~~ 找到一个翻译文章采用的是MongoDB,想到再去搭个mongodb就有点过了; 肥肥给我的建议是不要采用MySQL,建议做成Http API接口方式;
pillar是一大利器,不仅可以存储安全性数据,也可以作为业务数据存储; 利用ext_pillar对接CMDB系统,state用来描述业务处理逻辑,而真实数据取自CMDB;以前没想到还可以这么玩,这块绿肥、jacky两人最早实现,很有经验
讲了这么多,来说说这么实现这个Http API的ext_pillar(无CMDB)
1. 实现后端数据 -> 根据业务场景,设计数据结构(dict)来满足业务,控制权在你手上,你想要什么样子就可以实现什么样子,关键点符合你业务
2. 实现ext_pillar,能访问到http访问到后端数据
3. 配置salt master配置文件,重启master
4. pillar测试
实现:
1. 后端数据实现.
采用http方式用的就是JSON数据,不仅能生成json数据,也能变更json数据;首先来看下pillar数据映射SLS文件格式
hdworkers:
ver: 2014102202
上述数据格式转换下dict,{'hdworkers': {'ver': '2014102202'}} ,我只需要实现简单的版本号映射就行,那么复杂的数据,大家可以自行设计;下面贴程序代码(代码很烂,莫喷~)
# -*- coding: utf-8 -*- import json import os class BuildJson(object): ''' Build JSON data(base and minion_id etc..) ''' def base_data(self,args): ''' build base data ''' info = {} ret = dict(info,**args) self.write_data('base',ret) def build_data(self,id,args): if not os.path.exists('/home/api/pillar/%s' % (id)): with open('/home/api/pillar/base') as f: obj = f.readlines()[0] ret = eval(obj) self.write_data(id,ret) with open('/home/api/pillar/%s' % (id)) as f: data = f.readlines()[0] cov_data = eval(data) if not cov_data.has_key(args.keys()[0]): ret = dict(cov_data,**args) self.write_data(id,ret) else: cov_data.update(args) self.write_data(id,cov_data) def write_data(self,file,ret): f = open('/home/api/pillar/%s' % (file),'w+') f.write(str(ret)) f.close()
#data = {'hdworkers':{'ver':'2014103105'}}
#bapi = BuildJson()
#bapi.base_data(data)
#bapi.build_data('test-01',data)
生成base数据,再调用build_data(继承base数据,同时更新数据),而有些数据是会在id上有,但base是没的~,所以上述是我写的; 看官可以自行玩耍,,有好的可以反馈给我,我在修改~
2. 实现ext_pillar,能通过http方式访问
因为是和OMS平台结合,上述生成的文件,我在nginx做了localtion设置,让数据能通过http访问;不然ext_pillar没法玩了
Nginx配置过程我就忽略,直接贴结果
ID数据能通过http访问到,OK,往下走,配ext_pillar
ext_pillar实现
more /usr/lib/python2.6/site-packages/salt/pillar/oms.py
# -*- coding: utf-8 -*- ''' author: pengyao A module to pull data from OMS system via its API into the Pillar dictionary Configuring the Wolf system ext_pillar ================================== .. code-block:: yaml ext_pillar: - oms: api: http://oms.example.com/api/pillar/ Module Documentation ==================== ''' # Import python libs import logging import urllib2 import json # Set up logging log = logging.getLogger(__name__) def ext_pillar(minion_id, pillar, api): ''' Read pillar data from OMS system via its API. ''' pillar_url = api + "/" + minion_id log.info("Querying OMS system Pillar for %r" %(minion_id)) try: request = urllib2.urlopen(pillar_url).read() ret = eval(request) result = json.loads(json.dumps(ret)) except Exception, e: log.exception( 'Query OMS system failed! Error: %s' %(e) ) return {} return result
上述代码很简单,urllib2请求minion_id数据,json.loads把数据转换成dict返回给saltstack。 注意urllib请求得到的数据是str,我这把str先给转换成dict在传递给json去转,避免成为unicode......(赶脚json是不是有点多~)
3. 配置salt master配置文件,pillar测试
根据ext_pillar代码配置master配置文件,让master会去加载pillar数据
cat /etc/salt/master
ext_pillar:
- oms: #代码名字,oms.py
api: http://X.X.X.X/pillar/ # api前缀,http://访问域名/IP/pillar/minion_id能访问到数据
重启master
/etc/init.d/salt-master restart
4. pillar测试
salt 'minion_id' pillar.item hdworkers
我这就不演示数据生成过程,只要后端数据更新,执行对应minion id的pillar就能获取到最新数据,因为pillar是动态的~
希望这篇文章能帮助大家,玩的开心~~~ 以后再也不用和我一样找不到文章了。。