一、salt执行的结果返回数据库
方法一:Minion端将内容返回master端和数据库
server2:
将下列内容写入Minion端配置文件
[root@server2 ~]# vim /etc/salt/minion
815 mysql.host: '172.25.10.1'
816 mysql.user: 'salt'
817 mysql.pass: 'westos'
818 mysql.db: 'salt'
819 mysql.port: 3306
重启服务
[root@server2 ~]# /etc/init.d/salt-minion restart
server1:
安装数据库
[root@server1 opt]# yum install -y mysql-server
开启数据库
[root@server1 opt]# /etc/init.d/mysqld start
登陆数据库授权
[root@server1 opt]# mysql
mysql> grant all on salt.* to salt@'172.25.10.%' identified by 'westos';
编辑数据库内容(官网上有 网址http://docs.saltstack.cn/ref/returners/all/salt.returners.mysql)
[root@server1 ~]# vim test.sql
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;
-- CREATE INDEX jid ON jids(jid) USING BTREE; ##复制下来后这一行注释
--
-- 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;
--
-- Table structure for table `salt_events`
--
DROP TABLE IF EXISTS `salt_events`;
CREATE TABLE `salt_events` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`tag` varchar(255) NOT NULL,
`data` mediumtext NOT NULL,
`alter_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`master_id` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `tag` (`tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
将数据库内容导入mysql库
[root@server1 ~]# mysql < test.sql
将与server2的连通信息返回数据库
[root@server1 ~]# salt 'server2' test.ping --return mysql
执行成功,在数据库中查看
[root@server1 ~]# mysql
mysql> use salt
mysql> show tables;
mysql> select * from salt_returns;
方法二:由minion端将内容传给master端后直接由master端返回数据库(常用)
server1:
master端安装MySQL-python服务
[root@server1 ~]# yum install MySQL-python
编辑master端配置文件
[root@server1 ~]# vim /etc/salt/master
1059 master_job_cache: mysql
1060 mysql.host: 'localhost'
1061 mysql.user: 'salt'
1062 mysql.pass: 'westos'
1063 mysql.db: 'salt'
1064 mysql.port: 3306
重启服务
[root@server1 ~]# /etc/init.d/salt-master restart
给自己授权
[root@server1 ~]# mysql
mysql> grant all on salt.* to salt@localhost identified by 'westos';
mysql> flush privileges; ##刷新
退出数据库执行salt命令
[root@server1 ~]# salt server3 cmd.run 'df -h'
在数据库中查看
[root@server1 ~]# mysql -u salt -p
mysql> use salt
mysql> show tables;
mysql> select * from salt_returns;
二、Saltstack扩展模块
模块是赋予相应的值,grain是赋予变量
新建目录
[root@server1 files]# mkdir /srv/salt/_modules
添加查看磁盘的模块:以python脚本的方式
[root@server1 files]# cd /srv/salt/_modules/
[root@server1 _modules]# vim my_disk.py
#!/usr/bin/env python
def df():
return __salt__['cmd.run']('df -h')
所有主机同步模块
[root@server1 _modules]# salt '*' saltutil.sync_modules
推送到所有节点
[root@server1 _modules]# salt '*' my_disk.df
扩展模块存放位置
[root@server4 mnt]# cd /var/cache/salt/minion/extmods/modules/
[root@server4 modules]# ll
total 8
-rw------- 1 root root 73 Aug 18 15:32 my_disk.py
-rw------- 1 root root 319 Aug 18 15:32 my_disk.pyc
cd /var/cache/salt/minion/extmods/grains
[root@server4 grains]# ls
my_grains.py my_grains.pyc
三、基于salt-syndic部署saltstack实现多级master
通过建立top-master主机管理salt-master端及其salt-minion节点,同时可以进行salt-master主机的横向扩展,从而通过一个或几个top-master管理多个salt-master及其salt-minion,实现大规模的集群管理。
原本server4为server1的minion端,在这个实验中我们要将server4作为topmaster端。server1作为master端,server2,3为server1的minion端。
1、实验环境:
server1(master端):
将原本对server4的认证删除
[root@server1 _modules]# salt-key -d server4
server4:
关闭salt-minion服务,设置开机不自启
/etc/init.d/salt-minion stop
chkconfig salt-minion off
关闭其他服务
/etc/init.d/haproxy stop
/etc/init.d/keepalived stop
2、将server4设置为Topmaster
安装slat-master服务
[root@server4 grains]# yum install -y salt-master
编辑master配置文件
[root@server4 grains]# cd /etc/salt/
[root@server4 salt]# vim master
857 order_masters: True ##开启topmaster服务
打开salt-master服务
[root@server4 salt]# /etc/init.d/salt-master start
3、server1(master端)安装syndic服务
[root@server1 _modules]# yum install -y salt-syndic
[root@server1 _modules]# vim /srv/salt/master
861 syndic_master: 172.25.10.4 ##指定top master
重启master服务
[root@server1 salt]# /etc/init.d/salt-master stop
4、server4(topmaster端)接收server1的认证
[root@server4 salt]# salt-key -L
[root@server4 salt]# salt-key -A
[root@server4 salt]# salt '*' test.ping
之后就能连同包括master在内和master的所有Minion端了,实现top master功能
master端认证的Minion端
四、SSH方式远程部署,不需要安装minion服务
.salt-ssh 不需要安装minion服务对客户端进行管理。
先将server3的minion服务关闭
server3:
[root@server3 ~]# /etc/init.d/salt-minion stop
server1(master端):
安装salt-ssh服务
yum install -y salt-ssh
将server3的主机信息写入
vim /etc/salt/roster
server3:
host: 172.25.10.3
user: root
passwd: westos
将之前返回数据库实验所写master配置文件参数注释
vim /etc/salt/master
1059 #master_job_cache: mysql
1060 #mysql.host: 'localhost'
1061 #mysql.user: 'salt'
1062 #mysql.pass: 'westos'
1063 #mysql.db: 'salt'
1064 #mysql.port: 3306
利用SSH方式查看server3信息
salt-ssh 'server3' test.ping
salt-ssh 'server3' test.ping -i
salt-ssh 'server3' my_disk.df
五、Saltstack- API
server1(master端):
安装salt-api服务
[root@server1 master.d]# yum install salt-api
生成key文件
cd /etc/pki/tls/private/
[root@server1 private]# openssl genrsa 1024
[root@server1 private]# openssl genrsa 1024 > localhost.key
[root@server1 private]# ls
localhost.key
配置自签名证书
[root@server1 private]# cd ..
[root@server1 tls]# cd certs/
[root@server1 certs]# make testcert
[root@server1 certs]# ll localhost.crt
-rw------- 1 root root 1029 Aug 18 17:16 localhost.crt
编辑api.conf文件
[root@server1 certs]# cd /etc/salt/master.d/
[root@server1 master.d]# vim api.conf
rest_cherrypy:
port: 8000
ssl_crt: /etc/pki/tls/certs/localhost.crt
ssl_key: /etc/pki/tls/private/localhost.key
[root@server1 master.d]# ll /etc/pki/tls/private/localhost.key
-rw-r--r-- 1 root root 887 Aug 18 17:15 /etc/pki/tls/private/localhost.key
[root@server1 master.d]# ll /etc/pki/tls/certs/localhost.crt
-rw------- 1 root root 1029 Aug 18 17:16 /etc/pki/tls/certs/localhost.crt
编辑auth.conf文件
[root@server1 master.d]# vim auth.conf
external_auth:
pam:
saltapi:
- '.*'
- '@wheel'
- '@runner'
- '@jobs'
添加用户,修改密码
[root@server1 master.d]# useradd saltapi
[root@server1 master.d]# passwd saltapi
重启salt-master服务,打开salt-api服务
[root@server1 master.d]# /etc/init.d/salt-master stop
[root@server1 master.d]# /etc/init.d/salt-master start
[root@server1 master.d]# /etc/init.d/salt-api start
查看端口
[root@server1 master.d]# netstat -antlp |grep :8000
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 2761/salt-api -d
tcp 0 0 127.0.0.1:54534 127.0.0.1:8000 TIME_WAIT -
获得token
[root@server1 master.d]# curl -sSk https://localhost:8000/login -H 'Accept: application/x-yaml' -d username=saltapi -d password=westos -d eauth=pam
调用test.ping
[root@server1 master.d]# curl -sSk https://localhost:8000 -H 'Accept:application/x-yaml' -H 'X-Auth-Token:25fd5f8342d9e207e7c1a618be2f06d9b269e35d' -d client=local -d tgt='*' -d fun=test.ping
编辑py脚本(网上找的)
[root@server1 ~]# vim salt-api.py
1 # -*- coding: utf-8 -*-
2
3 import urllib2,urllib
4 import time
5
6 try:
7 import json
8 except ImportError:
9 import simplejson as json
10
11 class SaltAPI(object):
12 __token_id = ''
13 def __init__(self,url,username,password):
14 self.__url = url.rstrip('/')
15 self.__user = username
16 self.__password = password
17
18 def token_id(self):
19 ''' user login and get token id '''
20 params = {'eauth': 'pam', 'username': self.__user, 'password': self .__password}
21 encode = urllib.urlencode(params)
22 obj = urllib.unquote(encode)
23 content = self.postRequest(obj,prefix='/login')
24 try:
25 self.__token_id = content['return'][0]['token']
26 except KeyError:
27 raise KeyError
28
29 def postRequest(self,obj,prefix='/'):
30 url = self.__url + prefix
31 headers = {'X-Auth-Token' : self.__token_id}
32 req = urllib2.Request(url, obj, headers)
33 opener = urllib2.urlopen(req)
34 content = json.loads(opener.read())
35 return content
36
37 def list_all_key(self):
38 params = {'client': 'wheel', 'fun': 'key.list_all'}
39 obj = urllib.urlencode(params)
40 self.token_id()
41 content = self.postRequest(obj)
42 minions = content['return'][0]['data']['return']['minions']
43 minions_pre = content['return'][0]['data']['return']['minions_pre']
44 return minions,minions_pre
45
46 def delete_key(self,node_name):
47 params = {'client': 'wheel', 'fun': 'key.delete', 'match': node_nam e}
48 obj = urllib.urlencode(params)
49 self.token_id()
50 content = self.postRequest(obj)
51 ret = content['return'][0]['data']['success']
52 return ret
53
54 def accept_key(self,node_name):
55 params = {'client': 'wheel', 'fun': 'key.accept', 'match': node_nam e}
56 obj = urllib.urlencode(params)
57 self.token_id()
58 content = self.postRequest(obj)
59 ret = content['return'][0]['data']['success']
60 return ret
61
62 def remote_noarg_execution(self,tgt,fun):
63 ''' Execute commands without parameters '''
64 params = {'client': 'local', 'tgt': tgt, 'fun': fun}
65 obj = urllib.urlencode(params)
66 self.token_id()
67 content = self.postRequest(obj)
68 ret = content['return'][0][tgt]
69 return ret
70
71 def remote_execution(self,tgt,fun,arg):
72 ''' Command execution with parameters '''
73 params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg}
74 obj = urllib.urlencode(params)
75 self.token_id()
76 content = self.postRequest(obj)
77 ret = content['return'][0][tgt]
78 return ret
79
80 def target_remote_execution(self,tgt,fun,arg):
81 ''' Use targeting for remote execution '''
82 params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg, 'e xpr_form': 'nodegroup'}
83 obj = urllib.urlencode(params)
84 self.token_id()
85 content = self.postRequest(obj)
86 jid = content['return'][0]['jid']
87 return jid
88
89 def deploy(self,tgt,arg):
90 ''' Module deployment '''
91 params = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
92 obj = urllib.urlencode(params)
93 self.token_id()
94 content = self.postRequest(obj)
95 return content
96
97 def async_deploy(self,tgt,arg):
98 ''' Asynchronously send a command to connected minions '''
99 params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
100 obj = urllib.urlencode(params)
101 self.token_id()
102 content = self.postRequest(obj)
103 jid = content['return'][0]['jid']
104 return jid
105
106 def target_deploy(self,tgt,arg):
107 ''' Based on the node group forms deployment '''
108 params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup'}
109 obj = urllib.urlencode(params)
110 self.token_id()
111 content = self.postRequest(obj)
112 jid = content['return'][0]['jid']
113 return jid
114
115 def main():
116 sapi = SaltAPI(url='https://172.25.10.1:8000',username='saltapi',passwo rd='westos') ##修改为自己的内容
117 #sapi.token_id()
118 print sapi.list_all_key() ##这一行注释取消
119 #sapi.delete_key('test-01')
120 #sapi.accept_key('test-01')
121 #sapi.deploy('test-01','nginx')
122 #print sapi.remote_noarg_execution('test-01','grains.items')
123
124 if __name__ == '__main__':
125 main()
[root@server1 ~]# python salt-api.py
([u'server1', u'server2', u'server3'], [])
调用python脚本
将脚本118行加上注释,在121行打开注释并修改为以下内容
121 sapi.deploy('server3','nginx.service')
运行脚本
[root@server1 ~]# python salt-api.py
查看进程