💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
推荐:Linux运维老纪的首页,持续学习,不断总结,共同进步,活到老学到老
导航剑指大厂系列:全面总结 运维核心技术:系统基础、数据库、网路技术、系统安全、自动化运维、容器技术、监控工具、脚本编程、云服务等。
常用运维工具系列:常用的运维开发工具, zabbix、nagios、docker、k8s、puppet、ansible等
数据库系列:详细总结了常用数据库 mysql、Redis、MongoDB、oracle 技术点,以及工作中遇到的 mysql 问题等
懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
自动化运维之SaltStack 部署应用
技能目标
- 掌握 SaltStack 的原理和安装
- 掌握 SaltStack 的常用模块
- 掌握SaltStack的grains、
pillar、state
1.1 SaltStack 基础
在生产环境中,服务器往往不只是一台,有可能是成千上万台。对于运维人员来说,如
果单独的对每台服务器进行管理,工作难度比较大。这时部署自动化运维就可以尽可
能安全、高效的完成这些工作。
一般,会把自动化运维工具划分为两类:一类是需要使用代理工具的,也就是基
于专用的 Agent 程序来完成管理功能,如:SaltStack、Puppet、Func、Zabbix 等;
另外一类是不需要配置代理工具的,可以直接基于 SSH 服务来完成管理功能,如:
Ansible、Fabric 等。本章将主要介绍自动化运维工具 SaltStack 是如何实现自动化运
维部署的。下面是几款功能类似的自动化运维工具。
SaltStack:是一个服务器基础设施管理工具,它具有配置管理、远程执行、监控等功
能。SaltStack 由 Python 语言编写,是非常简单易用和轻量级的管理工具。
Ansible:是基于 Python 开发的,集合了众多优秀运维工具的优点,实现了批量
运行命令、部署程序、配置系统等功能的自动化运维管理工具。默认通过 SSH
协议进行远程命令执行或下发配置,无需部署任何客户端代理软件,从而使得自
动化环境部署变得更加简单。可同时支持多台主机并行管理,使得管理主机更加
便捷。
Puppet:是基于 Ruby 开发的,支持 Linux、Unix、Windows 平台的自动化运维
管理工具,可以针对用户、系统服务、配置文件、软件包等进行管理,有很强的
扩展性,但远程执行命令相对较弱。
针对这几款自动化运维工具比较如表 1-1 所示。
表 1-1 自动化运维工具比较
工具 | 开发语言 | 结构 | 配置文件格式 | 运行任务 |
Ansible | Python | 无 | YAML | 支持命令行 |
SaltStack | Python | C/S | YAML | 支持命令行 |
Puppet | Ruby | C/S | Ruby 语法格式 | 通过模块实现 |
通过部署 SaltStack 环境,可以在成千上万台服务器上批量执行命令,对于不同的业务
进行集中管理、分发文件、采集数据、软件包管理等。有利于运维人员提高工作效率、规范
业务配置和操作。
1.SaltStack 原理
SaltStack 由 Master 和 Minion 构成,Master 是服务器端,表示一台服务器,Minion
是客户服务器端,表示多台服务器。在 Master 上发送命令给符合条件的 Minion,Minion 就
会执行相应的命令。Master 和 Minion 之间是通过 ZeroMQ(消息队列)进行通信。
SaltStack 的 Master 端监听 4505 与 4506 端口,4505 为 SaltStack 的消息发布端口,
4506 为 SaltStack 客户端与服务端通信的端口。SaltStack 客户端程序并不监听端口,当客
户端启动后,会主动连接 Master 端注册,然后一直保持该 TCP 连接,而 Master 通过这条
TCP 连接对客户端进行控制。如果连接断开,Master 对客户端将不能进行控制。但是,当
客户端检查到连接断开后,会定期的向 Master 端请求注册连接。
2.SaltStack 安装
SaltStack 的 Master 和 Minion 安装非常简单,在 CentOS 系统中的安装步骤如下。
(1)安装 EPEL 源
在 CentOS 官方 YUM 源中没有 SaltStack 的安装包支持,需要先安装第三方的 EPEL
作为部署 SaltStack 的 YUM 源,具体操作如下所示。
[root@master ~]# yum install -y epel-release
//Master 与 Minion 均需要操作
(2)安装 Master
在 Master 端上安装 salt-master 软件,具体操作如下所示。
[root@master ~]# yum install -y salt-master
(3)安装 Minion
在 Minion 端上安装 salt-minion 软件,具体操作如下所示。
[root@minion ~]# yum install -y salt-minion
(4)配置 Master
修改 Master 的配置文件,具体操作如下所示。
[root@master ~]# vim /etc/salt/master
interface: 192.168.9.233
//设置监听的地址
auto_accept: True
//设置自动接受客户端发送过来的 Key,如果服务器很多的话,
需要开启该功能
修改后可以启动 Master,具体操作如下所示。
[root@master ~]# systemctl start salt-master
[root@master ~]# systemctl enable salt-master
Created
symlink
from
/etc/systemd/system/multi-user.target.wants/salt-master.service
to
/usr/lib/systemd/system/salt-master.service.
(5)配置 Minion
修改 Minion 的配置文件,具体操作如下所示。
[root@minion ~]# vim /etc/salt/minion
master: 192.168.9.233
//改成前面的 Master 服务器地址
id: minion.saltstack.com
//建议这里修改成主机名,便于 Master 端识别
......
//省略内容
//在配置文件末尾加入下面内容,设置每隔 10 分钟自动同步 Master 配置。其效果等同于在客户端执
行 salt-call state.highstate 或在 server 端执行 salt ‘*‘state.highstate
schedule:
highstate:
function: state.highstate
minutes: 10
修改后可以启动 Minion,具体操作如下所示。
[root@minion ~]# systemctl start salt-minion
[root@minion ~]# systemctl enable salt-minion
Created
symlink
from
/etc/systemd/system/multi-user.target.wants/salt-minion.service
to
/usr/lib/systemd/system/salt-minion.service.
当 Minion 启动后,会自动生成公钥私钥,并将公钥发送到 Master 端。Minion 不监听
端口,全靠和 Master 保持长连接,可通过 netstat -an | grep ES 命令查看是否连接成功。
至此 SaltStack 安装完成。
3.SaltStack 使用
安装好 SaltStack 后,就可以在 Master 上面通过命令对 Minion 进行操作了。
(1)salt 实时批量操作,语法如下:
salt [选项] '<target>' <function> [arguments]
常用命令举例:
在 Master 端测试 Minion 是否连接正常。
salt '*' test.ping
上述命令中“*”为匹配所有主机,“test.ping”为 salt 一个函数。*号是正则,若分了多个组,
可以通过类似于 web*,来只匹配 web 服务器。
查看所有主机的磁盘信息,cmd.run 执行单个命令。
salt '*' cmd.run 'df -h'
把本地脚本拷贝到远程主机上执行。
salt '*' cmd.script salt://test.sh
salt '*' cmd.script salt://scripts/runme.sh 'arg1 arg2 arg3'
上述命令中,”cmd.script”表示执行一个脚本,即把本地脚本拷贝到远程主机上执行,
test.sh 要放在指定的文件存放路径,默认是/srv/salt/。脚本后面也可以跟参数执行,比如
arg1、arg2、arg3。
向客户端推送 Master 端配置。
salt '*' state.highstate
查看所有主机的磁盘信息,并设置该命令执行的超时控制。
salt '*' cmd.run 'df -h' -t 5
(2)salt 分组管理,在配置文件/etc/salt/master 中加入如下内容:
vim /etc/salt/master
nodegroups:
group1: 'L@Server-11,Server-12'
group2: '@testmind'
//分组格式可在/etc/salt/master 中搜索 group,查看示例代码
salt -N web01group cmd.run 'hostname'
//分组执行
(3)salt-run 检查客户端 up 状态,具体操作如下所示。
salt-run manage.status
//查看所有客户端 up/down 状态
salt-run manage.up
//只显示 up 状态的客户端
salt-run manage.down
//只显示 down 状态的客户端
(4) salt-cp 批量拷贝文件,在 master 端执行,语法如下:
salt-cp [options] ‘<target>‘SOURCE DEST
示例代码如下:
salt-cp '*' /etc/hosts /etc/hosts
//把 Master 上的 hosts 文件分发到所有主机。
(5)SaltStack 定时同步
可以将 salt-call state.highstate 命令放在 Minion 端的定时任务中,来进行自动请求同
步。也可以将 salt ‘*‘ state.highstate 命令放在 Master 端的定时任务中,来进行自动推送到
所有机器。也可以在/etc/salt/minion 配置文件中加入如下内容,如下代码是每隔 10 分钟同
步。
schedule:
highstate:
function: state.highstate
seconds:600
(6)SaltStack 自动分发目录
指定同步的目录后,文件只需放到该目录下就会自动同步到 Minion 端,示例代码如下。
cat /srv/salt/top.sls
base:
"Server*":
- ssh_key.key
- zabbix.zabbix
//在 top.sls 文件中指定 Server 开头主机访问 zabbix.sls 文件里面定义的内容
[root@li salt]# cat /srv/salt/zabbix/zabbix.sls
/usr/local/zabbix/scripts:
//指定 Minion 端同步后生成的目录
file.recurse:
- source: salt://zabbix/zabbix_scripts
//指定要 Master 端同步的原始目录,以后只要把想要分发
的文件放在这个目录中,就会自动同步了
- dir_mode: 755
//用 dir_mode 设置目录的权限
- file_mode: 744
//用 file_mode 来设置文件的权限
(7)SaltStack 自动分发文件
当文件出现变更时,匹配 Server 开头的主机,同步文件到这些 Minion 上,并设置为对
应的文件权限,示例如下。
cat /srv/salt/top.sls
base:
"Server*":
- ssh_key.key
- zabbix.zabbix
cat /srv/salt/zabbix/zabbix.sls
/usr/local/zabbix/etc/zabbix_agentd.conf.d/UserParameter.conf:
//指定在 Minion 端生成的文件名
file.managed:
- source: salt://zabbix/UserParameter.conf //指定在 Master 同步的原始文件
- backup: minion
- mode: 744
- user: root
- group: root
//当文件发生变化时,都会把原文件备份,备份文件目录:/var/cache/salt/minion/
1.2 SaltStack 模块及应用
SaltStack 工具提供了非常多的功能模块,以便于对操作系统的基础功能和常用工具进
行操作。
1.2.1 SaltStack 常用模块
1.pkg 模块
pkg 模块的作用是包管理,包括增删更新。语法如下:
name: 包名称
(1)安装单个 httpd 包,示例代码如下。
httpd:
pkg.installed
//或者
lg_httpd:
pkg.installed:
- name: httpd
(2)安装一系列软件包,示例代码如下。
mypkgs:
pkg.installed:
- pkgs:
- foo
- bar
- baz
(3)指定软件版本<, <=, >=, and >,示例代码如下:
mypkgs:
pkg.installed:
- pkgs:
- foo
- bar: 1.2.3-4
- baz
或者
mypkgs:
pkg.installed:
- pkgs:
- foo
- bar: '>=1.2.3-4'
- baz
(4)安装指定相关 rpm 包,示例代码如下:
mypkgs:
pkg.installed:
- sources:
- foo: salt://rpms/foo.rpm
- bar: http://somesite.org/bar.rpm
- baz: ftp://someothersite.org/baz.rpm
- qux: /minion/path/to/qux.rpm
(5)升级软件包到最新,示例代码如下:
mypkgs:
pkg.latest:
- pkgs:
- foo
- bar
- baz
(6)删除软件包,示例代码如下:
foo:
pkg.removed
(7)删除多个软件包,示例代码如下:
mypkgs_remove:
pkg.removed:
- pkgs:
- foo
- bar
2.file 模块
file 模块的作用是管理文件操作,包括同步文件,设置文件权限,所属用户组,删除文
件等操作。file 模块的参数如下所示:
(1)file.managed:文件管理:
name:要同步到 Minion 上的文件路径+文件名;
source:同步文件源为 Master 上的文件;
backup 参数:备份作用,如果有改动才会备份;
backup: .bak 会在 Minion 上该文件的同级目录下加.bak 备份;
backup:minion,会备份到 Minion 下的/var/cache/salt/minion/backup_files
下。
mode:权限设置,例如 644;
owner:所属设置;
group:所属组设置。
(2)file.append:向文件中添加内容:
text:向文件中添加内容信息;
(3)file.comment:文件注释操作:
char:设置注释使用的字符,默认是#;
regex:需要跟文件中每一行中信息匹配的正则表达式。
(4)file.copy:把 Minion 本地文件复制到某个目录下:
source:Minion 本地文件;
makedirs:如果复制的目标目录不存在是否要创建;
force:如果复制目标文件和源文件是相同的文件名,是否覆盖;
(5)file.directory:目录创建:
user:对新创建文件夹设置所属用户;
group:对新创建文件夹设置所属组;
dir_mode:对新创建文件夹设置访问权限;
file_mode:对新创建文件夹下文件设置权限;
recurse:递归接受以上设置,用户组等等;
makedirs:强制建立文件夹 = mkdir -p。
以上参数只有对新建的文件夹设置相应的属性,原来存在属性都不变更。
(6)file.exists:判断文件是否存在;
(7)file.absent:删除文件;
(8)file.symlink:建立 link 链接参数详解:
name:源文件;
target:目标文件;
force:是否强制创建。
(9)file.touch:创建空文件,或者修改文件三个时间;
name:文件名;
atime:访问时间;
mtime:修改时间;
makedirs:如果目录不存在,是否创建目录。
下面演示几个 file 模块的使用方法:
(1)YUM 安装源配置文件同步,示例代码如下。
yum:
file.managed:
- name: /etc/repo.d/centos-base.repo
- source: salt://files/centos-base.repo
- mode: 644
- owner: root
- group: root
(2)同步之前备份文件,示例代码如下。
/tmp/c.log:
file.managed:
- source:
- salt://a.log
- backup: .bak
或者
/tmp/dd.log:
file.managed:
- source:
- salt://a.log
- backup: minion
(3)向 Minion 的文件中追加内容,示例代码如下。
/tmp/d.log:
file.append:
- text: |
Thou hadst better eat salt with the Philosophers of Greece,
than sugar with the Courtiers of Italy.
- Benjamin Franklin
或者:
/tmp/e.log:
file.append:
- text:
- Trust no one unless you have eaten much salt with him.
- "Salt is born of the purest of parents: the sun and the sea."
或者
#a.log b.log append /tmp/bb.log
/tmp/bb.log:
file:
- append
- sources:
- salt://a.log
- salt://b.log
(4)添加注释 ,默认添加#,示例代码如下。
/tmp/a.log:
file.comment:
- regex: ^s
(5)把本地的文件拷贝到其他的目录中,示例代码如下。
/tmp/abc/a.log:
file.copy:
- source: /tmp/b.log
- makedirs: True
- force: True
(6)创建目录,并作相应设置,示例代码如下。
/tmp/aaa/bbb/ddd/fff:
file.directory:
- user: root
- group: root
- dir_mode: 755
- file_mode: 644
- makedirs: True
- recurse:
- user
- group
- mode
(7)判断文件是否存在,示例代码如下。
/tmp/a.log:
file.exists
(8)设置链接,示例代码如下。
/tmp/aaa.log:
file.symlink:
- target: /tmp/alink.log
- force: True
#创建一个空文件
/tmp/bbb.log:
file.touch
#删除文件:
/tmp/ccc.log:
file.absent
#使用 red 替换文件中字符串
/tmp/red.log:
file.red:
- before: 'blue'
- after: 'black'
- limit: 's'
#高级运用使用模板
/tmp/template_test.conf:
file.managed:
- source: salt://template_test.conf
- mode: 644
- owner: root
- group: root
- template: jinja
template_test.conf 文件中的内容--------------->
{% if grains['os'] == 'RedHat' %}
host: {{ grains['host'] }}
{% elif grains['os'] == 'CentOS' %}
host: {{ grains['fqdn'] }}
{% endif %}
3.cmd 模块
cmd 模块的作用是在 Minion 上执行命令或者脚本,参数如下所示。
(1)cmd.run 参数
name:执行脚本或者命令的名字;
onlyif:测试命令,如果执行测试命令返回 true,cmd.run 的命令才有可能执行;
unless:与 onlyif 相反,如果执行后为 false,cmd.run 的命令才有可能执行;
cwd:执行命令当前目录设置,默认为/root;
user:执行命令的用户,默认 root;
group:执行命令的组,默认 root;
shell:执行命令使用的 Shell;
env:执行命令的环境设置;
umask:运行命令时候 umask 设置;
output_loglevel:执行命令日志输出级别,其中特殊的设置是 quiet,不输出日志;
timeout:执行命令的超时时间,如果超时就发送 kill -l SIGTERM 命令,如果"kill -l
SIGTERM"被忽略了,那么紧接着发送 kill 命令。
(2)cmd.wait 参数
与 cmd.run 中的参数相比,只是 wait 中没有 timeout 参数,其他参数意义一样。cmd.run
和 cmd.wait 的区别是:多个判断条件时候,只要有一个条件满足就会执行 cmd.run,只有
所有的条件都满足才会执行 cmd.wait。
下面演示 cmd 模块的使用方法:
(1)在/tmp 目录下,使用 nobody 用户执行脚本/tmp/testscript,示例代码如下。
Run testscript:
cmd.run:
- name: /tmp/testscript
- cwd: /
- user: nobody
- mode
(2)判断 httpd 配置文件是否改动,如果改动,执行同步,然后测试配置文件是否可用,
如果可用,重新加载配置文件,示例代码如下。
"/etc/httpd/conf/httpd.conf":
file.managed:
- source: salt://httpd/conf/httpd.conf
reloadhttpd:
cmd.wait:
- name: "/etc/init.d/httpd graceful"
- onlyif: "/etc/init.d/httpd configtest"
- watch:
- file: /etc/httpd/conf/httpd.conf
需要注意的是:"/etc/httpd/conf/httpd.conf" 配置文件这块,最好使用引号,因为有时
候可能会含有特殊字符。
4.user 模块
user 模块的作用是管理系统账户操作,参数如下所示:
(1)user.present 参数中 uid、gid、home 等选项没有设置是系统默认设置,参数详解:
name:要创建的用户名;
uid:设置 uid;
gid:设置默认的组 gid;
groups:设置用户所属组;
home:用户的自定义登录目录;
password:为用户设置密码;
enforce_password:如果密码已设置且密码哈希值与“password”字段中设置的密
码不同,则设置为 False 以防止密码被更改。如果未设置“password”,则忽略此选
项,默认为 True;
shell:设置用户的登录后的 Shell,默认将设置为系统默 Shell;
(2)user.absent 用于删除用户参数详解:
name: 设置需要删除的用户名;
purge: 是否删除用户家目录;
force: 如果用户当前已登录,则 absent state 会失败。选项为 True 时,就算用户
当前处于登录状态也会删除本用户。
User 模块的使用方法如下所示:
(1)创建用户 aaa 并设置密码、shell、home 目录、uid、gid、其他所属组,示例代码
如下。
laoseng:
user.present:
- password: '7D2dlkjDoOO988DFDS'
- shell: /bin/bash
- home: /home/aaa
- uid: 888
- gid: 888
- groups:
- wheel
- storage
(2)创建用户 laoseng,示例代码如下。
laoseng:
user.absent
5.service 模块
service 模块的作用是管理系统服务操作,包括 start、stop、reload、restart,参数如
下所示:
name:服务名称;
enable:设置自启动 True,默认不设置;
watch:监控一些条件,如果成立默认执行 restart。
reload:默认为 False,如果设置为 True 时候,当 watch 条件成立,则会 reload,
不会 restart。
service 模块的使用方法:Apache 服务管理。示例代码如下:
httpd:
service:
- running
- enable: True
- reload: True
- watch:
- pkg: httpd
6.cron 模块
cron 模块作用管理 cron 服务操作,参数如下所示:
cron.present 添加 cron 任务,参数:
name:资源名字;
user:默认 root,或者指定用户执行;
minute、hour、daymonth、month、dayweek:参数默认是*;
cron.absent:删除 cron 任务。
cron 模块使用方法如下所示。
(1)添加 cron 任务,示例代码如下:
/path/to/cron/script:
cron.present:
- user: root
- minute: random
- hour: 2
- daymonth: '*'
- month: '*/2'
- dayweek: 4
- comment: "this script is rsync pic"
或者
rsync_pic:
cron.present:
- name: "/bin/sh /tmp/script.sh >/dev/null 2>&1"
- comment: "this script.sh is rsync log"
- user: root
- minute: random
- hour: 2
- month: '*/2'
- dayweek: 4
- pkg: httpd
(2)删除 cron 任务,示例代码如下:
/path/to/cron/script:
cron.absent
7.hosts 模块
hosts 模块的作用是管理/etc/hosts 文件,参数如下所示。
(1)host.present 添加域名,参数:
name:域名;
names:多个域名;
ip:ip 地址。
(2)host.absent 删除域名。
hosts 模块使用方法如下所示:
(1)添加单个 ip 与单个域名对应,示例代码如下:
host2:
host.present:
- ip: 192.168.1.12
- name:
- 2.bbb.com
(2)添加单个 ip 与多域名对应,示例代码如下:
host1:
host.present:
- ip: 192.168.1.12
- names:
- 2.bbb.com
- test.test.com
(3)删除 ip 对应的域名,示例代码如下:
host3:
host.absent:
- ip: 192.168.1.12
- name: 2.bbb.com
1.2.2 综合应用案例
案例需求:
使用 YUM 安装 Apache 服务;
设置 Apache 用户和组;
设置同步配置文件,并启动服务。
案例实现:
所需模块:pkg 模块、user 模块、组模块、service 模块、配置文件模块。
建立模块之间的关系:安装模块-->建立用户和组-->设置 httpd 目录-->同步配置文
件-->启动服务。
示例代码如下。
apache:
pkg:
- installed
service:
- running
- watch:
- pkg: apache
- file: /etc/httpd/conf/httpd.conf
- user: apache
user.present:
- uid: 87
- gid: 87
- home: /var/www/html
- shell: /bin/nologin
- require:
- group: apache
group.present:
- gid: 87
- require:
- pkg: apache
/etc/httpd/conf/httpd.conf:
file.managed:
- source: salt://apache/httpd.conf
- user: root
- group: root
- mode: 644
1.3 SaltStack 批量部署并配置 Nginx
1.3.1 案例环境
在生产环境中,经常需要根据不同的业务需求来分组部署和配置 Nginx 服务器。本案
例使用三台服务器,均采用 CentOS 7.3 系统,要求能上互联网,Selinux 和防火墙均已关
闭。
需要注意的是,三台服务器一定要设置完整的 fqdn,和域名一样的形式,不然在主控
端执行远程操作或者配置的时候等待时间会非常长,甚至还会出现其它不可控的问题。服务
器具体参数配置如表 1-2 所示。
表 1-2 服务器参数
角色 | 主机名 | IP 地址 | 组名 | cpu 个数 | Nginx 根目录 |
master | master.saltstack.com | 192.168.9.233 | — | — | |
minion | web01.saltstack.com | 192.168.9.234 | web01group | 1 | /data |
minion | web02.saltstack.com | 192.168.9.235 | web02group | 2 | /www |
实验网络拓扑如图 1.1 所示。
图 1.1 网络拓扑
1.3.2 操作步骤
1. SaltStack 安装
下面演示部署服务器的具体步骤。
(1)在三台服务器增加主机名和 IP 的映射关系,修改/etc/hosts 文件,增加如下内容。
生产环境建议使用 DNS 服务器统一做解析管理。
[root@localhost ~]# hostnamectl set-hostname master.saltstack.com
[root@localhost ~]# bash
[root@master ~]#
[root@localhost ~]# hostnamectl set-hostname web01.saltstack.com
[root@localhost ~]# bash
[root@web01 ~]#
[root@localhost ~]# hostnamectl set-hostname web02.saltstack.com
[root@localhost ~]# bash
[root@web02 ~]#
[root@master ~]# cat << EOF >> /etc/hosts
192.168.9.233 master.saltstack.com
192.168.9.234 web01.saltstack.com
192.168.9.235 web02.saltstack.com
EOF
//三台服务器上均操作
(2)因为后面需要安装 SaltStack 服务端、SaltStack 客户端与 Nginx 服务,所以在三
台服务器上都需要安装 EPEL 源。下面以主控端 Master 为例进行介绍。
[root@master ~]# yum install -y epel-release
主控端(也就是 Master)上安装 SaltStack 软件。[root@master ~]# yum install -y salt-master
被控端(也就是两台 Minion)上安装 SaltStack 软件。
[root@web1 ~]# yum install -y salt-minion
[root@web2 ~]# yum install -y salt-minion
(3)配置主控端配置文件/etc/salt/master,默认的 master 文件全部是注释的。首先需
要修改主控端配置文件中的监听地址。需要注意的是为了安全,监听的地址一定要写私网地
址。
interface: 192.168.9.233
设置允许被控端自动认证,只要被控端设置完主控端的 IP 地址后启动服务,主控端就
会允许被控端自动认证,以避免以后每次运行 salt-key 来确认证书信任。
auto_accept: True
修改 SaltStack 文件根目录位置,去掉注释。
file_roots:
base:
- /srv/salt/
修改组分类。
nodegroups:
web01group: 'web01.saltstack.com'
web02group: 'web02.saltstack.com'
开启 pillar 功能。
pillar_opts: True
设置 pillar 的主目录,去掉注释。
pillar_roots:
base:
- /srv/pillar
主控端主要修改内容包括:
[root@master ~]# cat /etc/salt/master | grep -v "^$" | grep -v "^#"
interface: 192.168.9.233
auto_accept: True
file_roots:
base:
- /srv/salt
pillar_roots:
base:
- /srv/pillar
pillar_opts: True
nodegroups:
web01group: 'web01.saltstack.com'
web02group: 'web02.saltstack.com'
主控端做完上述操作后启动 salt-master 服务。
[root@master ~]# systemctl start salt-master
[root@master ~]# systemctl enable salt-master
Created
symlink
from
/etc/systemd/system/multi-user.target.wants/salt-master.service
to
/usr/lib/systemd/system/salt-master.service.
启动完后监听 TCP 4505、TCP 4506 端口。生产环境中,如果启用防火墙,建议主控
端开放这两个端口。
创建 salt 文件根目录及 pillar 目录。
[root@master ~]# mkdir /srv/salt
[root@master ~]# mkdir /srv/pillar
(4)配置两台被控端的配置文件/etc/salt/minion。
注意:默认的 minion 文件也是全部注释的。
master: 192.168.9.233
//设置主控端 IP
id: web01.saltstack.com
//设置被控主机名,另一台是 web02.saltstack.com
分别启动两台被控端服务。
[root@web01 ~]# systemctl start salt-minion
[root@web01 ~]# systemctl enable salt-minion
Created
symlink
from
/etc/systemd/system/multi-user.target.wants/salt-minion.service
to
/usr/lib/systemd/system/salt-minion.service.
[root@web02 ~]# systemctl start salt-minion
[root@web02 ~]# systemctl enable salt-minion
Created
symlink
from
/etc/systemd/system/multi-user.target.wants/salt-minion.service
to
/usr/lib/systemd/system/salt-minion.service.
在主控端上,简单测试主控端和被控端的通信状态。如果返回都是 True,说明正常。
注意:
这里的 ping 和我们平时用的 ping 命令不同。它只是 test 类下面的一个方法,是验证主
控端和被控端的通信状态。
*表示所有通过认证的被控端。还可以支持其它很多正则表达式的匹配。
[root@master ~]# salt '*' test.ping
web01.saltstack.com:
True
web02.saltstack.com:
True
2. SaltStack 批量部署 Nginx
下面利用 SaltStack 的三个重要组件 grains、pillar 与 state 完成 Nginx 的安装配置工作。grains 和 pillar 的作用都是采集被控端数据的。其中 grains 的特性是每次启动汇报;而 pillar
是随时可变的,只要在 master 端修改了,一般都会立刻生效的。所以,grains 更适合做一
些静态的属性值的采集,例如设备的角色、磁盘个数等诸如非常固定的属性。如果想定义的
属性值是经常变化的,就采用 pillar。如果想定义的属性值是很固定、不易变的,就采用 grains。
在配置之前,需要分析 Nginx 的主配置文件,要根据当前 CPU 个数设置一些值、设置
一些打开文件句柄数等等。
定义 grains 数据的方法有两种:一种为在被控主机定制配置文件,另外一种是通过主
控端扩展模块 API 实现,区别是模块更灵活。下面用自定义的方式进行。
通过下面的命令可以查看被控机 web01 主机的 grains 所有值。
[root@master ~]# salt 'web01.saltstack.com' grains.items
web01.saltstack.com:
----------
SSDs:
biosreleasedate:
07/02/2015
biosversion:
6.00
cpu_flags:
- fpu
- vme
- de
- pse
- tsc
- msr
- pae
- mce
- cx8
- apic
- sep
- mtrr
- pge
- mca
//省略内容
grains 是 SaltStack 重要的组件之一,它可以收集被控主机的基本信息,如 CPU、内
核、操作系统、虚拟化等静态数据。但是有些数据采集不到,例如默认打开的文件句柄数,
需要通过自定义的 Python 脚本获取。在服务端利用这些信息对不同被控主机进行个性化配
置。
首先,创建 grains 目录,需要将目录下的定制文件同步到被控机上运行;然后,能正
常获取被控机打开文件句柄数。
[root@master ~]# mkdir /srv/salt/_grains
[root@master ~]# vim /srv/salt/_grains/nginx_config.py
#!/usr/bin/python
import os,sys,commands
def NginxGrains():
'''
return Nginx config grains value
'''
grains = {}
max_open_file=65535
try:
getulimit = commands.getstatusoutput('source /etc/profile;ulimit -n')
except Exception,e:
pass
if getulimit[0]==0:
max_open_file = int(getulimit[1])
grains['max_open_file'] = max_open_file
return grains
上述脚本的含义就是让被控机获取它当前打开文件句柄数。
在 同 步 到 被 控 端 之 前 , 执 行 如 下 命 令 , 确 认 在 主 控 端 是 否 能 获 取 被 控 端 的
max_open_file 值。
[root@master ~]# salt '*' grains.item max_open_file
web02.saltstack.com:
----------
max_open_file:
web01.saltstack.com:
----------
max_open_file:
从命令执行结果中得知:不能获取到 max_open_file 的值,需要同步 grains 模块,在
主控端运行如下命令。
[root@master ~]# salt '*' saltutil.sync_all
web02.saltstack.com:
----------
beacons:
grains:
- grains.nginx_config
modules:
output:
renderers:
returners:
sdb:
states:
utils:
web01.saltstack.com:
----------
beacons:
grains:
- grains.nginx_config
modules:
output:
renderers:
returners:
sdb:
states:
utils:
被控端文件存放在/var/cache/salt 目录下。
[root@web01 ~]# find /var/cache/salt/
/var/cache/salt/
/var/cache/salt/minion
/var/cache/salt/minion/extmods
/var/cache/salt/minion/extmods/grains
/var/cache/salt/minion/extmods/grains/nginx_config.py
/var/cache/salt/minion/extmods/grains/nginx_config.pyc
/var/cache/salt/minion/proc
/var/cache/salt/minion/module_refresh
/var/cache/salt/minion/files
/var/cache/salt/minion/files/base
/var/cache/salt/minion/files/base/_grains
/var/cache/salt/minion/files/base/_grains/nginx_config.py
再次获取 max_open_file 的值。
[root@master ~]# salt '*' grains.item max_open_file
web02.saltstack.com:
----------
max_open_file:
1024
web01.saltstack.com:
----------
max_open_file:
1024
配置 pilllar:在主控端上创建入口文件 top.sls,入口文件的作用是定义 pillar 的数据覆
盖被控主机的有效域范围。具体内容如下:
[root@master ~]# vim /srv/pillar/top.sls
base:
web01group:
//组名
- match: nodegroup
- web01server
//设置包括 web01server.sls
web02group:
//组名
- match: nodegroup
- web02server
//设置包括 web02server.sls
“web01group”和”web02group”是/etc/salt/master 中定义的不同的组,对每一个组编写
一个对应的文件指定配置,这里使用的是“web01server”和”web02server”,再分别定义不同
组主机的 Nginx 的根目录,如下所示:
[root@master ~]# vim /srv/pillar/web01server.sls
nginx:
root: /data
[root@master ~]# vim /srv/pillar/web02server.sls
nginx:
root: /www
使用以下命令查看 pillar 配置的情况。
[root@master ~]# salt '*' pillar.data nginx
web01.saltstack.com:
----------
nginx:
----------
root:
/data
web02.saltstack.com:
----------
nginx:
----------
root:
/www
在执行结果中可以很明显的看出,被控主机的 Nginx 的根目录被配置成功。
定义 state 的入口 top.sls 文件,注意和 pillar 的入口文件名字一样,内容如下。
[root@master ~]# vim /srv/salt/top.sls
base:
'*':
- nginx
其次,定义被控机执行的状态,安装 Nginx 软件、配置、启动。
[root@master ~]# vim /srv/salt/nginx.sls
nginx:
pkg:
//1.包管理
- installed
//安装包
file.managed:
//
2.文件管理
- source: salt://nginx/nginx.conf
//配置文件在服务器路径
- name: /etc/nginx/nginx.conf
//配置文件在被控主机的路径
- user: root
//nginx 用户名
- group: root
//用户所在组
- mode: 644
//权限
- template: jinja
//配置文件使用 jinja 模板
service.running:
//3.运行服务管理
- enable: True
//开机自动运行
- reload: True
//可以重载
- watch:
- file: /etc/nginx/nginx.conf
- pkg: nginx
其中:
salt://nginx/nginx.conf 为配置模板文件位置;
enable:True 表示检查服务是否在开机自启动服务队列中,如果不在则加上,等价
于 chkconfig nginx on 命令;
reload:True 表示服务支持 reload 操作,不加则会默认执行 restart 操作;
watch 即用于检测/etc/nginx/nginx.conf 是否发生变化,又用于确保 Nginx 已安装
成功。
上面的配置文件实际上与在一台服务器直接安装 Nginx 的过程是相同的,首先是安装
包,然后是对配置文件进行修改,最后是启动服务。
使用 jinja 模板定义 Nginx 配置文件 nginx.conf,首先创建一个 nginx 目录,因为上面定
义了 Nginx 配置文件的源路径。
[root@master ~]# mkdir /srv/salt/nginx
然后在该路径下创建 Nginx 配置文件,nginx.conf 配置文件可以根据自己的需求进行编
写。
[root@master ~]# vim /srv/salt/nginx/nginx.conf
user nginx;
worker_processes {{grains['num_cpus']}};
{% if grains['num_cpus'] ==1 %}
worker_cpu_affinity 10;
{% elif grains['num_cpus'] ==2 %}
worker_cpu_affinity 01 10;
{% elif grains['num_cpus'] == 4 %}
worker_cpu_affinity 0001 0010 0100 1000;
{% elif grains['num_cpus'] == 8 %}
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000
10000000;
{% else %}
worker_cpu_affinity 0001 0010 0100 1000;
{% endif %}
worker_rlimit_nofile {{ grains['max_open_file'] }};
error_log /var/log/nginx_error.log;
pid
/var/run/nginx.pid;
events
{
worker_connections {{ grains['max_open_file'] }};
}
http
{
include
/etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 60;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"' ;
server{
listen 80 default_server;
server_name _;
location / {
root {{ pillar['nginx']['root'] }};
index index.html index.htm;
}
error_page 404
/404.html;
location = /404.html {
root /usr/share/nginx/html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
现在就可以在主控端执行刷新 state 配置,让两台被控端执行安装 Nginx 并配置。
[root@master ~]# salt '*' state.highstate
web01.saltstack.com:----------
ID: nginx
Function: pkg.installed
Result: True
Comment: The following packages were installed/updated: nginx
Started: 12:50:33.539350
Duration: 33590.857 ms
Changes:
//省略部分......
----------
ID: nginx
Function: file.managed
Name: /etc/nginx/nginx.conf
Result: True
Comment: File /etc/nginx/nginx.conf updated
Started: 12:51:07.133783
Duration: 42.468 ms
Changes:
//省略部分......
----------
ID: nginx
Function: service.running
Result: True
Comment: Service nginx has been enabled, and is running
Started: 12:51:07.205801
Duration: 992.623 ms
Changes:
----------
nginx:
True
Summary
------------
Succeeded: 3 (changed=3)
Failed:
0
------------
Total states run:
3
通过执行结果,看到了三个 ID,相当于三个任务,第一个安装,第二个配置,第三个
启动。而且显示三个都成功了,失败数是零个。如果不放心,也可以看看被控端 Nginx 是
否启动。
[root@web01 ~]# ps -ef | grep nginx
root
2737
1 0 14:35 ?
00:00:00 nginx: master process /usr/sbin/nginx
nginx
2738 2737 0 14:35 ?
00:00:00 nginx: worker process
root
2770 2365 0 14:35 pts/0
00:00:00 grep --color=auto nginx
查看 web01.saltstack.com 节点的 Nginx 主配置文件 nginx.conf。
[root@web01 ~]# more /etc/nginx/nginx.conf
user nginx;
worker_processes 1;
//根据 cpu 个数配置
worker_cpu_affinity 10;
worker_rlimit_nofile 1024;
//根据定义的 max_open_file 定义
error_log /var/log/nginx_error.log;
pid
/var/run/nginx.pid;
events
{
worker_connections 1024;
//根据定义的 max_open_file 定义
}
......
//省略内容
location / {
root /data;
//定义的 Nginx 目录
index index.html index.htm;
}
//省略内容
查看 web02.saltstack.com 节点的 Nginx 主配置文件 nginx.conf,上面注释的内容有相
应的变化。这样,基本完成了通过 SaltStack 批量部署 Nginx 并配置。