一、Job简介
master在下发指令任务时,会附带上产生的jid。
minion在接收到指令开始执行时,会在本地的/var/cache/salt/minion/proc
目录下产生该jid命名的文件,用于在执行过程中master查看当前任务的执行情况。
指令执行完毕将结果传送给master后,删除该临时文件。
Job缓存默认保存24小时:
# vim /etc/salt/master
keep_jobs: 24
master端Job缓存目录:
/var/cache/salt/master/jobs
二、把Job存储到数据库
2.1在server4上mariadb数据库
[root@server4 ~]# yum install mariadb-server.x86_64 安装数据库
[root@server4 ~]# systemctl start mariadb.service
[root@server4 ~]# mysql_secure_installation
2.2在server5(minion端)安装MySQL-python.x86_64
[root@server5 ~]# yum install -y MySQL-python.x86_64
更改配置文件
[root@server5 ~]# vim /etc/salt/minion
[root@server5 ~]# systemctl restart salt-minion.service
[root@server4 ~]# vim add.sql
```sql
# cat add.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`
--
[root@server4 ~]# mysql -uroot -pwestos < add.sql 导入数据库
[root@server4 ~]# mysql -uroot -pwestos
MariaDB [(none)]> grant all on salt.* to salt@localhost identified by 'salt';
Query OK, 0 rows affected (0.01 sec)
MariaDB [(none)]> grant all on salt.* to salt@'%' identified by 'salt';
Query OK, 0 rows affected (0.00 sec)
[root@server4 ~]# salt server5 cmd.run hostname
server5:
server5
2.4在master端配置,复位刚才在minion端的配置,这样就不用再minion端去安装MySQL-python.x86_64
[root@server5 ~]# vim /etc/salt/minion
[root@server5 ~]# systemctl restart salt-minion.service
[root@server5 ~]# yum install -y mysql
[root@server4 ~]# yum install -y MySQL-python.x86_64
[root@server4 ~]# vim /etc/salt/master
master_job_cache: mysql
return: mysql
mysql.host: '172.25.254.4'
mysql.user: 'salt'
mysql.pass: 'salt'
mysql.db: 'salt'
mysql.port: 3306
[root@server4 ~]# systemctl restart salt-master.service
三、salt-ssh简介
1】salt-ssh可以独立运行的,不需要minion端。
2】salt-ssh 用的是sshpass进行密码交互的。
3】以串行模式工作,性能下降。
3.1salt-ssh配置
停止minion端服务
[root@server5 ~]# systemctl stop salt-minion.service
[root@server6 ~]# systemctl stop salt-minion.service
安装salt-ssh:
[root@server4 ~]# yum install -y ssh-salt
[root@server4 ~]# cat /etc/salt/roster
# Sample salt-ssh config file
#web1:
# host: 192.168.42.1 # The IP addr or DNS hostname
# user: fred # Remote executions will be executed as user fred
# passwd: foobarbaz # The password to use for login, if omitted, keys are used
# sudo: True # Whether to sudo to root, not enabled by default
#web2:
# host: 192.168.42.2
server5:
host: 172.25.254.5
user: root
passwd: westos
server6:
host: 172.25.254.6
user: root
passwd: westos
测试:
salt-ssh '*' test.ping -i //询问密码加 -i
vim ~/.ssh/config
StrictHostKeyChecking no
加入此参数在当访问其他主机时不再校验key,直接显示密码登录不用回答yes或no
[root@server4 ~]# salt-ssh server5 cmd.run df
server5:
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/rhel-root 8374272 1500000 6874272 18% /
devtmpfs 521648 0 521648 0% /dev
tmpfs 533788 0 533788 0% /dev/shm
tmpfs 533788 8328 525460 2% /run
tmpfs 533788 0 533788 0% /sys/fs/cgroup
/dev/sda1 1038336 135308 903028 14% /boot
tmpfs 106760 0 106760 0% /run/user/0
四、salt-syndic简介
如果大家知道zabbix proxy的话那就很容易理解了,syndic其实就是个代理,隔离master与minion。
Syndic必须要运行在master上,再连接到另一个topmaster上。
Topmaster 下发的状态需要通过syndic来传递给下级master,minion传递给master的数据也是由syndic传递给topmaster。
topmaster并不知道有多少个minion。
syndic与topmaster的file_roots和pillar_roots的目录要保持一致
4.1salt-syndic配置
4.2salt-syndic配置过程
实验环境
server4 172.25.254.4 salt-master
server5 172.25.254.5 salt-minion
server6 172.25.254.6 salt-minion
server7 172.25.254.7 salt-master(中心master)
server7作为server4与其他minion端的中间人。
server4制管理中间master
中间master去管理其他minion端
[root@server5 ~]# systemctl start salt-minion.service
[root@server6 ~]# systemctl start salt-minion.service
[root@server7 ~]# yum install -y salt-master
[root@server7 ~]# vim /etc/salt/master
1047行: order_masters: True
[root@server7 ~]# systemctl start salt-master.service
在server1上:
[root@server4 ~]# yum install -y salt-syndic
[root@server4 ~]# vim /etc/salt/master
1051行: syndic_master: 172.25.254.7 指定顶级master主机
[root@server4 ~]# systemctl restart salt-master.service
[root@server4 ~]# systemctl restart salt-syndic.service
可以看到server7顶级的master只有一个下属server4,但是可以看到两个minion端,实际上只是server4取获取minion端的信息在交给server7.
五、salt-api配置
5.1salt-api简介
SaltStack 官方提供有REST API格式的 salt-api 项目,将使Salt与第三方系统集成变得尤为简单。
官方提供了三种api模块:
rest_cherrypy
rest_tornado
rest_wsgi
官方链接:https://docs.saltstack.com/en/latest/ref/netapi/all/index.html#all-netapi-modules
5.2salt-api配置过程
安装salt-api:
[root@server4 ~]# yum install -y salt-api python-cherrypy
[root@server4 certs]# cd /etc/salt/master.d/
[root@server4 master.d]# ll
total 0
[root@server4 master.d]# vim auth.conf 创建用户认证文件
[root@server4 master.d]# cat auth.conf
external_auth:
pam:
saltdev:
- .*
- '@wheel'
- '@runner'
- '@jobs'
[root@server4 master.d]# useradd saltdev 创建用户
[root@server4 master.d]# passwd saltdev 更改密码westos
Changing password for user saltdev.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.
[root@server4 master.d]# vim cert.conf 激活rest_cherrypy模块
[root@server4 master.d]# cat cert.conf
rest_cherrypy:
port: 8000
ssl_crt: /etc/pki/tls/certs/localhost.crt
ssl_key: /etc/pki/tls/private/localhost.key
[root@server4 master.d]# systemctl restart salt-master 重启
[root@server4 master.d]# systemctl start salt-api 启动
[root@server4 master.d]# netstat -tnpl | grep 8000 查看端口
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 116430/python
5.4获取认证token:
[root@server4 master.d]# curl -sSk https://localhost:8000/login \
> -H 'Accept: application/x-yaml' \
> -d username=saltdev \
> -d password=westos \
> -d eauth=pam
return:
- eauth: pam
expire: 1591767118.761024
perms:
- .*
- '@wheel'
- '@runner'
- '@jobs'
start: 1591723918.761023
token: bc00b70cb788756454e0db7eddf7fd4b47a3bb30
user: saltdev
推送任务
[root@server4 master.d]# curl -sSk https://localhost:8000 \
> -H 'Accept: application/x-yaml' \
> -H 'X-Auth-Token: bc00b70cb788756454e0db7eddf7fd4b47a3bb30' \ token值是上面命令获取的toekn值
> -d client=local \
> -d tgt='*' \
> -d fun=test.ping
代码:https://github.com/binbin91/oms/blob/master/deploy/saltapi.py
[root@server4 ~]# vim saltapi.py
# -*- coding: utf-8 -*-
import urllib2,urllib
import time
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
try:
import json
except ImportError:
import simplejson as json
class SaltAPI(object):
__token_id = ''
def __init__(self,url,username,password):
self.__url = url.rstrip('/')
self.__user = username
self.__password = password
def token_id(self):
''' user login and get token id '''
params = {'eauth': 'pam', 'username': self.__user, 'password': self.__password}
encode = urllib.urlencode(params)
obj = urllib.unquote(encode)
content = self.postRequest(obj,prefix='/login')
try:
self.__token_id = content['return'][0]['token']
except KeyError:
raise KeyError
def postRequest(self,obj,prefix='/'):
url = self.__url + prefix
headers = {'X-Auth-Token' : self.__token_id}
req = urllib2.Request(url, obj, headers)
opener = urllib2.urlopen(req)
content = json.loads(opener.read())
return content
def list_all_key(self):
params = {'client': 'wheel', 'fun': 'key.list_all'}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
minions = content['return'][0]['data']['return']['minions']
minions_pre = content['return'][0]['data']['return']['minions_pre']
return minions,minions_pre
def delete_key(self,node_name):
params = {'client': 'wheel', 'fun': 'key.delete', 'match': node_name}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
ret = content['return'][0]['data']['success']
return ret
def accept_key(self,node_name):
params = {'client': 'wheel', 'fun': 'key.accept', 'match': node_name}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
ret = content['return'][0]['data']['success']
return ret
def remote_noarg_execution(self,tgt,fun):
''' Execute commands without parameters '''
params = {'client': 'local', 'tgt': tgt, 'fun': fun}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
ret = content['return'][0][tgt]
return ret
def remote_execution(self,tgt,fun,arg):
''' Command execution with parameters '''
params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
ret = content['return'][0][tgt]
return ret
def target_remote_execution(self,tgt,fun,arg):
''' Use targeting for remote execution '''
params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg, 'expr_form': 'nodegroup'}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
jid = content['return'][0]['jid']
return jid
def deploy(self,tgt,arg):
''' Module deployment '''
params = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
return content
def async_deploy(self,tgt,arg):
''' Asynchronously send a command to connected minions '''
params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
jid = content['return'][0]['jid']
return jid
def target_deploy(self,tgt,arg):
''' Based on the node group forms deployment '''
params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup'}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
jid = content['return'][0]['jid']
return jid
def main(): 本机地址 用户 密码
sapi = SaltAPI(url='https://172.25.254.4:8000',username='saltdev',password='westos')
#sapi.token_id()
#print sapi.list_all_key()
#sapi.delete_key('test-01')
#sapi.accept_key('test-01')
sapi.deploy('172.25.254.6','nginx') 给server6安nginx服务
#print sapi.remote_noarg_execution('test-01','grains.items')
if __name__ == '__main__':
main()
[root@server4 ~]# python saltapi.py