SaltStack是一个基于Python开发的开源软件,采用C/S架构,有服务端master和客户端minion。SaltStack是一个基础平台管理工具,配置管理系统,具有一个分布式远程执行系统,可用来在远程节点服务器上执行操作命令与查询数据,而这些动作是并行执行的,且使用最小的网络负载。
官网:https://www.saltstack.com/
阿里云官方镜像:https://developer.aliyun.com/mirror/
https://mirrors.aliyun.com/saltstack/
1)下载安装EPEL源
yum install -y https://repo.saltstack.com/yum/redhat/salt-repo-latest-2.el7.noarch.rpm
注:服务端与客户端都需要下载与安装EPEL源
使用镜像安装初始化软件包yum install https://mirrors.aliyun.com/saltstack/yum/redhat/salt-repo-latest-2.el7.noarch.rpm
(配置yum源)
更改下载路径
sed -i "s/repo.saltstack.com/mirrors.aliyun.com\/saltstack/g" /etc/yum.repos.d/salt-latest.repo
2)master端设置:
yum install -y salt-master #安装master端
systemctl enable salt-master #设置master自启动
systemctl start salt-master #启动master服务
ss -lntup | grep salt
3)minion端配置:
在启动客户端之前,需要修改客户端的配置文件,来确定master是谁
yum install -y salt-minion #安装minion端
vim /etc/salt/minion
master: 172.25.6.1 #设置master主机的ip
systemctl enable salt-minion
systemctl start salt-minion
ps -ef | grep salt
注:在实际生产环境中,一般建议使用主机名
4)查看指定端口:
yum install lsof -y
lsof -i:4505
lsof -i:4506
5)公钥与私钥文件
minion端在第一次启动时会在/etc/salt/目录下产生一个pki目录
pki目录中的文件:
可以看到,在minion目录下会生成两个文件,一个是minion的公钥,另一个是minion的私钥,然后它会将自己的公钥文件发送给master
master端在第一次启动时也会在/etc/salt/目录下产生一个pki目录,这个目录中也有master端的公钥与私钥文件
pki目录中的文件:
6)SaltStack认证配置
SaltStack的服务端与客户端之间通信是需要配置认证的,使用salt-key命令来管理Key
salt-key命令的常用参数及说明
参数 | 说明 |
---|---|
-a | 参数后跟主机名,认证指定的主机 |
-A | 认证所有的主机 |
-L | 列出所有客户端的Key |
-D | 删除所有客户端的Key |
-d | 删除某一个客户端的Key |
在服务端,使用salt-key命令可以查看当前认证状态
可以看出,当前有一个Key处于拒绝状态
可以使用下面的命令去认证指定的主机
可以看出,服务端已经接受客户端的认证
再次查看服务端与客户端存放各自秘钥的目录是否有变化:
可以看出,认证的过程就是服务端与客户端之间交换各自公钥的过程
master端测试与minion端的连接:
minion端启动之后会生成minion_id,若更改操作系统的名字,而没有更改minion_id文件内的名字,minion_id不会改变,若想更新,需要把minion_id文件删除,重启minion端,master端将会自动生成新的文件
yum install -y python-setproctitle.x86_64
systemctl restart salt-master
#可以查看进程更详尽的信息
salt '' [arguments]
salt (命令) '*' (目标) cmd.run 'test.ping' (模块)
1)目标使用介绍
目标用于指定哪些minion端需要执行此命令操作
target:指定哪些minion,默认的规则是使用glob匹配minion_id
salt '*' test.ping
targets也可以使用正则表达式:
salt -E 'server[1-3]' test.ping
salt server? test.ping
targets也可以指定列表:
salt -L 'server2,server3' test.ping
salt ‘*’ cmd.run 'uname -a'
salt 'server2' sys.doc pkg #查看模板文档
salt 'server2' pkg.install httpd
salt 'server2' pkg.remove httpd
http://docs.saltstack.cn/ref/modules/all/index.html
(1)*:匹配规则,用来代表所有客户端
(2)IP地址:直接使用IP地址来指定客户端
(3)正则表达式:正则匹配
salt -E 'server(1|2)' test.ping
(4)客户端列表:使用主机名作为列表,主机名之间用“,”分隔
salt -L 'server1,server2' test.ping
salt 'server2' sys.list_modules #查看当前支持哪些模块
salt 'server2' sys.list_function cmd #查看某个模块所支持的函数
salt 'server2' sys.doc cmd.run #查看模块中某个函数的用法
vim /etc/salt/master
file_roots: #默认值
base:
- /srv/salt
systemctl restart salt-master
mkdir /srv/salt/_modules
vim /srv/salt/_modules/mydisk.py
def df():
return __salt__['cmd.run']('df -h')
salt server2 saltutil.sync_modules
salt server2 mydisk.df
1)缩进:使用空格缩进(两个空格),用来表示层级关系,不能使用< Tab >键
2)冒号:以冒号结尾的行的下一行必须缩进两个空格
字典的keys在YAML中的表现形式是一个以冒号结尾的字符串
my_key: my_value
3)短横线:使用“-”表示列表项,它与空格一起成对出现(一个短横杠加一个空格)
- list_value_one
- list_value_two
SaltStack从0.8.8版本起加入状态管理系统(state system)。配置管理文件以“.sls”结尾,默认使用YAML作为文件的描述格式,使用空格字符为缩进格式,不可以使用< Tab >键,配置文件注释使用“#”,字符串不使用引号,如果有引号就需要进行转义
vim /srv/salt/apache.sls
httpd: # ID声明
pkg: # 状态声明
- installed # 函数声明
或者:
httpd:
pkg.installed
salt server2 state.sls apache
安装多个包:
web:
pkg.installed:
- pkgs:
- httpd
vim /srv/salt/top.sls
base:
'*':
- apache
salt '*' state.highstate
apache/init.sls
就是表示apache
管理模块包括文件状态管理模块和服务状态管理模块
文件状态管理模块:
file.managed #保证文件存在并且为对应的状态
file.recurse #保证目录存在并且为对应的状态
file.absent #确保文件不存在,如果存在,则进行删除操作
服务状态管理模块:
service.running #确保服务处于运行状态,如果没有启动,则进行启动操作
service.enabled #确保服务会开机自启动
service.disenabled #确保服务不会开机自启动
service.dead #确保服务当前没有运行
salt server3 state.sls nginx
Grains存储的信息是静态数据,可用于收集minion端相关的本地信息,如操作系统版本、内核版本、CPU、内存、硬盘、网卡等信息
信息查询
用于查询minion端的IP、FQDN等信息
默认可用的grains:
salt '*' grains.ls
查看每一项的值:
salt '*' grains.items
取单项的值:
salt server2 grains.item ipv4
salt server2 grains.item fqdn
salt '*' grains.get hwaddr_interfaces #查看所有主机的所有网卡的MAC地址信息
salt '*' grains.get ip_interfaces #查看所有主机的所有IP地址信息
salt '*' grains.get os #查看所有主机的系统版本信息
自定义grains项
vim /etc/salt/minion
grains:
roles:
- apache
- httpd
重启salt-minion,否则数据不会更新:
systemctl restart salt-minion
salt server2 grains.item roles
vim /etc/salt/grains
deployment: datacenter1
不需要重启服务,但是需要同步
同步数据:
salt server2 saltutil.sync_grains
查询自定义项:
salt server2 grains.item deployment
编写grains模块
在salt-master端创建_grains目录:
mkdir /srv/salt/_grains
vim /srv/salt/_grains/my_grain.py
def my_grain():
grains = {}
grains['roles'] = 'nginx'
grains['hello'] = 'world'
return grains
salt '*' saltutil.sync_grains #同步grains到minion端
grains匹配运用
在target中匹配minion:
salt -G roles:apache cmd.run hostname
salt -G 'os:Centos' test.ping #系统版本为Centos的所有主机执行ping测试
salt -G 'os:Centos' cmd.run 'echo welcome to here!' #系统版本为Centos的所有主机执行一条命令
在top文件中匹配:
vim /srv/salt/top.sls
base:
'roles:apache':
- match: grain
- apache
'roles:nginx':
- match: grain
- nginx
salt '*' state.highstate
pillar在master端定义,然后指定对应的minion端,用saltutil.refresh_pillar刷新缓存来存储master指定的数据,且只有指定的minion端才能看到。基于这一点,此功能特别适用于保存敏感信息
声明pillar
定义pillar基础目录:
编辑配置文件/etc/salt/master
vim /etc/salt/master
pillar_roots:
base:
- /srv/pillar #设置pillar存储文件的目录
服务端创建此文件的存储目录
mkdir /srv/pillar -p
重启服务端服务
systemctl restart salt-master
/etc/init.d/salt-master restart
自定义pillar项
vim /srv/pillar/top.sls
base:
'*':
- packages
vim /srv/pillar/packages.sls
{% if grains['fqdn'] == 'server3' %}
package: httpd
{% elif grains['fqdn'] == 'server2' %}
package: mairadb
{% endif %}
刷新所有客户端pillar缓存,同步信息
salt '*' saltutil.refresh_pillar
查询pillar数据
salt '*' pillar.items
salt '*' pillar.item roles
salt -I 'roles:apache' test.ping
vim /srv/salt/apache.sls
apache:
pkg.installed:
- name: {{ pillar['package'] }}
1)两者的用途不同。Grains用于存储客户的基本信息,而Pillar用于存储master端分配给minion端的数据
2)存储数据的区域不同。Grains存储在客户端,而Pillar存储在服务端
3)更新方式不同。Grains是在minion启动时进行更新,也可以使用saltutil.sync_grains进行手工刷新。Pillar使用saltutil.refresh_pillar进行刷新,效率更高,更灵活。
Jinja模板使用方式
Jinja最基本的用法是使用控制结构包装条件:
vim /srv/salt/test.sls
/mnt/testfile:
file.append:
{% if grains['fqdn'] == 'server2' %}
- text: server2
{% elif grains['fqdn'] == 'server3' %}
- text: server3
{% endif %}
vim /srv/salt/apache.sls
/etc/httpd/conf/httpd.conf:
file.managed:
- source: salt://httpd.conf
- template: jinja
- context:
bind: 172.25.6.2 #指定监听地址
import方式,可在state文件之间共享
定义变量文件:
vim lib.sls
{% set port = 80 %}
导入模板文件:
vim httpd.conf
{% from 'lib.sls' import port %}
...
Listen {{ prot }}
引用变量
直接引用grains变量:
Listen {{ grains['ipv4'][1] }}
直接引用pillar变量:
Listen {{ pillar['ip'] }}
在state文件中引用:
- template: jinja
- context:
bind: {{ pillar['ip'] }}
Job简介
SaltStack在执行任何一个操作时,都会在master上产生一个JID
master将minion返回的执行结果存储在本地/var/cache/salt/master/jobs目录,默认缓存24小时,此配置可以通过修改master配置文件中的keepjobs选项来调整
Job缓存默认保存24小时:
vim /etc/salt/master
keep_jobs: 24
master端Job缓存目录:
/var/cache/salt/master/jobs
vim /etc/salt/master
master_job_cache: mysql
mysql.host: 'localhost'
mysql.user: 'salt'
mysql.pass: 'salt'
mysql.db: 'salt'
mysql.port: 3306
重启salt-master服务:
systemctl restart salt-master
安装mysql数据库:
yum install -y mariadb-server MySQL-python
执行数据库初始化脚本:
mysql_secure_installation
导入数据模板:
mysql -p < salt.sql
创建数据库授权:
mysql
> grant all on salt.* to salt@localhost identified by 'salt';
> grant all on salt.* to salt@'%' identified by 'salt';
salt.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;
Job管理
查看所有minion当前正在运行的jobs(在所有minions上运行saltutil.running)
salt-run jobs.active
列出当前master jobs cache中所有job
salt-run jobs.list_jobs
从master jobs cache中查询指定jid的运行结果
salt-run jobs.lookup_jid <jid>
yum install -y salt-ssh
salt-ssh配置
配置roster文件,默认的本地路径是 /etc/salt/roster:
server2:
host: 172.25.6.2
user: root
[root@server2 ~]# systemctl stop salt-minion
[root@server3 ~]# systemctl stop salt-minion
测试:
salt-ssh '*' test.ping -i //询问密码加 -i
#'*'指roster中指定的主机
vim ~/.ssh/config
StrictHostKeyChecking no
vim /etc/salt/master
order_masters: True #作为顶级master
systemctl start salt-master
salt-key -L #查看下级master的连接授权
salt-key -A
下级master端:
yum install -y salt-syndic
vim /etc/salt/master
syndic_master: 172.25.6.4 #指向topmaster
systemctl restart salt-master
systemctl start salt-syndic
可以看到,topmaster通过syndic转交给下级masters,下级masters继而和minions进行通信
salt-api简介
https://docs.saltstack.com/en/latest/ref/netapi/all/index.html#all- netapi-modules
salt-api配置
1)安装salt-api:
yum install -y salt-api python-cherrypy
在server1或server4上安装salt-api
在解决依赖性的同时会安装python-cherrypy
2)生成证书:
cd /etc/pki/tls/private
openssl genrsa 2048 > localhost.key
cd /etc/pki/tls/certs
make testcert #根据提示填写相关信息即可
useradd -s /sbin/nologin saltapi
echo westos | passwd --stdin saltapi
vim /etc/salt/master.d/auth.conf
external_auth:
pam:
saltapi:
- .*
- '@wheel'
- '@runner'
在调用api时,需要认证
创建认证文件,扩展名必须为.conf
创建用户
4)激活rest_cherrypy模块:
vim /etc/salt/master.d/api.conf
rest_cherrypy:
host: 172.25.0.1
port: 8000
ssl_crt: /etc/pki/tls/certs/localhost.crt
ssl_key: /etc/pki/tls/private/localhost.key
systemctl restart salt-master
systemctl start salt-api
curl -sSk https://172.25.0.1:8000/login \
-H 'Accept: application/x-yaml' \
-d username=saltapi \
-d password=westos \
-d eauth=pam
curl -sSk https://172.25.0.1:8000 \
-H 'Accept: application/x-yaml' \
-H 'X-Auth-Token: 77e2b1de04b0dbc0a4bf11900712b83e4fa2c241'\
-d client=local \
-d tgt='*' \
-d fun=test.ping
token值是上面命令获取的token值