安装saltstack

旧文档

新文档

服务器 主机名 ip 身份 软件包
centos7 xue1 192.168.70.75 master salt-master
centos7 xue2 192.168.70.76 minion salt-minion

命令

安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 安装saltstack存储库和密钥
rpm --import https://repo.saltproject.io/py3/redhat/7/x86_64/3003/SALTSTACK-GPG-KEY.pub
curl -fsSL https://repo.saltproject.io/py3/redhat/7/x86_64/3003.repo | sudo tee /etc/yum.repos.d/salt.repo
# 清缓存
yum clean all
yum makecache

yum -y install salt-master # 主控端安装
yum -y install salt-ssh # salt-ssh安装
yum -y install salt-minion # 受控端安装


# 受控端需要修改(注意:后面需要有一个空格)
vim /etc/salt/minion

# 受控端设置
# 主控端ip
master: 192.168.70.75
# 受控端的名字(自定义)
id: xue2

# 主控端设置(取消注释,默认salt脚本路径和复制文件的路径)
file_roots:
base:
- /srv/salt/


# 在主控端可以看有多少请求(主控端需要开启4505和4506端口)
salt-key -L
# 接受需要的受控端
salt-key -a "xue*"
# 接受以后可以测试有没有成功
salt "xue*" test.ping
1
2
3
4
5
6
7
8
9
10
11
//salt-key常用选项
-L //列出所有公钥信息
-a minion //接受指定minion等待认证的key
-A //接受所有minion等待认证的key
-r minion //拒绝指定minion等待认证的key
-R //拒绝所有minion等待认证的key
-f minion //显示指定key的指纹信息
-F //显示所有key的指纹信息
-d minion //删除指定minion的key
-D //删除所有minion的key
-y //自动回答yes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//语法:salt [options] '<target>' <function> [arguments]

//常用的options
--version //查看saltstack的版本号
--versions-report //查看saltstack以及依赖包的版本号
-h //查看帮助信息
-c CONFIG_DIR //指定配置文件目录(默认为/etc/salt/)
-t TIMEOUT //指定超时时间(默认是5s)
--async //异步执行
-v //verbose模式,详细显示执行过程
--username=USERNAME //指定外部认证用户名
--password=PASSWORD //指定外部认证密码
--log-file=LOG_FILE //指定日志记录文件

//常用target参数
-E //正则匹配
-L //列表匹配
-S //CIDR匹配网段
-G //grains匹配
--grain-pcre //grains加正则匹配
-N //组匹配
-R //范围匹配
-C //综合匹配(指定多个匹配)
-I //pillar值匹配

编写

具体格式可以参考官方文档

vi /data/salt/test.sls 创建测试文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#创建文件夹(注意file.directory前面两个空格,-前面4个,-后面1个,True前面1个,最后三行可以指定用户、组、权限)
/data/logs/:
file.directory:
- makedirs: True
- user: fred
- group: users
- mode: 755

#删除/data这个目录和下面的所有文件
del:
file.absent:
- name: /data/

#上传单文件到受控端(主控端写相对路径,上传到受控端的绝对路径)
upload:
file.managed:
- name: /data/app/1.txt
- source: salt://1.txt
- mode: 644

#上传目录到受控端(主控端写相对路径,上传到受控端的绝对路径,include_empty空目录也要上传)
#exclude_pat来排除文件,在E@后面跟正则表达式
#watch可以监视某个有没有执行成功
upload_res:
file.recurse:
- name: /data/data/
- source: salt://data/
- dir_mode: 755
- file_mode: 644
- exclude_pat: E@(.svn)|(setup-v3.sh)|(setup.sh)
- include_empty: True
- watch:
- file: upload

salt使用git为服务端

使用最新的tls版(目前为3006.5)

1
2
3
4
5
# 新版本的salt自带python
rpm --import https://repo.saltproject.io/salt/py3/redhat/7/x86_64/SALT-PROJECT-GPG-PUBKEY-2023.pub
curl -fsSL https://repo.saltproject.io/salt/py3/redhat/7/x86_64/3006.repo | sudo tee /etc/yum.repos.d/salt.repo

salt -V
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Salt Version:
Salt: 3006.5

Python Version:
Python: 3.10.13 (main, Nov 15 2023, 04:34:27) [GCC 11.2.0]

Dependency Versions:
cffi: 1.16.0
cherrypy: unknown
dateutil: 2.8.1
docker-py: Not Installed
gitdb: Not Installed
gitpython: Not Installed
Jinja2: 3.1.2
libgit2: 1.7.1
looseversion: 1.0.2
M2Crypto: Not Installed
Mako: Not Installed
msgpack: 1.0.2
msgpack-pure: Not Installed
mysql-python: Not Installed
packaging: 22.0
pycparser: 2.21
pycrypto: Not Installed
pycryptodome: 3.9.8
pygit2: 1.13.3
python-gnupg: 0.4.8
PyYAML: 6.0.1
PyZMQ: 23.2.0
relenv: 0.14.2
smmap: Not Installed
timelib: 0.2.4
Tornado: 4.5.3
ZMQ: 4.3.4

System Versions:
dist: centos 7.9.2009 Core
locale: utf-8
machine: x86_64
release: 3.10.0-1160.71.1.el7.x86_64
system: Linux
version: CentOS Linux 7.9.2009 Core

安装pygit2

1
2
3
yum install python-pygit2 -y

salt-pip install pygit2

需要在master中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fileserver_backend:												# 当前配置为git和本地都用,两边有文件时优先使用git
- gitfs # 需要在这里写出来才能用
- roots

