一、SaltStack 概述
1.1 核心特性
SaltStack 是一款开源的自动化运维工具,采用客户端 - 服务器(C/S)架构,以高效、灵活和可扩展著称。其核心特性包括:
- 高性能架构:基于 ZeroMQ 消息队列,支持大规模节点并发管理,每秒可处理数千节点
- 多模式管理:支持远程执行(Remote Execution)和配置管理(Configuration Management)两种模式
- 灵活的目标定位:通过 Grains、Pillar 和目标匹配器精确定位被管理节点
- 状态声明式配置:使用 YAML 格式的 SLS 文件定义系统目标状态
- 强大的模块系统:丰富的内置模块覆盖系统管理各领域,支持自定义模块
- 可扩展性:支持通过 API 与其他系统集成,可扩展至数万节点规模
- 加密通信:使用 AES 加密确保客户端与服务器之间的通信安全
1.2 应用场景
SaltStack 适用于多种自动化场景:
- 大规模服务器集群管理
- 软件包安装与配置
- 系统配置标准化与合规性检查
- 批量命令执行与任务调度
- 云资源与容器管理
- 事件驱动自动化(通过 Reactor 系统)
- 基础设施监控与告警集成
1.3 核心组件
SaltStack 架构由以下核心组件构成:
- Salt Master:控制节点,负责发送命令和配置给 Minion
- Salt Minion:被管理节点,接收并执行 Master 的命令
- ZeroMQ:用于 Master 与 Minion 之间的消息传递
- Grains:Minion 的静态属性(如操作系统、IP 地址等)
- Pillar:存储敏感数据,仅对指定 Minion 可见
- SLS 文件:定义系统状态的配置文件
- Reactor:事件驱动系统,用于响应特定事件并触发自动化操作
二、SaltStack 安装与部署
2.1 环境准备
2.1.1 系统要求
- 操作系统:支持 Linux(CentOS、Ubuntu、Debian 等)、Windows、macOS
- Python 版本:2.7 或 3.4+
- 网络:Master 与 Minion 之间需开放 4505 和 4506 端口
-
- 4505:发布端口(发布命令和配置)
-
- 4506:响应端口(接收 Minion 的执行结果)
2.1.2 主机规划
主机角色 |
操作系统 |
IP 地址 |
主机名 |
Salt Master |
CentOS 7 |
192.168.1.100 |
salt-master |
Salt Minion 1 |
CentOS 7 |
192.168.1.101 |
minion-01 |
Salt Minion 2 |
Ubuntu 20.04 |
192.168.1.102 |
minion-02 |
2.2 Salt Master 安装
2.2.1 CentOS 7 安装
# 安装EPEL源
yum install -y epel-release
# 安装Salt Master
yum install -y salt-master
# 启动并设置开机自启
systemctl start salt-master
systemctl enable salt-master
# 检查服务状态
systemctl status salt-master
# 开放防火墙端口
firewall-cmd --permanent --add-port=4505/tcp
firewall-cmd --permanent --add-port=4506/tcp
firewall-cmd --reload
2.2.2 Ubuntu 20.04 安装
# 添加SaltStack官方源
curl -fsSL https://repo.saltproject.io/py3/ubuntu/20.04/amd64/latest/SALTSTACK-GPG-KEY.pub | sudo apt-key add -
echo "deb http://repo.saltproject.io/py3/ubuntu/20.04/amd64/latest focal main" | sudo tee /etc/apt/sources.list.d/salt.list
# 更新软件包列表并安装
apt update
apt install -y salt-master
# 启动并设置开机自启
systemctl start salt-master
systemctl enable salt-master
# 检查服务状态
systemctl status salt-master
2.3 Salt Minion 安装
2.3.1 CentOS 7 安装
# 安装EPEL源
yum install -y epel-release
# 安装Salt Minion
yum install -y salt-minion
# 配置Master地址
sed -i "s/#master: salt/master: 192.168.1.100/g" /etc/salt/minion
# (可选)配置Minion ID
echo "minion-01" > /etc/salt/minion_id
# 启动并设置开机自启
systemctl start salt-minion
systemctl enable salt-minion
2.3.2 Ubuntu 20.04 安装
# 添加SaltStack官方源
curl -fsSL https://repo.saltproject.io/py3/ubuntu/20.04/amd64/latest/SALTSTACK-GPG-KEY.pub | sudo apt-key add -
echo "deb http://repo.saltproject.io/py3/ubuntu/20.04/amd64/latest focal main" | sudo tee /etc/apt/sources.list.d/salt.list
# 更新软件包列表并安装
apt update
apt install -y salt-minion
# 配置Master地址
sed -i "s/#master: salt/master: 192.168.1.100/g" /etc/salt/minion
# (可选)配置Minion ID
echo "minion-02" > /etc/salt/minion_id
# 启动并设置开机自启
systemctl start salt-minion
systemctl enable salt-minion
2.4 密钥认证管理
SaltStack 使用公钥加密确保通信安全,需要在 Master 上接受 Minion 的密钥:
# 查看待认证的Minion密钥
salt-key -L
# 输出示例:
# Accepted Keys:
# Denied Keys:
# Unaccepted Keys:
# minion-01
# minion-02
# Rejected Keys:
# 接受单个Minion密钥
salt-key -a minion-01
# 接受所有Minion密钥
salt-key -A
# 拒绝单个Minion密钥
salt-key -r minion-01
# 删除Minion密钥
salt-key -d minion-01
2.5 验证安装
# 测试与所有Minion的连接
salt '*' test.ping
# 输出示例:
# minion-01:
# True
# minion-02:
# True
# 查看Minion的Grains信息
salt 'minion-01' grains.items
# 在所有Minion上执行命令
salt '*' cmd.run 'uname -a'
三、SaltStack 核心配置
3.1 Master 配置
Master 主配置文件为/etc/salt/master,常用配置项:
# 网络配置
interface: 0.0.0.0 # 监听地址
publish_port: 4505 # 发布端口
ret_port: 4506 # 响应端口
# 安全配置
auto_accept: False # 是否自动接受Minion密钥
worker_threads: 5 # 工作线程数,根据CPU核心数调整
# 文件服务器配置
file_roots:
base:
- /srv/salt/base
dev:
- /srv/salt/dev
prod:
- /srv/salt/prod
# Pillar配置
pillar_roots:
base:
- /srv/pillar/base
dev:
- /srv/pillar/dev
prod:
- /srv/pillar/prod
# 日志配置
log_level: info
log_file: /var/log/salt/master
# 超时设置
timeout: 5
修改配置后需重启 Master:
systemctl restart salt-master
3.2 Minion 配置
Minion 主配置文件为/etc/salt/minion,常用配置项:
# Master地址
master: 192.168.1.100
# Minion ID(若未通过minion_id文件设置)
# id: minion-01
# 日志配置
log_level: info
log_file: /var/log/salt/minion
# 模块设置
modules_dirs:
- /srv/salt/_modules
# 状态执行设置
state_output: full # 状态执行输出详细程度
# 超时设置
master_timeout: 60
修改配置后需重启 Minion:
systemctl restart salt-minion
3.3 目录结构
推荐的 SaltStack 目录结构:
/srv/
├── salt/ # 状态文件和模块
│ ├── base/ # 基础环境
│ │ ├── top.sls # 顶级状态文件
│ │ ├── nginx/ # Nginx状态模块
│ │ ├── mysql/ # MySQL状态模块
│ │ └── _modules/ # 自定义执行模块
│ ├── dev/ # 开发环境
│ └── prod/ # 生产环境
└── pillar/ # Pillar数据
├── base/
│ ├── top.sls # Pillar顶级文件
│ ├── secrets.sls # 敏感数据
│ └── users.sls # 用户配置
├── dev/
└── prod/
创建目录结构:
mkdir -p /srv/salt/{base,dev,prod}
mkdir -p /srv/salt/base/{nginx,mysql,_modules}
mkdir -p /srv/pillar/{base,dev,prod}
四、远程执行系统
4.1 目标匹配器
SaltStack 提供多种方式定位 Minion:
# 匹配所有Minion
salt '*' test.ping
# 按Minion ID匹配
salt 'minion-01' test.ping
salt 'minion-*' test.ping # 通配符匹配
# 按列表匹配
salt -L 'minion-01,minion-02' test.ping
# 按正则表达式匹配
salt -E 'minion-(01|02)' test.ping
# 按Grains匹配
salt -G 'os:CentOS' test.ping # 匹配操作系统为CentOS的Minion
salt -G 'cpuarch:x86_64' test.ping # 匹配64位系统
# 按Pillar匹配
salt -I 'role:webserver' test.ping # 匹配角色为webserver的Minion
# 按IP地址匹配
salt -S '192.168.1.0/24' test.ping # 匹配网段内的Minion
# 复合匹配
salt -C 'G@os:CentOS and S@192.168.1.100/24' test.ping
4.2 常用执行模块
4.2.1 系统信息模块
# 查看Minion详细信息
salt '*' grains.items
# 查看特定Grains值
salt '*' grains.get os
salt '*' grains.get ip_interfaces:eth0
# 查看磁盘使用情况
salt '*' disk.usage
# 查看内存使用情况
salt '*' mem.info
# 查看网络接口
salt '*' network.interfaces
4.2.2 包管理模块
# 安装软件包(CentOS)
salt -G 'os:CentOS' pkg.install nginx
# 安装软件包(Ubuntu)
salt -G 'os:Ubuntu' pkg.install nginx
# 卸载软件包
salt '*' pkg.remove httpd
# 更新软件包
salt '*' pkg.upgrade
# 检查软件包状态
salt '*' pkg.version nginx
4.2.3 服务管理模块
# 启动服务
salt '*' service.start nginx
# 停止服务
salt '*' service.stop nginx
# 重启服务
salt '*' service.restart nginx
# 查看服务状态
salt '*' service.status nginx
# 设置服务开机自启
salt '*' service.enable nginx
4.2.4 文件管理模块
# 检查文件是否存在
salt '*' file.exists /etc/nginx/nginx.conf
# 获取文件状态
salt '*' file.stats /etc/nginx/nginx.conf
# 创建目录
salt '*' file.directory /data/logs mode=755 user=root group=root
# 复制文件(从Master到Minion)
salt '*' cp.get_file salt://nginx/nginx.conf /etc/nginx/nginx.conf
# 执行命令并获取输出
salt '*' cmd.run 'netstat -tuln'
4.3 命令执行选项
# 指定超时时间
salt '*' cmd.run 'sleep 30' timeout=40
# 以root权限执行
salt '*' cmd.run 'systemctl restart nginx' runas=root
# 批量执行命令并保存输出到文件
salt '*' cmd.run 'df -h' --out=txt > disk_usage.txt
# 并行执行(默认开启)
salt '*' cmd.run 'uptime' -b 10 # 每次10个Minion
# 查看作业状态
salt '*' cmd.run 'sleep 60' -t 100 --async # 异步执行
# 输出示例:jid: 20230520123456789012
salt-run jobs.lookup_jid 20230520123456789012 # 查看结果
五、状态管理系统
5.1 SLS 文件基础
SLS(SaLt State)文件用于定义系统的目标状态,采用 YAML 格式,示例:
# /srv/salt/base/nginx/install.sls
nginx-install:
pkg.installed:
- name: nginx
nginx-config:
file.managed:
- name: /etc/nginx/nginx.conf
- source: salt://nginx/nginx.conf
- user: root
- group: root
- mode: 644
- require:
- pkg: nginx-install
nginx-service:
service.running:
- name: nginx
- enable: True
- watch:
- file: nginx-config
SLS 文件语法规则:
- 使用缩进表示层级关系(2 个空格)
- 每个状态块由 ID 声明和状态函数组成
- require:定义依赖关系,确保状态执行顺序
- watch:监控文件变化,自动触发服务重启等操作
5.2 顶级文件(top.sls)
top.sls 用于将 SLS 文件映射到目标 Minion,是状态执行的入口:
# /srv/salt/base/top.sls
base:
'minion-01':
- nginx
- mysql
'minion-02':
- nginx
'G@os:CentOS':
- linux.centos
'I@role:webserver':
- webserver
'*':
- common
执行状态:
# 对所有Minion应用状态
salt '*' state.highstate
# 对特定Minion应用状态
salt 'minion-01' state.highstate
# 应用单个SLS文件
salt '*' state.sls nginx.install
# 测试状态执行(不实际修改系统)
salt '*' state.highstate test=True
5.3 常用状态模块
5.3.1 pkg 模块(包管理)
# 安装指定版本的软件包
nginx:
pkg.installed:
- name: nginx
- version: 1.18.0
# 确保软件包不被安装
apache:
pkg.removed:
- name: httpd
5.3.2 file 模块(文件管理)
# 创建文件并设置内容
/etc/motd:
file.managed:
- source: salt://common/motd
- user: root
- group: root
- mode: 644
- template: jinja # 启用Jinja2模板
- context:
environment: production
contact: admin@example.com
# 创建目录
/data/app:
file.directory:
- user: appuser
- group: appgroup
- mode: 755
- makedirs: True # 递归创建父目录
- recurse:
- user
- group # 递归设置子目录权限
# 符号链接
/usr/local/bin/python:
file.symlink:
- target: /usr/bin/python3
- force: True # 强制创建,覆盖现有文件
# 确保文件不存在
/tmp/oldfile:
file.absent
5.3.3 service 模块(服务管理)
# 管理服务状态
mysql:
service.running:
- name: mysqld
- enable: True # 开机自启
- reload: True # 支持reload操作
- require:
- pkg: mysql # 依赖mysql包安装
- watch:
- file: /etc/my.cnf # 配置文件变化时重启
5.3.4 user 模块(用户管理)
# 创建用户
appuser:
user.present:
- uid: 1001
- gid: 1001
- home: /home/appuser
- shell: /bin/bash
- fullname: "Application User"
- groups:
- developers
- docker
- require:
- group: appuser
# 创建用户组
appuser:
group.present:
- gid: 1001
5.3.5 cmd 模块(命令执行)
# 执行一次性命令
initialize_db:
cmd.run:
- name: /opt/app/init_db.sh
- creates: /var/lib/app/db_initialized # 文件存在则不执行
- user: appuser
- require:
- pkg: apppackage
5.4 模板系统(Jinja2)
SaltStack 支持 Jinja2 模板引擎,用于动态生成配置文件:
# /srv/salt/base/nginx/templates/nginx.conf.j2
user nginx;
worker_processes {{ grains['num_cpus'] }}; # 使用Grains数据
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
{% if pillar['environment'] == 'production' %}
sendfile on;
tcp_nopush on;
{% else %}
sendfile off;
{% endif %}
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
在 SLS 文件中引用模板:
# /srv/salt/base/nginx/config.sls
/etc/nginx/nginx.conf:
file.managed:
- source: salt://nginx/templates/nginx.conf.j2
- template: jinja
- user: root
- group: root
- mode: 644
- context:
max_connections: 1000 # 自定义上下文变量
六、Pillar 系统
6.1 Pillar 概述
Pillar 用于存储敏感数据(如密码、密钥)和特定节点的配置数据,具有以下特点:
- 数据存储在 Master 端,仅对指定 Minion 可见
- 适合存储环境变量、API 密钥、数据库密码等
- 支持加密存储敏感信息
6.2 Pillar 配置
# /srv/pillar/base/top.sls
base:
'minion-01':
- webserver
- secrets
'I@role:dbserver':
- dbserver
'*':
- common
# /srv/pillar/base/secrets.sls
mysql_root_password: secure_password_123
api_key: ABCDEFG123456
ssl_cert_passphrase: P@ssw0rd!
# /srv/pillar/base/webserver.sls
nginx:
port: 80
server_name: example.com
worker_processes: 4
ssl_enabled: True
在 SLS 文件中引用 Pillar 数据:
# /srv/salt/base/mysql/config.sls
/etc/my.cnf:
file.managed:
- source: salt://mysql/templates/my.cnf.j2
- template: jinja
- user: root
- group: root
# 在模板中使用
# {{ pillar['mysql_root_password'] }}
同步 Pillar 数据到 Minion:
# 手动同步Pillar数据
salt '*' saltutil.refresh_pillar
# 查看Minion的Pillar数据
salt 'minion-01' pillar.items
salt 'minion-01' pillar.get mysql_root_password
6.3 Pillar 加密
使用 salt-pillar 加密敏感数据:
# 生成加密密钥
mkdir -p /etc/salt/pki/master
salt-key --gen-keys=pillar
mv pillar.pub /etc/salt/pki/master/pillar.pub
mv pillar.pem /etc/salt/pki/master/pillar.pem
# 加密数据
echo "secret_password" | salt-call --local crypto.encrypt pillar.pub
# 输出加密后的字符串
# 在Pillar中使用加密数据
# /srv/pillar/base/secrets.sls
encrypted_password: |
-----BEGIN PGP MESSAGE-----
...加密后的内容...
-----END PGP MESSAGE-----
在 Master 配置中启用 Pillar 加密:
# /etc/salt/master
pillar_roots:
base:
- /srv/pillar/base
pillar_private_key: /etc/salt/pki/master/pillar.pem
pillar_public_key: /etc/salt/pki/master/pillar.pub
七、Reactor 系统
7.1 Reactor 概述
Reactor 是 SaltStack 的事件驱动自动化系统,能够响应 Salt 事件并触发预定义操作,常见应用场景:
- Minion 上线自动配置
- 配置文件变化自动测试
- 系统异常自动修复
- 安全事件响应
7.2 Reactor 配置
- 启用 Reactor:
# /etc/salt/master
reactor:
- 'salt/minion/*/start': # 事件匹配模式
- /srv/reactor/minion_start.sls # 触发的SLS文件
- 'salt/job/*/ret/*': # 作业返回事件
- /srv/reactor/job_failure.sls
2. 创建 Reactor SLS 文件:
# /srv/reactor/minion_start.sls
minion_initial_setup:
local.state.highstate:
- tgt: {{ data['id'] }} # 从事件数据中获取Minion ID
- args:
- test: False
# /srv/reactor/job_failure.sls
{% if data['retcode'] != 0 %} # 检查作业是否失败
notify_failure:
local.cmd.run:
- tgt: 'salt-master'
- args:
- cmd: 'echo "Job failed on {{ data['id'] }}: {{ data['fun'] }}" | mail -s "Salt Job Failure" admin@example.com'
{% endif %}
3. 重启 Master 使配置生效:
systemctl restart salt-master
7.3 自定义事件
发送自定义事件并触发 Reactor:
# 从Master发送自定义事件
salt-call event.send 'custom/event' '{"message": "backup_complete", "status": "success"}'
# 在Reactor中匹配自定义事件
# /etc/salt/master
reactor:
- 'custom/event':
- /srv/reactor/handle_backup.sls
八、SaltStack 实战案例
8.1 Web 服务器集群部署
# /srv/salt/base/top.sls
base:
'I@role:webserver':
- webserver
- nginx
- php
# /srv/salt/base/webserver/init.sls
webserver-packages:
pkg.installed:
- pkgs:
- git
- wget
- unzip
- curl
web-root:
file.directory:
- name: /var/www/html
- user: nginx
- group: nginx
- mode: 755
- makedirs: True
deploy-app:
git.latest:
- name: https://github.com/example/webapp.git
- target: /var/www/html
- user: nginx
- require:
- pkg: webserver-packages
- file: web-root
# /srv/pillar/base/webserver.sls
role: webserver
php:
version: 7.4
modules:
- curl
- gd
- mysql
nginx:
port: 80
server_name: web.example.com
执行部署:
# 对所有Web服务器应用配置
salt -I 'role:webserver' state.highstate
8.2 数据库备份自动化
# /srv/salt/base/mysql/backup.sls
mysql-backup-dir:
file.directory:
- name: /var/backups/mysql
- user: root
- group: root
- mode: 700
mysql-backup-script:
file.managed:
- name: /usr/local/bin/mysql_backup.sh
- source: salt://mysql/scripts/backup.sh.j2
- mode: 700
- user: root
- group: root
- template: jinja
- context:
backup_dir: /var/backups/mysql
retention_days: 7
mysql-backup-cron:
cron.present:
- name: /usr/local/bin/mysql_backup.sh
- user: root
- minute: 0
- hour: 2
- dayweek: '*'
- require:
- file: mysql-backup-script
九、SaltStack 高级特性
9.1 自定义模块
创建自定义执行模块:
# /srv/salt/base/_modules/monitoring.py
def check_disk_usage(path='/'):
"""
检查指定路径的磁盘使用率
"""
import shutil
disk = shutil.disk_usage(path)
percent_used = (disk.used / disk.total) * 100
return {
'path': path,
'total': disk.total,
'used': disk.used,
'free': disk.free,
'percent_used': percent_used
}
# 同步自定义模块到Minion
salt '*' saltutil.sync_modules
# 使用自定义模块
salt '*' monitoring.check_disk_usage '/data'
9.2 Syndic 分布式架构
当管理大规模节点时,可使用 Syndic 实现分层架构:
# 顶层Master配置
syndic_master: True
# Syndic配置
master: top_level_master_ip
syndic: True
# 下级Master配置
order_masters: True
9.3 API 集成
SaltStack 提供 REST API 用于与其他系统集成:
# 安装API依赖
yum install -y salt-api
# 配置API
# /etc/salt/master.d/api.conf
rest_cherrypy:
port: 8000
host: 0.0.0.0
ssl_crt: /etc/pki/tls/certs/salt-api.crt
ssl_key: /etc/pki/tls/private/salt-api.key
# 创建API用户
useradd -M -s /sbin/nologin saltapi
echo "saltapi:password" | chpasswd
# 启动API服务
systemctl start salt-api
systemctl enable salt-api
# 测试API
curl -sSk https://localhost:8000/login \
-H 'Content-Type: application/json' \
-d '{"username": "saltapi", "password": "password", "eauth": "pam"}'
十、最佳实践与总结
10.1 最佳实践
- 环境隔离:
-
- 使用不同环境(base、dev、prod)隔离配置
-
- 通过 Pillar 管理环境特定变量
2. 状态设计原则:
-
- 保持 SLS 文件模块化和可重用性
-
- 明确依赖关系,避免循环依赖
-
- 优先使用原生状态模块而非 cmd.run
3. 安全实践:
-
- 加密 Pillar 中的敏感数据
-
- 限制 Minion 权限,遵循最小权限原则
-
- 定期轮换 Salt Master 和 Minion 密钥
4. 性能优化:
-
- 合理设置 worker_threads 数量
-
- 对大规模部署使用 Syndic 架构
-
- 禁用不需要的模块和功能
10.2 总结
SaltStack 是一款功能强大的自动化运维工具,兼具远程执行和配置管理能力,特别适合大规模节点管理。其核心优势在于:
- 高性能架构,支持数千节点并发管理
- 灵活的目标定位机制,精确定位被管理节点
- 声明式状态配置,确保系统一致性
- 事件驱动的自动化能力,响应实时变化
通过本文的学习,你应该掌握了 SaltStack 的安装配置、远程执行、状态管理、Pillar 系统和 Reactor 系统等核心功能。在实际应用中,建议从简单场景入手,逐步构建复杂的自动化流程,充分发挥 SaltStack 在运维自动化中的价值。