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 环境,可以在成千上万台服务器上批量执行命令,对于不同的业务进行集中管理、分发文件、采集数据、软件包管理等。有利于运维人员提高工作效率、规范 业务配置和操作。
2、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 端请求注册连接。
3、SaltStack安装
3.1基础环境
操作系统 配置 主机名 IP Nginx 根目录
CentOS7.9 1C2G master.saltstack.com 10.128.0.10
CentOS7.9 1C2G web01.saltstack.com 10.128.0.11 /data
CentOS7.9 2C2G web02.saltstack.com 10.128.0.12 /www
#关闭防火墙
systemctl stop firewalld systemctl disable firewalld
#关闭内核安全机制
sed -i "s/^SELINUX=.*/SELINUX=disabled/g" /etc/selinux/config
#时间同步
yum -y install chrony
systemctl start chronyd
systemctl enable chronyd
chronyc sources -v
#设置主机名
hostnamectl set-hostname master.saltstack.com
hostnamectl set-hostname web01.saltstack.com
hostnamectl set-hostname web02.saltstack.com
#添加hosts
cat >> /etc/hosts << EOF
10.128.0.10 master.saltstack.com
10.128.0.11 web01.saltstack.com
10.128.0.12 web02.saltstack.com
EOF
#安装SaltStack源
sudo rpm --import https://repo.saltproject.io/py3/redhat/7/x86_64/latest/SALTSTACK-GPG-KEY.pub
curl -fsSL https://repo.saltproject.io/py3/redhat/7/x86_64/latest.repo | sudo tee /etc/yum.repos.d/salt.repo
3.2安装 SaltStack 服务端
-
主控端(也就是 Master)上安装 SaltStack 软件
# 备份配置文件
cp /etc/salt/master{,_bak}
# 默认的 master 文件全部是注释的。首先需 要修改主控端配置文件中的监听地址。需要注意的是为了安全,监听的地址一定要写私网地 址
interface: 10.128.0.10
# 设置允许被控端自动认证,只要被控端设置完主控端的 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@192 ~]# cat /etc/salt/master
interface: 10.128.0.10
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'
###############################################################
-
配置主控端配置文件/etc/salt/master
systemctl start salt-master
systemctl enable salt-master
-
创建 salt 文件根目录及 pillar 目录
mkdir /srv/salt
mkdir /srv/pillar
3.3安装SaltStack 客户端
-
被控端(也就是两台 Minion)上安装 SaltStack 软件
yum install -y salt-minion
-
配置两台被控端的配置文件/etc/salt/minion
# 备份配置文件
cp /etc/salt/minion{,_bak}
# 注意:默认的 minion 文件也是全部注释的。
master: 10.128.0.10 //设置主控端 IP
id: web01.saltstack.com //设置被控主机名,另一台是 web02.saltstack.com
-
分别启动两台被控端服务
systemctl start salt-minion
systemctl enable salt-minion
-
在主控端上,简单测试主控端和被控端的通信状态。如果返回都是 True,说明正常
# 在master节点执行
salt '*' test.ping
-
删除key
# 如果出问题的话可以先删除key,然后重启被删除端的salt-minion
salt-key -d web01.saltstack.com
systemctl restart salt-minion
-
同步配置
# server端执行此命令可以同步配置
salt '*' state.highstate
-
常用命令行
# 查看所有客户端up和down状态
salt-run manage.status
# 只显示up状态的客户端
salt-run manage.up
# 只显示down状态的客户端
salt-run manage.down
# 查看所有主机的磁盘信息,cmd.run 执行单个命令
salt '*' cmd.run 'df -h'
# 把本地脚本拷贝到远程主机上执行
salt '*' cmd.script salt://test.sh
# 把本地脚本拷贝到远程主机上执行,带参数
salt '*' cmd.script salt://scripts/runme.sh 'arg1 arg2 arg3'
3.4批量分发文件
[root@localhost ~]$ cat /srv/salt/top.sls # 先定义入口配置文件
base:
'*':
- send_file
#############################################################################
[root@localhost ~]$ cat /srv/salt/send_file.sls # 定义要加载的sls文件
send_file: # send_file 只是一个标识,方便我们查看这个文件的作用
file.managed: # file.managed函数用来管理文件
- name: /tmp/1.txt # 指定分发到目标 minion 的哪个路径
- source: salt://1.txt # 指定源文件路径,salt://1.txt 相当于 /srv/salt/1.txt
- user: root # 指定文件的属主
- group: root # 指定文件的属组
- mode: 600 # 指定文件的权限
################################################################################
[root@localhost ~]$ touch /srv/salt/1.txt # 创建源文件
[root@localhost ~]$ salt '*' state.highstate # 通过state模块,会自动去找/srv/salt/top.sls文件,然后top.sls会去加载send_file.sls文件,最终实现文件分发
3.5使用 YUM 安装 Apache 服务
cat > /srv/salt/top.sls << EOF
base:
'*':
- http
EOF
cat > /srv/salt/http.sls << EOF
httpd:
pkg.installed:
- pkgs:
- httpd
- php
- httpd-tools
service.running:
- name: httpd
- enable: true
- reload: true
group.present:
- gid: 87
user.present:
- name: httpd
- uid: 87
- gid: 87
- home: /var/www/html
- shell: /sbin/nologin
file.managed:
- name: /etc/httpd/conf/httpd.conf
- source: salt://httpd/httpd.conf
- user: root
- group: root
- mode: 644
EOF
3.6SaltStack 批量部署 Nginx,master节点操作
-
首先,创建 grains 目录,需要将目录下的定制文件同步到被控机上运行;然后,能正 常获取被控机打开文件句柄数
mkdir /srv/salt/_grains
### 注意这里有两个版本的python程序,这里使用python3版本的
vi /srv/salt/_grains/nginx_config.py
###########################################################################################
#!/usr/bin/python
# 这个适用于python2版本
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
############################################################################################
###########################################################################################
#!/usr/bin/python
# 这个适用于python3版本
import os,sys,subprocess
def NginxGrains():
'''
return Nginx config grains value
'''
grains = {}
max_open_file=65535
try:
getulimit = subprocess.getstatusoutput('source /etc/profile;ulimit -n')
except:
pass
if getulimit[0]==0:
max_open_file = int(getulimit[1])
grains['max_open_file'] = max_open_file
return grains
############################################################################################
# 同步 grains 模块
salt '*' saltutil.sync_all
# 再次获取 max_open_file 的值
salt '*' grains.item max_open_file
-
配置 pilllar
# 在主控端上创建入口文件 top.sls,入口文件的作用是定义 pillar 的数据覆 盖被控主机的有效域范围
vi /srv/pillar/top.sls
########################################################################################
base:
web01group: //组名
- match: nodegroup
- web01server //设置包括 web01server.sls
web02group: //组名
- match: nodegroup
- web02server //设置包括 web02server.sls
########################################################################################
cat /srv/pillar/top.sls
base:
web01group:
- match: nodegroup
- web01server
web02group:
- match: nodegroup
- web02server
########################################################################################
# “web01group”和”web02group”是/etc/salt/master 中定义的不同的组,对每一个组编写 一个对应的文件指定配置,这里使用的是“web01server”和”web02server”,再分别定义不同 组主机的 Nginx 的根目录
vi /srv/pillar/web01server.sls
nginx:
root: /data
vi /srv/pillar/web02server.sls
nginx:
root: /www
# 使用以下命令查看 pillar 配置的情况
salt '*' pillar.items
# 定义 state 的入口 top.sls 文件,注意和 pillar 的入口文件名字一样
vi /srv/salt/top.sls
#################################
base:
'*':
- nginx
##################################
# 定义被控机执行的状态,安装 Nginx 软件、配置、启动
vi /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
#############################################################
[root@master salt]# cat nginx.sls
nginx:
pkg:
- installed
file.managed:
- source: salt://nginx/nginx.conf
- name: /etc/nginx/nginx.conf
- user: root
- group: root
- mode: 644
- template: jinja
service.running:
- 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 已安装 成功。
-
使用 jinja 模板定义 Nginx 配置文件 nginx.conf,首先创建一个 nginx 目录,因为上面定 义了 Nginx 配置文件的源路径
mkdir /srv/salt/nginx
vi /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 并配置
salt '*' state.highstate
#2 3
yum -y install epel-release