经过前两篇的实战,发现saltstack还是有些小问题的,所以需要进阶一下。
进阶1:创建一些自己的模块,关于创建自己的模块的方法参见saltstack知识点
在base目录下创建_modules目录,你自己编写的模块都可以存放在该目录下,当前目录结构如下:
可以看到我创建了一个ip.py文件,看看相关文件的内容:
可以看到在base/top.sls文件中并没有新增模块名
现在把写好的模块同步到你需要执行的机器上,可以全部同步,也可以针对性的同步
#只同步某一台 salt '192.168.1.201' saltutil.sync_modules #同步所有客户端 salt '×' saltutil.sync_modules #还可以利用正则规则来区分
现在在master上执行你编写的模块,由于并不依赖雨state.sls文件,所以执行时命令也有变化,在主要命令后面跟模块名.函数名
进阶2:屏幕返回值输出到指定的地方
saltstack执行命令时默认的返回值都是打印到当前屏幕的,如果一次执行很多台机器,怎么查看这些记录,为了方便的查看这些返回结果信息,这就用到了salt的returners功能了。关于returners是上面,看这里
在base目录下创建_returners目录,你自己编写的模块都可以存放在该目录下,当前目录结构如下:
我在_returners目录下创建了两个文件,一个是local_log.py:表示把执行结果存放到本地,一个是mysql_log.py:表示把结果存放到mysql中
1 返回结果存放到本地
和自建模块一样,在编写完returners之后,也是要同步到客户端的,同步的规则和自建模块一样。
#同步到某一台机器 salt '192.168.1.202' saltutil.sync_returners
在master上执行命令,查看192.168.1.202的运行结果,返回的结果写入192.168.1.202本地
在192.168.1.202上查看
2 返回结果存放到mysql中
官方的默认returners中已经包含了mysql的returners,我门先直接利用官方原生的mysql returners,官方的mysql returners源码在https://github.com/saltstack/salt/blob/develop/salt/returners/mysql.py,里面有创建相关表的语句
mysql服务器在192.168.1.204
#在mysql服务器上创建表 CREATE DATABASE `salt` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; USE `salt`; -- -- Table structure for table `jids` -- DROP TABLE IF EXISTS `jids`; CREATE TABLE `jids` ( `jid` varchar(255) NOT NULL, `load` mediumtext NOT NULL, UNIQUE KEY `jid` (`jid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `salt_returns` -- DROP TABLE IF EXISTS `salt_returns`; CREATE TABLE `salt_returns` ( `fun` varchar(50) NOT NULL, `jid` varchar(255) NOT NULL, `return` mediumtext NOT NULL, `id` varchar(255) NOT NULL, `success` varchar(10) NOT NULL, `full_ret` mediumtext NOT NULL, `alter_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, KEY `id` (`id`), KEY `jid` (`jid`), KEY `fun` (`fun`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;给相关salt表赋予访问权限
GRANT ALL PRIVILEGES ON salt.* TO 'salt'@localhost IDENTIFIED BY 'saltt';
因为要把客户端执行命令的结果直接返回给mysql服务器,所以客户端也是需要配置mysql信息的,我们以192.168.1.201为例,在salt的配置文件中加入如下信息,你也可以把它单独写在一个文件中,我是写在单独文件中的,这样便于管理,如下:
#/etc/salt/minion.d/mysql.conf mysql.host: '192.168.1.204' mysql.user: 'salt' mysql.pass: 'salt' mysql.db: 'salt' mysql.port: 3306然后在master上执行命令,如下:
salt '192.168.1.201' cmd.run 'uptime' --return mysql
注意这里用的是salt自带的原生mysql returners,并没有使用我自己写的mysql_log returns,我们看看数据库中的记录:
第一句是刚创建好表时的结果,可以看到数据库中已经有一条记录了,下面我们用我自己写的mysql_log returners来试试
salt '192.168.1.201' cmd.run 'hostname' --return mysql_log
我们来看看数据库中的记录
mysql_log.py的文件内容如下
#/usr/bin/python #coding:utf-8 from contextlib import contextmanager import sys import json import logging # Import third party libs try: import MySQLdb HAS_MYSQL = True except ImportError: HAS_MYSQL = False log = logging.getLogger(__name__) def __virtual__(): if not HAS_MYSQL: return False return "mysql_log" def _get_options(): ''' Returns options used for the MySQL connection. ''' defaults = {'host': '192.168.1.204', 'user': 'salt', 'pass': 'salt', 'db': 'salt', 'port': 3306} _options = {} # Ensure port is an int for attr in defaults: _attr = __salt__['config.option']('mysql.{0}'.format(attr)) if not _attr: log.debug('Using default for MySQL {0}'.format(attr)) _options[attr] = defaults[attr] continue _options[attr] = _attr return _options @contextmanager def _get_serv(commit=False): ''' Return a mysql cursor ''' _options = _get_options() conn = MySQLdb.connect(host=_options['host'], user=_options['user'], passwd=_options['pass'], db=_options['db'], port=_options['port']) cursor = conn.cursor() try: yield cursor except MySQLdb.DatabaseError as err: error, = err.args sys.stderr.write(str(error)) cursor.execute("ROLLBACK") raise err else: if commit: cursor.execute("COMMIT") else: cursor.execute("ROLLBACK") finally: conn.close() def returner(ret): ''' Return data to a mysql server ''' with _get_serv(commit=True) as cur: sql = '''INSERT INTO `salt_returns` (`fun`, `jid`, `return`, `id`, `success`, `full_ret` ) VALUES (%s, %s, %s, %s, %s, %s)''' cur.execute(sql, (ret['fun'], ret['jid'], str(ret['return']), ret['id'], ret['success'], json.dumps(ret)))