gitfs_provider: pygit2 # 配置salt的文件服务器为pygit2
gitfs_ssl_verify: False # 是否校验ssl(主配置)
gitfs_update_interval: 120 # 间隔多少s去拉git(主配置)
gitfs_user: test # git的账号(主配置)
gitfs_password: test # git的密码(主配置)
gitfs_insecure_auth: True # 默认False情况下,Salt将不会通过HTTP(非HTTPS)远程进行身份验证(主配置)
gitfs_remotes:
- http://xx.xx.xx.xx:8080/root/saltstack.git: # git地址
- user: root # git的账号(子配置)
- password: password # git的密码(子配置)
- ssl_verify: False # 是否校验ssl(子配置)
- update_interval: 30 # 间隔多少s去拉git(子配置)
- base: master # 分支(子配置)

配置git钩子(gitlab为例)

/data/salt/新建update_fileserver.sls文件,可以按照上面的来填写目录和文件名

1
2
update_fileserver:
runner.fileserver.update

在master中配置

1
2
3
reactor:
- 'salt/fileserver/gitfs/update':
- /data/salt/update_fileserver.sls # 此配置可以按照上面的来填写目录和文件名

配置gitlab钩子

15.11 及更高的版本可能在hooks目录

15.10 及更早的版本(当前公司为这个配置)

1
2
3
4
# 管理中心->项目->saltstack->找到Gitaly相对路径
# 在服务端中找到对应路径(容器内目录需要加上/var/opt/gitlab/git-data/repositories)
mkdir custom_hooks && cd custom_hooks && touch post-receive chmod a+x post-receive
vim post-receive # 注:下面的脚本最开始的那行最好在容器内执行which python3来填写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/opt/gitlab/embedded/bin/python3
import logging
import time
import paramiko


class SSHClient:
"""
:param host: string ip
:param password: string 密码
:param port: string 端口
:param username: string 用户名
"""

def __init__(self, host: str,
password: str = None, port: int = 22, username: str = 'root'):

self.host = host
self.port = port
self.username = username
self.password = password
self.client = paramiko.SSHClient()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.connect()

def connect(self):
self.client.connect(self.host, port=self.port, username=self.username, password=self.password)

def execute_command(self, command):
logging.info(f"即将执行命令: {command}")
stdin, stdout, stderr = self.client.exec_command(command)
output = stdout.read().decode('utf-8')
error = stderr.read().decode('utf-8')
exit_code = stdout.channel.recv_exit_status()
logging.info(f"执行结果:\n{output}")
if error:
logging.error(f"执行错误:\n{error}")
logging.info(f"退出代码: {exit_code}")
return {
'stdout': output,
'stderr': error,
'exit_code': exit_code
}

def execute_commands(self, commands):
results = []
for command in commands:
result = self.execute_command(command)
results.append(result)
return results

def upload_and_execute_script(self, local_path, remote_path):
logging.info("----------------开始脚本文件----------------")
sftp = self.client.open_sftp()
sftp.put(local_path, remote_path)
sftp.close()
logging.info("----------------上传脚本结束----------------")

# 确保脚本是可执行的
self.execute_command(f'chmod +x {remote_path}')
self.execute_command(f"sed -i 's/\r//' {remote_path}")

# 执行脚本
command_result = self.execute_command(f'/bin/bash {remote_path}')
return command_result

def upload_file(self, local_path, remote_path):
logging.info("----------------开始上传文件----------------")
sftp = self.client.open_sftp()
sftp.put(local_path, remote_path)
sftp.close()
logging.info("----------------上传文件结束----------------")

def download_file(self, remote_path, local_path):
logging.info("----------------开始下载文件----------------")
sftp = self.client.open_sftp()
sftp.get(remote_path, local_path)
sftp.close()
logging.info("----------------下载文件结束----------------")

def wait_for_file(self, remote_path, timeout=300):
start_time = time.time()
i = 0

while time.time() - start_time < timeout:
sftp = self.client.open_sftp()
i = i + 1

try:
sftp.stat(remote_path)
logging.info(f"当前为第{i}次尝试,文件 {remote_path} 存在,可以执行下一步操作。")
sftp.close()
return True
except FileNotFoundError:
logging.info(f"当前为第{i}次尝试,文件 {remote_path} 不存在,等待...")
sftp.close()
time.sleep(5) # 休眠5秒,可以根据需要调整休眠时间

logging.error(f"超时:等待文件 {remote_path} 超过 {timeout} 秒。")
return False

def close(self):
self.client.close()


if __name__ == "__main__":
host = '172.168.2.255'
password = 'password'
ssh = SSHClient(host, password)
command = 'salt-call event.fire_master update salt/fileserver/gitfs/update'
result_single = ssh.execute_command(command)
ssh.close()

salt-ssh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# target的信息
host: # 远端主机的ip地址或者dns域名
port: # ssh端口
user: # 登录的用户
sudo: # 可以通过sudo
priv: # ssh秘钥的文件路径
tty: # 如果设置了sudo,设置这个参数为true
timeout: # 当建立链接时等待响应时间的秒数
# 可选的部分
passwd: # 用户密码,如果不使用此选项,则默认使用秘钥方式
minion_opts: # minion的位置路径
thin_dir: # target系统的存储目录,默认是/tmp/salt-<hash>
cmd_umask: # 使用salt-call命令的umask值

hdy-xg-server-001:
host: 154
port: 22
user: root
sudo: true
passwd:
tty: true
timeout: 60
1
2
3
4
5
6
7
# 可能需要py3
salt-ssh -r 'hdy-xg-server-001' 'yum -y install python3'

vim ~/.ssh/config


StrictHostKeyChecking no