导语:关于saltstack的使用首先考虑官网documention文档,https://docs.saltstack.com/en/latest/contents.html
1、salt介绍
saltstack是由thomas Hatch于2011年创建的一个开源项目,设计初衷是为了实现一个快速的远程执行系统。
2、salt原理
SaltStack 客户端(Minion)在启动时,会自动生成一套密钥,包含私钥和公钥。之后将公钥发送给服务器端,服务器端验证并接受公钥,以此来建立可靠且加密的通信连接
minion跟master在启动时候都会生成一对密钥,并且当minion在master上认证时候会将minion的公钥给master,同时master将公钥给minion。
可以将master中的minion.pub跟minion节点的minion.pub进行比较,可以发现一致。
3、saltstack运行方式
Local 本地运行,交付管理
Master/Minion <<< 常用方式
Salt SSH 不需要客户端
4、服务器环境准备
|服务器环境 | centos7.6 | centos7.6
|IP地址 | 172.27.187.23 | 172.27.187.24
|身份 | master | minion
| 软件包 | salt-master | salt-minion
注意:确保是在同一个局域网内
4.1 安装saltstack
salt软件包需要epel源的支持,那么下载
EPEL的全称叫 Extra Packages for Enterprise Linux 。EPEL是由 Fedora 社区打造,为 RHEL 及衍生发行版如 CentOS、Scientific Linux 等提供高质量软件包的项目。装上了 EPEL之后,就相当于添加了一个第三方源。
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum clean all #清空缓存
yum makecache #生成yum缓存
安装好epel源就可以开始安装salt了
查看salt包
yum list salt
安装salt-master
yum install salt-master -y
安装salt-minion
yum install salt-minion -y
4.2 配置minion,简单配置
1、在/etc/hosts中更改本地解析,将master的域名以及ip写上,以便于minion可以找到master
2、配置minion的配置文件,可以通过rpm -qc salt-minion查看可知,配置文件在/etc/salt/minion中,更改master:根据hosts中书写修改,可以写ip也可以写域名,保证minion可以找到master即可,id:配置为minion的名字;如下
vi /etc/hosts
172.27.187.23 master
172.27.187.22 slave
172.27.187.24 slave2
vi /etc/salt/minion
master: master
id: slave
master 参数为 salt-master 的域名,或者 IP 地址,这里设置的是上面配置的域名
id 参数为在 master 处看到的 minion 的名称,如果不指定,minion 会在启动时尝试自动判断 id,大多数系统 id 会被设置为 FQDN(全域名)
4.3 分别启动服务
systemctl start salt-master.service
systemctl start salt-minion.service
4.4 在 master 上查看并接受 minion 的密钥
minion 启动之后会请求 master 为其发送证书,证书签发完成后,表示 master 可以新人该 minion,
salt-key -L
Accepted Keys:
Denied Keys:
Unaccepted Keys:
slave
slave2
Rejected Keys:
# 这里 Unaccepted Keys:中的slave 是 salt-master 服务端的 minion 发送过来的
此时我们看到的 slave、slave2,表明两个 minion 客户端已经和服务端建立了联系,并且 master 已经获取了 minion 的公钥,正在等待更多进一步有关是否接受该 minion 的指令。我们可以查看密钥的指纹码来确保其与 minion 的密钥想匹配,在 master 上执行如下命令:
#在 master 上执行如下命令,查看密钥指纹码
# salt-key -f slave
Unaccepted Keys:
slave: ea:49:9f:26:34:5b:a8:3e:97:ba:60:af:06:77:9d:5b
#在 minion 上执行如下命令,查看密钥指纹码
# salt-call --local key.finger
local:
ea:49:9f:26:34:5b:a8:3e:97:ba:60:af:06:77:9d:5b
4.5 master 接受 minion 密钥有三种方式
## 第一种方式:每次接受一台minion 的key
# salt-key -a master
The following keys are going to be accepted:
Unaccepted Keys:
master
Proceed? [n/Y] y
Key for minion master accepted.
## 第二种方式:一次接受所有minion 的key
# salt-key -A
The following keys are going to be accepted:
Unaccepted Keys:
salve
Proceed? [n/Y] y
Key for minion slave accepted.
## 第三种方式:让 master 自动签发
# vi /etc/salt/master
auto_accept: True # 设置该选项, 需要重启
systemctl restart salt-master
## 查看已经接受的 minion
# salt-key -L
Accepted Keys:
slave
slave2
Denied Keys:
Unaccepted Keys:
Rejected Keys:
**测试是否可以**
# salt "*" test.ping #后面*号符合正则表达式的书写
slave:
True
slave2:
True
这是一条远程执行命令,用来简单的测试 minion 是否存活。
流程是,master 发送一条消息给所有的 minion,并告诉它们运行 salt 内置模块中一个函数。
注意:如果改用minion的key,1、需要删除/etc/salt/minion_id、/etc/salt/pki,2、删除master的key,通过salt-key -d salt-client -y
pillar讲解
简介
grains用于存储静态不易变更的数据,而pillar一般用于存储动态, 敏感的数据,通过minion和master设置或获取grains信息,而pillar信息只能在master端配置,在到minion端执行。pillar 默认使用sls文件进行数据存储(YAML格式),除此之外, pillar也同事支持多种后端的数据存储方式
常用的场景
1. 敏感数据:例如ssh key,加密整数等,由于Pillar使用独立的加密session,可以确保这些敏感数据不被其他minion看到。
2. 不同变量:可以再pillar中处理平台差异性,比如针对不同的操作系统设置软件包的名字,然后在state中引用。
3. 用户版本等变量:可以在pillar中添加任何需要用到的数据,比如定义用户和UID的对应关系,软件版本和端口,minion的角色等等
基础内容:
默认目录: /srv/pillar/, 在master配置文件中指定,目录默认需要自己创建。修改配置文件可修改。
入口文件: /srv/pillar/top.sls , pillar默认的主入口配置文件。
Pillar默认值:与grains不同,所有的pillar值都是人为设定的,默认pillar为空。
sls 文件:pillar的文件,sls是saltstack的缩写,YAML风格,支持jinja模板。
常用命令
salt '*' sys.doc pillar # 查看与pillar有关的帮助信息
salt '*' pillar.items # 获取所有pillar items值
salt '*' pillar.data # 等价于pillar.items
salt '*' saltutil.refresh_pillar # 刷新pillar值
salt '*' saltutil.sync_all # 刷新pillar值,与refresh_pillar操作类似,但范围更大
salt '*' sys.list_functions pillar # 列出所有的pillar相关函数方法
salt '*' pillar.get xxx # 获取某项的值,类似于python字典的get函数
salt '*' pillar.raw # 内存中获取
salt '*' state.highstate pillar={'app_name': 'ngx-internet'} # 在命令设置pillar 数据,可以在sls脚本中运用到相对应的值,例如要在不同的minion中设定值,就可以用这个办法
#数据格式,类似于字典
foo:
bar:
baz:qux
#获取方式:
{{ pillar['foo']['bar']['baz']}}
{{ salt['pillar.get']('foo:bar:baz', 'qux')}}
Master配置文件中关于pillar的相关信息
(1) pillar目录
pillar_roots:
base:
- /srv/pillar
(2) 是否将master配置文件中的数据信息添加到pillar中,默认是不加,需要的话可以改成True,重启服务生效。
pillar_opts: False
(3) pillar 源,salt支持引入pillar外部资源,例如从数据库导入pillar值,默认是关闭的
ext_pillar_first: False
(4) 开启pillar gitgs ssl验证
pillar_gitfs_ssl_verify: True
(5) 开启pillar render 错误信息
pillar_safe_render_error: True
(6) 设置pillar配置合并策略
pillar_source_merging_strategy: smart
Pillar的刷新方式
salt '*' saltutil.refresh_pillar
salt '*' saltutil.sync_all
#编写完pillar最好手动刷新一次
salt '*' saltutil.refresh_pillar
[root@saltmaster pillar]# salt '*' saltutil.refresh_pillar
saltmaster:
True
salt '*' saltutil.sync_all
[root@saltmaster pillar]# salt '*' saltutil.sync_all
saltmaster:
----------
beacons:
clouds:
engines:
grains:
log_handlers:
modules:
output:
proxymodules:
renderers:
returners:
sdb:
states:
utils:
刷pillar 的输出结果
关于pillar的 sls 文件使用说明:
默认的入口文件为/src/pillar/top.sls
top.sls的引用方式分为两种:
将引用sls文件放在同级目录
在/src/pillar/ 目录下创建对应的nginx目录,并在该目录下创建init.sls文件。
备注:如果要引用执行的sls文件和目录同时存在,也就是方法一和方法二都存在,nginx.sls和nginx/init.sls,会优先使用nginx.sls文件。
方式一:
[root@saltmaster srv]# tree /srv/pillar/
/srv/pillar/ # 默认pillar文件目录
├── nginx.sls # nginx 引用文件
└── top.sls # 固定的入口文件top.sls
方式二:
[root@saltmaster srv]# tree /srv/pillar/
/srv/pillar/
├── nginx # nginx 目录
│ └── init.sls # 引用文件
└── top.sls # 固定的入口文件top.sls
#引入文件说明
[root@saltmaster pillar]# cat nginx.sls
nginx:
package-name: nginx
version: 2.2.4
top.sls引用说明
配置好top.sls以及附属sls文件后,可以刷新一下pillar,查看各个pillar值
个人总结:通过pillar模块可以自定义pillar值,便于管理,将不同的信息部署到不同的minion中,先要在top.sls中定义pillar数据所在的目录,如上结构,然后在nginx目录下创建init.sls文件,将需要的数据放在里面,如果有多个数据文件,均要在top.sls总入口进行定义。
salt中sls文件书写
1.1 file.managed作用
是salt.states.file模块中使用最普遍的一个函数了,功能是将一个文件从master端传递到minion端,使得两边的内容一致。
这个文件的内容可以是某种模板语言,例如jinja,从而使得master端文件维持不变的情况下传递到minion端的文件内容灵活多变。
参数详解
name
存放在minion端的文件路径,必须是绝对路径。通常这个参数作为了state文件里面的ID。
例如
name: /home/vagrant/test.txt
source :存放在master端的文件路径,必须是相对于file_roots的路径。file_roots用**salt://**来表示,默认情况下的路径为/srv/salt/。
假如有个文件路径为/srv/salt/files/test.txt,那么这个参数应该配置为
source: salt://files/test.txt
有了name和source两个参数就可以完整最基本的文件传输功能,例如创建一个state文件file_backup_test.sls如下
bash
/home/vagrant/file_backup_test.txt:
file.managed:
- source: salt://files/file_backup_test.txt
在这个脚本中调用了file模块的managed函数,如果定义了name的话就会将其作为参数传入到函数中,如果没有name,就会将自定义的id去传参。
就可以把master端的/srv/salt/files/file_backup_test.txt同步到minion端的/home/vagrant/file_backup_test.txt。
file.directoy
可以参考以下链接,file中各个模块的作用https://blog.51cto.com/nginxs/1346258
https://blog.csdn.net/weixin_44541528/article/details/95458259
SaltStack如何拷贝master服务器上文件和目录到minion服务器
使用cp.get_file和 cp.get_dir函数来实现功能
1、cp.get_file实现从master端复制文件到minion服务器的文件中
我们操作实现一个/srv/salt/dev/data/zabbix_agentd_install.sh 拷贝到 web9这个服务器的/home/shell/zabbix_agent_install.sh
使用的命令是:
salt 'web9' cp.get_file salt://dev/data/zabbix_agentd_install.sh /home/shell/zabbix_agent_install.sh
2、cp.get_dir是实现从master端复制目录到minion服务器的对应目录下
如果拷贝一个文件到minion端的文件中,如果是我们拷贝data这个目录过去呢,就需要用到cp.get_dir 这个命令。命令用法是:
salt 'web9' cp.get_dir salt://dev/data /home/shell/
#注意:/home/shell下边不要跟其他的,salt会自动到下边常见data目录。现在到web9的服务器/home/shell查看多了一个data目录
各模块的学习可以参考:
https://docs.saltstack.com/en/latest/ref/states/all/index.html
saltstack执行模块state介绍:
1.state.apply会将highdata缓存到minion端(high data是组成sls文件的块,而多个sls文件通过top.sls文件内的一个环境使用就组成了 highstate了)
state.apply会调用state.highstate 或者 state.sls,这个基于后面的参数。分为以下两种
a. salt ‘’ state.apply 会执行top.sls state文件。
b. salt '’ state.apply install-man 执行salt://install-man 或者salt://install-man/init.sls
2.当执行state.highstate方法时,salt会自动编译在top.sls中的所有sls文件,编译到单独的definition中,称为highstate。
3.state.sls 执行一个或多个sls文件
nginx安装脚本
{% set install_dir = '/opt/nginxintall' %}
{% set app_dir = '/opt/nginx' %}
make-app-directory-{{ app_name }}:
cmd.run:
- name: rm -rf {{ install_dir }}/
file.directory:
- name: {{ install_dir }}
- dir_mode: 700
- file_mode: 600
- user: root
- group: root
- makedirs: True
- recurse:
- mode
get-installzip:
file.managed:
- name: {{ install_dir }}/install-plugins.zip
- source: salt://nginx/install-plugins.zip
- user: root
- group: root
- require:
- file: make-app-directory-{{ app_name }}
cmd.run:
- name: cd {{ install_dir }}/ && unzip install-plugins.zip && chown -R root:root {{ install_dir }}
install-app-{{ app_name }}:
cmd.run:
- name: cd {{ install_dir }}/install-plugins/ && sh build_nginx_1.16.0.sh >intall.log 2>&1
- require:
- cmd: get-installzip
get-conf:
file.managed:
- name: {{ app_dir }}/1.16.0/conf.zip
- source: salt://{{ app_info['filepath'] }}
- user: root
- group: root
- require:
- cmd: install-app-{{ app_name }}
cmd.run:
- name: rm -rf {{ app_dir }}/1.16.0/conf/ && cd {{ app_dir }}/1.16.0 && unzip {{ app_dir }}/1.16.0/conf.zip
get-luainit:
file.managed:
- name: {{ app_dir }}/1.16.0/luascript/init.lua
- source: salt://nginx/init.lua
- user: root
- group: root
- require:
- cmd: install-app-{{ app_name }}
cmd.run:
- name: cp {{ app_dir }}/1.16.0/luascript/json.lua /usr/local/share/lua/5.1/json.lua
get-robots:
file.managed:
- name: {{ app_dir }}/1.16.0/htdocs.zip
- source: salt://nginx/htdocs.zip
- user: root
- group: root
- require:
- cmd: install-app-{{ app_name }}
cmd.run:
- name: rm -rf {{ app_dir }}/1.16.0/htdocs/ && cd {{ app_dir }}/1.16.0 && unzip {{ app_dir }}/1.16.0/htdocs.zip && mkdir -p /opt/nginx/1.16.0/proxy_pass_cache
get-policy:
file.managed:
- name: {{ app_dir }}/1.16.0/luascript/policy.json
- source: salt://{{ json_path }}
- user: root
- group: root
modify-rights:
cmd.run:
- names:
- chown -R cloudlink:cloudlink /usr/local/share/lua/
- chown -R cloudlink:cloudlink /opt/nginx/
run-nginx:
cmd.run:
- name: {{ app_dir }}/1.16.0/sbin/nginx
- require:
- cmd: get-conf
- cmd: get-robots
- cmd: get-luainit
clear-app-{{ app_name }}:
cmd.run:
- name: salt-call saltutil.clear_cache
nginx配置文件更新脚本
{% set app_dir = '/opt/nginx' %}
backup-app-directory-{{ app_name }}:
cmd.run:
- names:
- date "+%Y%m%d_%H%M%S" | awk '{time=$1;cmd="mv {{ app_dir }}/1.16.0/conf/ {{ app_dir }}/1.16.0/conf_back"time"";system(cmd)}'
- user: cloudlink
- group: cloudlink
get-conf:
file.managed:
- name: {{ app_dir }}/1.16.0/conf.zip
- source: salt://{{ app_info['filepath'] }}
- user: cloudlink
- group: cloudlink
- require:
- cmd: backup-app-directory-{{ app_name }}
cmd.run:
- name: cd {{ app_dir }}/1.16.0 && unzip {{ app_dir }}/1.16.0/conf.zip && chown -R cloudlink:cloudlink {{ app_dir }}/1.16.0/conf/
backup-app-policy-{{ app_name }}:
cmd.run:
- names:
- date "+%Y%m%d_%H%M%S" | awk '{time=$1;cmd="cp {{ app_dir }}/1.16.0/luascript/policy.json {{ app_dir }}/1.16.0/luascript/policy.json"time"";system(cmd)}'
- user: cloudlink
- group: cloudlink
get-policy:
file.managed:
- name: {{ app_dir }}/1.16.0/luascript/policy.json
- source: salt://{{ json_path }}
- user: cloudlink
- group: cloudlink
- require:
- cmd: backup-app-policy-{{ app_name }}
test-conf:
cmd.run:
- name: {{ app_dir }}/1.16.0/sbin/nginx -t
- require:
- cmd: get-conf
reload-conf:
cmd.run:
- name: {{ app_dir }}/1.16.0/sbin/nginx -s reload
- require:
- cmd: test-conf
clear-app-search:
cmd.run:
- name: salt-call saltutil.clear_cache