自动化运维工具-saltstack

Posted 琴声浮或沉__听懂只一人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动化运维工具-saltstack相关的知识,希望对你有一定的参考价值。

自动化运维工具-saltstack

saltstack采用C/S结构的方式来进行配置管理,运行速度快、部署轻松,几分钟内便可运行起来,而且服务器之间能够做到秒级通讯,容易批量管理上万台服务器,显著降低人力与运维成本
话不多说,开始进入正题!

初识saltstack

  • 一种基于C/S架构的服务器基础架构集中化管理平台,管理端称为master,客户端称为minion
  • 具备配置管理、远程执行、监控等功能
  • 基于python语言开发
  • 结合轻量级的消息队列软件ZeroMQ与Python第三方模块(Pyzmq、PyCrypto、Pyjinjia2、 python-msgpack 和 PyYAML 等)构建

1.特征

1. 部署简单方便
2. 主从集中化管理
3. 配置简单、功能强大、扩展性强
4. 主控端(master)和被控端(minion)基于证书认证,安全可靠
5. 支持API自定义模块,可通过Python扩展

2.运行模式

  • local:本地单点(不建议这么做,不然就没意义了)
  • Master/Minion:通过server/client的方式进行管理,效率很高
  • Salt SSH:通过SSH方式进行管理(类似于ansible),效率相对来说比较低

对比上面的运行模式,我们可以得出saltstack一般都是采用Master/Minion来进行自动化运维管理的,下面便是Master/Minion的架构图

minion:客户端安装组件,配置好之后会主动去连接master,从master端得到资源状态信息,并同步资源管理信息
master:服务端安装组件,运行在主服务器上,负责salt命令运行和资源的管理

3.如何实现批量操作?

  • master与minion之间通过Zero进行消息传递,使用ZeroMQ进行消息传递,以及Zero-MQ的发布订阅模式,连接方式包括tcp、ipc
  • master将要执行的操作或命令发送给minion,minion从消息总线上收到要进行的操作或要处理的命令,之后交给minion_handle_aes处理
  • 之后minion_handle_aes发起一个本地线程去调用cmdmod去执行操作或命令,线程执行完毕后调用minion.return_pub方法,将执行结果通过消息总线返回给master
  • master接收到客户端返回的结果,调用master._handle_aes方法,将结果写进文件中
  • salt.client.LocalClient.cmd_cli通过轮询获取执行结果,将结果输出到终端

4.与ansible异同之处

saltstack与ansible都作为自动化运维工具,能够对目标主机实现配置管理批量操作等功能,满足企业的自动化运维管理,那么他们之间有什么异同之处呢?

相同点:

\\1. 都是基于python开发,可以部署到不同的系统环境中
\\2. 具有较好的二次开发性,便于实现个性定制
\\3. ansible的playbook和saltstack的state都是遵循yaml格式
\\4. 执行返回结果都是json格式,容易理解

不同点:

从响应速度来看:

saltstack的master与minion之间是通过ZeroMQ来传输数据,而ansible是通过标准SSH进行数据传输,saltstack的响应速度要比ansible的要快

从安全性来讲:

ansible与saltstack都需要和远程主机进行连接,所以最大的问题就是MITM攻击(通过伪装成master主机和远程主机进行通信,从而进行攻击)
saltstack使用ZeroMQ进行数据传输,ZeroMQ本身数据传输不支持加密,saltstack可以通过使用AES数据加密方法来对数据进行加密传输,但minion以守护进程的方式运行在远程主机,容易暴露
ansible则使用标准SSH进行连接,不需要在远程主机上启动守护进程,而且标准SSH数据传输就是加密传输,安全方面ansible要更胜一

从成本来讲:

saltstack需要在master和minion主机启动守护进程,需要检测守护进程的运行状态,增加了运维成本
ansible和远程主机之间都是通过标准SSH进行连接的,远程主机只需要运行SSH进程就可以进行操作,而SSH是机房主机中都会安装和启动的进程,运维成本低于saltstack,使用起来要比saltstack简单的多

从语法来讲:

saltstack的state和ansible的playbook都遵循YAML格式,但是Ansible的Playbook语法要比SaltStack的State语法具有更好的可读性

master&minion

前面我们说过,在saltstack中有两种角色——master(主控端)和minion(被控端),master来管理minion
下面我们来看下master和minion之间是怎么通信的

1.认证

2.连接

master启动后默认监听4505和4506两个端口
4505端口为saltstack的消息发布系统端口;4506端口为 saltstack minion与master 通信的端口
查看4505的端口状态我们会发现所有的minion在4505端口持续保持在ESTABLISHED状态

安装&部署

我们先来看一下本次实验的架构图

192.168.244.141作为主控端master

192.168.244.128/129都是被控端minion

我们先分别在三台服务器上安装依赖包

#安装saltstack存储库和密钥
rpm --import https://repo.saltproject.io/py3/redhat/7/x86_64/3002/SALTSTACK-GPG-KEY.pub

#配置镜像源
touch /etc/yum.repos.d/salt.repo
curl -fsSL https://repo.saltproject.io/py3/redhat/7/x86_64/3002.repo | tee /etc/yum.repos.d/salt.repo

#清缓存
yum clean expire-cache

然后我们根据不同的角色来安装不同组件

#master
[root@master ~]#  yum install salt-master -y

#minion
[root@minion1 ~]# yum install salt-minion -y
[root@minion2 ~]# yum install salt-minion -y

安装完毕后开启并设置自启动

[root@master ~]#systemctl enable salt-master && systemctl start salt-master

[root@minion1 ~]#systemctl enable salt-minion && systemctl start salt-minion
[root@minion2 ~]#systemctl enable salt-minion && systemctl start salt-minion

1.配置

修改master配置文件

master配置文件路径:vim /etc/salt/master

[root@master ~]# vim /etc/salt/master
[root@master ~]# grep -Ev "^$|#" /etc/salt/master
file_root:
  base:
    - /home/salt
pillar_roots:
  base:
    - /home/salt/pillar
order_masters: True
auto_accept: True


##file_roots:主目录
##pillar_roots:pillar组件主目录
##order_masters:允许开启多层master
##auto_accept:自动认证
[root@master ~]#systemctl restart salt-master

修改minion配置文件

minion配置文件路径:vim /etc/salt/minion

我只展示操作minion1的过程,minion2同理的

[root@minion1 ~]# vim /etc/salt/minion
[root@minion1 ~]# grep -Ev "^$|#" /etc/salt/minion
master: 192.168.244.141
id: 192.168.244.129
user: root

#重启服务
[root@minion1 ~]# systemctl restart salt-minion
# minion的识别ID,可以是IP,域名,或是可以通过DNS解析的字符串
id: 192.168.244.128

# salt运行的用户权限
user: root

# master的识别ID,可以是IP,域名,或是可以通过DNS解析的字符串
master : 192.168.244.141

# master通讯端口
master_port: 4506

# 备份模式,minion是本地备份,当进行文件管理时的文件备份模式
backup_mode: minion

# 执行salt-call时候的输出方式
output: nested

# minion等待master接受认证的时间
acceptance_wait_time: 10

# 失败重连次数,0表示无限次,非零会不断尝试到设置值后停止尝试
acceptance_wait_time_max: 0

# 重新认证延迟时间,可以避免因为master的key改变导致minion需要重新认证的syn风暴
random_reauth_delay: 60

# 日志文件位置
log_file: /var/logs/salt_minion.log

# 文件路径基本位置
file_roots:
base:
- /etc/salt/minion/file

# pillar基本位置
pillar_roots:
base:
- /data/salt/minion/pillar

2.认证并连接

minion在第一次启动时,会在/etc/salt/pki/minion/下自动生成minion.pem(private key)和 minion.pub(public key),然后将minion.pub发送给master

我们在master端来进行key认证,使用salt-key命令

[root@master ~]# salt-key 
Accepted Keys: #可以看到master已经检测到minion,且已认证key
192.168.244.128
192.168.244.129
Denied Keys:
Unaccepted Keys:
Rejected Keys:

#如果没有认证,手动输入认证一下
[root@master ~]# salt-key -a id

认证成功之后我们来验证一下

[root@master ~]# salt '192.168.244.128' test.ping
192.168.244.128:
    True  #返回结果表示成功
[root@master ~]# salt '192.168.244.129' test.ping
192.168.244.129:
    True

总结

首先介绍了saltstack是什么,以及它与ansible之间的相似之处和不同之处

还介绍了saltstack中master和minion之间是怎么实现通信的

最后还通过在三台虚拟机上部署saltstack组件,让大家印象更深刻

基础命令

用来执行salt命令,通常在master端运行。

salt [option] '<target>' <function> [arguments]
例如:
salt 'minion1' cmd.run '192.168.244.128'
'minion1' 是指在那些minion上操作;
cmd是一个执行模块;test是模块下的函数;
'192.168.244.128'是test函数的参数,有的函数需要参数,有的不需要
#查看帮助文档
salt -d
salt '*' sys.doc
salt 'x' sys.doc test

#查看service相关模块命令
salt -d | grep service

#获取主机所有服务
salt '*' service.get_all

#重载sshd服务
salt '*' service.reload sshd

#显示软件包版本列表
salt '*' pkg.list_pkgs

#显示软件包版本信息
salt '*' pkg.version python

#安装软件包
salt '*' pkg.install httpd

#查看mysql服务状态
salt 'node1.com' service.status mysql

#启动mysql服务
salt 'node1.com' service.start mysql

#与上面一样查看服务
salt 'node1.com' cmd.run 'service mysql status'

#模块列表
salt '*' sys.list_modules

#把salt-master端相应的文件,分发文件到minion端
salt '*' cp.get_file salt://ceshi/b /tmp/test

#把salt-master端相应的目录,分发文件到minion端
salt '*' cp.get_dir salt://zabbix /tmp

#把salt-master端对应文件拷贝到minion端相应目录下
salt '*' file.copy /tmp/zabbix.sls /tmp/sls

#远程命令执行测试
salt '*' cmd.run 'uptime'

#查看grains分类
salt '*' grains.ls

#查看grains所有信息
salt '*' grains.items

#查看grains某个信息
salt '*' grains.item osrelease
  • salt-run

saltstack提供了Runners的功能,使用salt-run来运行,可以非常方便地在Master端执行相关的模块,获取minion端状态。salt-run下的很多模块我们用不到,多数我们可以通过salt命令就已经完成工作需要

常用的runner有manage

#查看存活的minion
salt-run manage.up

#查看死掉的minion
salt-run manage.down

#查看down掉的minion,并将其删除
salt-run manage.down removekeys=True

#查看minion的相关状态
salt-run manage.status

#查看slat的所有master和minion的版本信息
salt-run manage.versions
  • salt-key

用于密钥管理,来决定master与minion之间的通信,通常在master端执行

  • salt-call

在minion执行,minion执行自己可以执行的模块,而不是通过master下发job

salt-call [options] <function> [arguments]
##自己执行test.ping命令
salt-call test.ping

##自己执行cmd.run函数
salt-call cmd.run 'ifconfig'
  • salt-cp

通过salt-cp可以将master上的文件下发到minion上

salt-cp [options] '<target>' SOURCE DEST

salt-cp '*' testfile.html /tmp

#把master上的index.html分发到test minion上
salt-cp 'test*' index.html /tmp/a.html

#把master上的hosts文件分发到所有主机
salt-cp '*' /etc/hosts /etc/hosts

分组管理

在生产环境中我们可能要管理上百台服务器,有些服务器用来做数据库,有些服务器用来实现web服务,有些做负载均衡…

我们如果想对web服务器做批量操作的话,而web服务器又有几十台,我们是不可能将这几十台服务器的ip地址全都敲进命令里的,这样会大大降低运维效率

我们可以对这些服务器做分组,用来做负载均衡的分成一组、做web服务的分成一组,那么我们操作时只需要指定组名就可以了

在saltstack里我们一般用nodegroups来实现分组管理

Nodegroups

我们通过创建nodegroups配置文件来实现分组管理,配置文件的路径为

/etc/salt/master.d/nodegroups.conf

对目标服务器分组有以下七种方式,这七种方式的标示符分别为

G -- 针对 Grains 做单个匹配,例如:G@os:Ubuntu

E -- 针对 minion 针对正则表达式做匹配,例如:E@web\\d+.(dev|qa|prod).loc

P -- 针对 Grains 做正则表达式匹配,例如:P@os:(RedHat|Fedora|CentOS)

L -- 针对 minion 做列表匹配,例如:L@minion1.example.com,minion3.domain.com orbl*.domain.com 
使用 L 列表的方式,必须把 minion 列出来,或者是列出几台后,在后面接 or 或者 and 表达式, or 或者 and 后面接的表达式后面可以使用正则表达式。

I -- 针对 Pillar 做单个匹配,例如:I@pdata:foobar

S -- 针对子网或是 IP 做匹配,例如:S@192.168.1.0/24 or S@192.168.1.100

R -- 针对客户端范围做匹配,例如:R@%foo.bar

N -- 针对 nodegroup 做匹配

如果说我有多个分组,可以按照下列格式进行配置

[root@master ~]#vim /etc/salt/master.d/nodegroups.conf
nodegroups:
group1: 'L@192.168.244.128,192.168.244.130'
group2: 'L@192.168.244.100'
group3: 'S@192.168.64.0/24'
group4: 'E@192.168.64.12[2-3]'

[root@master ~]#salt -N group1 test.ping

案例:

[root@master ~]# vim  /etc/salt/master.d/nodegroup.conf
nodegroups:
  web: 'L@192.168.244.128,192.168.244.129'
 
 [root@master ~]# salt -N web test.ping
192.168.244.129:
    True
192.168.244.128:
    True

或者通过E匹配模式来做分组管理

[root@master ~]# vim  /etc/salt/master.d/nodegroup.conf
nodegroups:
  group1: 'E@192.168.244.12[8-9]'

[root@master ~]# salt -N group1 test.ping
192.168.244.129:
    True
192.168.244.128:
    True

SLS

SLS(Salt State文件)是Salt State系统的核心。SLS描述了系统的目标状态,SLS文件由格式简单的数据构成,经常被称作配置管理

SLS文件以“.sls”后缀结尾,但在调用时不需要写后缀

1.YAML

SLS配置文件采用YAML的格式编写

下面是YAML格式的一些要求

  1. .在YAML中不要使用Tab键来作为缩进
  2. .YAML推荐缩进为2个空格,’ : ’ , ’ - ’后面缩进1个空格再写
  3. 数字会解析成数字。如mode: 0644会解析成mode: 644,可用单引号括起来防止mode: ’0644ʹ此情况
  4. .YAML不允许双简写
  5. 下划线将会被删除。有出现下划线要用 " " 括起来

基本格式例子

http-install:
  pkg:
    - installed

#第一行被称为标签定义,在这里被定义为安装包的名
#第二行被称为状态定义,在这里定义使用module
#第三行被称为函数定义,在这里定义使用调用函数
[root@master ~]#vim /srv/salt/apache.sls
http-install: # ID声明 也是软件包名称 自定义
  pkg.installed: # 模块以及函数声明
    - pkgs:      
      - httpd   # 参数声明

指定主机执行:
[root@master ~]#salt server5 state.sls apache 文件后缀不用添加

SLS配置文件在master上,默认路径是在/srv/salt/下面,使用子目录来管理是个很好的选择,init.sls在一个子目录里面表示引导文件,也就表示子目录本身,所 以 apache/init.sls 就是表示 apache

例如文件树如下所示:

[root@master ~]#tree /srv/salt/apache
| --install.sls
|
|--_modules
#第一种写法
[root@master ~]# salt “*” state.sls apache/install

#第二种写法
[root@master ~]# mv install.sls init.sls
[root@master ~]# salt “*” state.sls apache

#同时存在apache/apache.sls 和 apache/init.sls,则 apache/init.sls 被忽略,apache.sls将被用来表
示 apache
/srv/salt/apache
| --install.sls
|
| --apache.sls
salt “*” state.sls apache #优先读取apache.sls此文件

2.常用模块

用户管理

  • 创建用户
useradd:
  user.present:
    -name: admin
    - shell: /bin/bash
    - home: /home/admin
    - uid: 888
  • 删除用户
userdel:
  user.absent:
    - name: admin
    - purge: True   #purge类似userdel -r
    - force: True   #force为用户在线也强制删除

文件管理

  • 上传文件
fileup:
  file.managed:
    - source: salt://nginx/nginx-xxx.xxx.tar.gz
    - user: root
    - group:root
    - mode: 755
    - backup:minion
    - template:jinja
  • 追加文件
fileadd:
  file.append:
    - text:
      - "exportJAVA_HOME=/usr/local/jdk1.6.0_13"
      - "exportPATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH"
      - "exportCLASSPATH=$JAVA_HOME/lib/:$JAVA_HOME/jre/lib:$CLASSPATH"

目录管理

  • 目录覆盖
dircover:
  file.recurse:
    -source: salt://nginx/conf
    -user: root
    -group: root
    -file_mode: 644
    -dir_mode: 755
  • 目录创建
diradd:
  file.directory:
    - name: /tmp/dir
    - user: web
    - group: web
    - file_mode:644
    - dir_mode:755
    - makedirs:True
    - include_empty: True
    - template:jinja
    - backup:minion

包管理

  • yum安装
installpkgs:
  pkg.installed:
    - pkgs:
      - httpd
      - telnet

3.逻辑关系

  • 继承(include)
include:
  - web.apache
  • 依赖(require)
- require:
  - pkg: nginx-install
  • 监控(watch)

在某个state变化时运行此模块,文中的配置,相关文件变化后,立即执行相应操作

- watch:
  - file: /etc/nginx/nginx.conf
  - file: /etc/nginx/fastcgi.conf
  - pkg: nginx
  • 顺序

优先级比require和watch低,有order指定的state比没有order指定的优先级高,假如一个state模块内 安装多个服务,或者其他依赖关系,可以使用。如果想让某个state最后执行,可以使用last

nginx:
  pkg.installed:
    - order:1

4.SLS文件执行顺序

  • top.sls

top.sls 是配置管理的入口文件,一切都是从这里开始,在master主机上默认路径为/srv/salt/目录

top.sls 默认从 base 标签开始解析执行,下一级是操作的目标,可以通过正则,grain模块,或分组名,来进行匹配,再下一级是要执行的state文件,不包换扩展名

一般对minion进行初始化操作时用top.sls比较多

通过正则进行匹配的示例

[root@master ~]# vim /srv/salt/top.sls
base:
  '*':
    - tengine
    
[root@master ~]# salt '*' state.highstate

通过分组名进行匹配的示例(必须要有 - match: nodegroup)

base:
  group1:
    - match: nodegroup    
    - web

通过grain模块匹配的示例(必须要有- match: grain)

base:
  'os:Fedora':
    - match: grain
    - web
  • init.sls

init.sls在一个子目录里面表示引导文件,我们可以在init.sls里面通过include模块来决定sls文件执行顺序

include:
  - tengine.make
  - tengine.install

5.案例

文件树如下

[root@master ~]# tree /srv/salt/tengine
| --top.sls
| --init.sls
| --install.sls
| --make.sls
| --files
     | --tengine-2.3.1.tar.gz

top.sls

base:
  '*':
    - tengine

init.sls

include:
  - tengine.make
  - tengine.install

make.sls

pkg-init:
  pkg.installed:
    - pkgs:
    - automake
    - gcc-c++
    - zlib-devel
    - openssl-devel
    - pcre-devel

install.sls

include:
  - tengine.make

tengine_source:
  file.managed:
    - name: /tmp/tengine-2.3.1.tar.gz
    - unless: test -e /tmp/tengine-2.3.1.tar.gz
    - source: salt://tengine/files/tengine-2.3.1.tar.gz

extract_tengine:
  cmd.run:
    - cwd: /tmp
    - names:
      - tar zxf tengine-2.3.1.tar.gz
    - unless:
      - test -d tengine-2.3.1
    - require:
      - file: tengine_source

tengine_compile:
  cmd.run:
    - cwd: /tmp/tengine-2.3.1
    - names:
      - ./configure --prefix=/usr/local/tengine && make && make install
    - require:
      - cmd: extract_tengine
    - unless: test -d /usr/local/tengine

执行命令

salt '192.168.244.128' state.highstate

总结

介绍了saltstack的一些基础命令,如何实现分组管理以及SLS相关内容

Grains

Grains是saltstack的一个组件,存放在minion端

当minion启动时会把收集到的数据静态存放在Grains中,只有minion重启时才会进行数据的更新

1.应用场景

  • 信息查询,用于查询minion的IP、OS等静态信息
  • 在target中使用,匹配minion
  • 在SLS中使用,配置管理模块

2.常用命令

列出minion1所有的静态数据key

salt 'minion1' grains.list

列出node1所有的静态数据key与value

salt 'minion1' grains.items 

列出所有minion的OS

salt '*' grains.item os

对匹配到的minion执行操作

salt -G 'os:CentOS' cmd.run ‘echo haha’ 

3.Grains配置

我们可以在/etc/salt/grains中定义

[root@minion1 ~]#vim /etc/salt/grains
role: nginx
env: test
myname: edison

也可以在/etc/salt/minion中定义,但是要满足YAML格式

[root@minion1 ~]#vim /etc/salt/minion
grains:
  role:
    - nginx
  env:
    - test
  myname:
    - edison

4.自定义Grains

我们可以定制Grains来用于分组管理

写一个python脚本,在/srv/salt/下创建一个_grains的目录,然后在这个目录中创建**.py**文件

[root@minion1 ~]# mkdir /srv/salt/_grains
[root@minion1 ~]# vim /srv/salt/_grains/test.py
#!/usr/bin/env python
def my_grains():
  grains = 
  grains['os'] = 'Redhat'
  grains['name'] = 'Python'
  return grains

然后在master端获取Grains

#列出多个
[root@master ~]# salt '192.168.244.129' grains.item role env myname

#列出一个
[root@master ~]# salt '192.168.244.129' grains.get myname

Grains在远程执行命令时很方便,我们可以按照Grains的一些指标来操作 比如把所有的web服务器的grains的role设置为nginx,这样我们就可以批量对nginx服务器进行操作

[root@minion1 ~]# vim /srv/salt/_grains/test.py
#!/usr/bin/env python
def my_grains():
  grains = 
  grains['os'] = 'Redhat'
  grains['role'] = 'nginx'
  return grains
[root@master ~]# salt -G role:nginx cmd.run 'hostname'
[root@master ~]# salt -G os:Redhat cmd.run 'hostname'

5.优先级

系统自带——>grains文件写的——>minion配置文件写的——>自己写的

##每次修改数据都需要重启服务或刷新grains操作才会生效,这也印证了是静态数据
[root@master ~]# salt '*' saltutil.sync_grains ##用于刷新grains的数据

Pillar

Pillar和Grains不同,Pillar是在master上定义的,并且是针对minion而去定义的信息,不需要到minion上进行操作

像一些重要的数据密码都可以存储在pillar上,pillar存储的是动态信息

pillar是存储在master端,缓存在minion端,存储的是minion的一些配置信息

1.应用场景

  • 比较敏感的数据,比如密码,key等
  • 特殊数据到特定Minion上
  • 动态的内容

2.常用命令

查看minion的pillar信息

salt '*' pillar.items

查看某个pillar值

salt '*' pillar.item <key> #只能看到顶级的
salt '*' pillar.get <key>:<key> #可以取到更小粒度的

刷新pillar

salt '*' saltutil.refresh_pillar

3.Pillar配置

先在master端修改配置文件,打开pillar组件目录

[root@master ~]# vim /etc/salt/master 
//找到如下内容,去掉注释
pillar_roots:
  base:
    - /srv/pillar

自定义配置文件

[root@master ~]# vim /srv/pillar/test.sls
conf: /etc/test.conf | myname: tpp

入口文件

[root@master ~]# vim /srv/pillar/top.sls
base:
  'slaver.test.com':
    - test

配置好后重启

[root@master ~]# systemctl restart salt-master

更改完配置文件后,我们可以通过·刷新pillar配置来获取新的动态

[root@master ~]# salt '*' saltutil.refresh_pillar

验证

[root@master ~]# salt 'slaver.test.com' pillar.items

[root@master ~]# salt 'slaver.test.com' pillar.item conf

[root@master ~]# salt 'slaver.test.com' pillar.item mynam

pillar同样可以用来作为salt的匹配对象

[root@master ~]# salt -I 'conf:/etc/123.conf' test.ping
[root@master ~]# salt -I 'conf:/etc/123.conf' cmd.run 'w'

4.Pillar案例

案例一:通过yum方式安装apache

  • 配置文件
[root@master ~]# vim /etc/salt/master //打开如下内容的注释,添加主目录
file_roots:
  base:
    - /srv/salt
pillar_roots:
  base:
    - /srv/pillar
  • 创建目录以及编写入口文件
[root@master ~]# mkdir /srv/salt
[root@master ~]# vim /srv/salt/top.sls
base:
  'slaver.test.com': #如果换成*,表示在所有minion执行apache模块
    - apache
  • 写pillar文件
[root@master ~]# vim /srv/salt/apache.sls
apache-service: #自定义标签名
  pkg.installed: #函数以及方法
    - name: #如果只有一个服务,写成-name: httpd 一行即可
    - httpd
    - httpd-devel
  service.running:
    - name: httpd
    - enable: True
  • 执行命令
[root@master ~]# salt 'slaver.test.com' state.highstate

案例二:目录管理

  • 编辑pillar文件
[root@master ~]# vim /srv/salt/editdir.sls
edit-dir:
  file.recurse:
    - name: /tmp/testdir
    - source: salt://test1
    - user: root
    - file_mode: 644
    - dir_mode: 755
    - mkdir: True
    - clean: True
#clean: True   master处删除文件或目录,目标也会跟着删除,否则不会删除。可以默认设置为 False
  • 新建测试目录
[root@master ~]# mkdir -p /srv/salt/test1
[root@master ~]# vim /srv/salt/test1/1.txt
hello world
  • 验证
[root@master ~]# salt 'slaver.test.com' state.sls editdir

在master新建 my_dir 目录以及 test_dir.add 文件,删除 1.txt 文件

[root@master ~]# mkdir /srv/salt/test1/my_dir
[root@master ~]# touch /srv/salt/test1/my_dir/2.txt
[root@master ~]# touch /srv/salt/test1/testdir.add
[root@master ~]# rm -rf /srv/salt/test1/1.txt


[root@master ~]# salt 'slaver.test.com' state.sls editdir

成功在minion /tmp/testdir/ 目录下创建了my_dir目录和test_dir.add文件,并删除了1.txt文件

值得注意的是要成功创建 my_dir 目录,前提是 master端的my_dir 目录下要有文件,比如这里的2.txt 文件,如若没有,客户端是不会创建 my_dir 目录的

案例三:远程执行

前面提到的远程执行命令 test.ping、cmd.run,直接敲在命令行不太规范和优雅,我们可以通过pillar实现远程执行命令

  • 编写pillar文件
[root@master ~]# vim /srv/salt/cmdtest.sls
cmd-test:
  cmd.run:
    - onlyif: test -f /tmp/123.txt
    - names:
      - touch /tmp/cmdtest.txt
      - mkdir /tmp/cmdtest
    - user: root
#onlyif条件:如果/tmp/123.txt存在,执行后面的命令;unless与之相反
  • 执行命令
[root@master ~]# salt 'slaver.test.com' state.sls cmdtest

案例四:任务计划cron

  • 编写pillar文件
[root@master ~]# vim /srv/salt/crontest.sls
cron-test:
  cron.present: #cron.absent是删除cron
    - name: /bin/touch /tmp/111.txt #创建111.txt
    - user: root
    - minute: '*'
    - hour: 20
    - daymonth: 1-10
    - month: '3,5'
    - dayweek: '*'
# *需要用单引号引起来。当然我们还可以使用 file.managed 模块来管理 cron,因为系统的 cron都是以配置文件的形式存在的
  • 执行
[root@master ~]# salt "slaver.test.com" state.sls crontest

SaltStack部署实践 | 一键部署Nginx、Redis

今天来学习一下如何通过编写 Saltstack 状态脚本来实现自动化批量部署Nginx、Redis

能力有限,内容为自身所学认知之文,不敢苟才,希望能够给有兴趣者一丁点帮助启发即可

Redis

我们现在 salt-master 的家目录下创建一个 Redis 目录,用来存放相关文件

mkdir /home/salt/redis/files -pv

创建好之后,根据自己需要将定制的redis的配置文件和注册服务文件放在files目录下

[root@server1 ~]# ll /home/salt/redis/files/
redis.conf
redis-server.service
redis-6.2.6.tar.gz
 

开始编写sls脚本

vim /home/salt/redis/install.sls

我们这次安装redis的版本为 6.2.6 版本

% set VERSION = '6.2.6' %

创建redis存放数据目录、日志目录、配置文件目录

redisdata_dir:
  file.directory:
    - name: /var/lib/redis
    - user: root
    - group: root
    - makedirs: True
    - unless:
      - test -e /var/lib/redis

redislog_dir:
  file.directory:
    - name: /var/log/redis
    - user: root
    - group: root
    - makedirs: True
    - require:
      - file: redisdata_dir
    - unless:
      - test -e /var/log/redis


redisconf_dir:
  file.directory:
    - name: /etc/redis
    - user: root
    - group: root
    - makedirs: True
    - require:
      - file: redislog_dir
    - unless:
      - test -e /etc/redis

接着我们将 redis 压缩包分发到每台minion上

PS:redis的工作目录在 /opt/redis-6.2.6/ 下

redis_source:
  file.managed:
    - name: /opt/redis-VERSION.tar.gz
    - source: salt://redis/files/redis-VERSION.tar.gz
    - require:
      - file: redisconf_dir
    - unless:
      - test -e /opt/redis-VERSION.tar.gz

然后解压缩

redis_extract:
  cmd.run:
    - cwd: /opt
    - names:
      - tar zxf redis- VERSION.tar.gz
    - require:
      - file: redis_source
    - unless:
      - test -e /opt/redis-VERSION

编译安装redis

redis_complie:
  cmd.run:
    - cwd: /opt/redis-VERSION
    - names:
      - make clean && make > /dev/null && make install > /dev/null
    - require:
      - cmd: redis_extract
    - unless:
      - test -e /usr/local/bin/redis-server

下发 Redis 服务配置文件并重新加载服务配置文件

redis_system:
  file.managed:
    - name: /usr/lib/systemd/system/redis-server.service
    - source: salt://redis/files/redis-server.service
    - require:
      - cmd: redis_complie
    - unless:
      - test -e /usr/lib/systemd/system/redis-server.service
      
redis_service_reload:
  cmd.run:
    - names:
      - systemctl daemon-reload
    - require:
      - file: redis_system      

下发 Redis 配置文件

redis_conf:
  file.managed:
    - name: /etc/redis/redis.conf
    - source: salt://redis/files/redis.conf
    - require:
      - cmd: redis_service_reload
    - unless:
      - test -e /etc/redis/redis.conf

启动Redis并加入到开机自启动中

redis_enable:
  cmd.run:
    - names:
      - systemctl enable redis-server
      - systemctl start redis-server
    - unless:
      - systemctl status redis-server

编写完之后我们在 master 上执行 salt 命令

salt ip地址 state.sls redis.install

完整脚本如下:

% set VERSION = '6.2.6' %

redisdata_dir:
  file.directory:
    - name: /var/lib/redis
    - user: root
    - group: root
    - makedirs: True
    - unless:
      - test -e /var/lib/redis

redislog_dir:
  file.directory:
    - name: /var/log/redis
    - user: root
    - group: root
    - makedirs: True
    - require:
      - file: redisdata_dir
    - unless:
      - test -e /var/log/redis

redisconf_dir:
  file.directory:
    - name: /etc/redis
    - user: root
    - group: root
    - makedirs: True
    - require:
      - file: redislog_dir
    - unless:
      - test -e /etc/redis
      
redis_source:
  file.managed:
    - name: /opt/redis-VERSION.tar.gz
    - source: salt://redis/files/redis-VERSION.tar.gz
    - require:
      - file: redisconf_dir
    - unless:
      - test -e /opt/redis-VERSION.tar.gz

redis_extract:
  cmd.run:
    - cwd: /opt
    - names:
      - tar zxf redis- VERSION.tar.gz
    - require:
      - file: redis_source
    - unless:
      - test -e /opt/redis-VERSION

redis_complie:
  cmd.run:
    - cwd: /opt/redis-VERSION
    - names:
      - make clean && make > /dev/null && make install > /dev/null
    - require:
      - cmd: redis_extract
    - unless:
      - test -e /usr/local/bin/redis-server

redis_system:
  file.managed:
    - name: /usr/lib/systemd/system/redis-server.service
    - source: salt://redis/files/redis-server.service
    - require:
      - cmd: redis_complie
    - unless:
      - test -e /usr/lib/systemd/system/redis-server.service

redis_service_reload:
  cmd.run:
    - names:
      - systemctl daemon-reload
    - require:
      - file: redis_system
      
redis_conf:
  file.managed:
    - name: /etc/redis/redis.conf
    - source: salt://redis/files/redis.conf
    - require:
      - cmd: redis_service_reload
    - unless:
      - test -e /etc/redis/redis.conf

redis_enable:
  cmd.run:
    - names:
      - systemctl enable redis-server
      - systemctl start redis-server
    - unless:
      - systemctl status redis-server  

Nginx

我们在 salt-master 的家目录下创建 Nginx 目录来存放相关脚本文件

mkdir -pv /home/salt/nginx/files
  • conf.sls:负责nginx的文件下发
  • init.sls:saltstack执行sls脚本顺序
  • install.sls:负责nginx的安装前准备以及编译安装
  • files:存放nginx配置文件以及注册服务文件,比如说nginx.conf、nginx.service

创建好之后,根据自己需要将定制的 Nginx 的配置文件和注册服务文件放在files目录下

编写 init.sls 文件

vim /home/salt/nginx/init.sls
include:
  - nginx.install
  - nginx.conf

下面开始进行 Nginx 的安装,这里我写了两个脚本,分别对应Nginx的不同安装方式:

1、一个源码编译安装 Nginx

2、一个是 yum 安装 Nginx

源码编译安装Nginx

首先编写安装脚本

vim /home/salt/nginx/install.sls

编译安装Nginx的话我们指定安装版本

% set VERSION = '1.15.4' %

创建Nginx工作目录、日志目录

data_dir:
  file.directory:
    - name: /var/lib/nginx
    - user: root
    - group: root
    - makedirs: True
    - unless:
      - test -e /var/lib/nginx

log_dir:
  file.directory:
    - name: /var/log/nginx
    - user: root
    - group: root
    - makedirs: True
    - require:
      - file: data_dir
    - unless:
      - test -e /var/log/nginx

下发 Nginx 压缩包到minio,接着进行解压缩

nginx_source:
  file.managed:
    - name: /opt/nginx-VERSION.tar.gz
    - source: salt://nginx/nginx-VERSION.tar.gz
    - require:
      - file: log_dir
    - unless:
      - test -e /opt/nginx-VERSION.tar.gz

nginx_extract:
  cmd.run:
    - cwd: /opt
    - names:
      - tar zxf nginx- VERSION.tar.gz
    - require:
      - file: nginx_source
    - unless:
      - test -e /opt/nginx-VERSION

安装编译安装时所需要的工具包

nginx_pkg:
  pkg.installed:
    - pkgs:
      - gcc
      - openssl-devel
      - pcre-devel
      - zlib-devel
    - require:
      - file: nginx_extract

编译安装Nginx

指定Nginx的工作目录为:/opt/nginx

nginx_compile:
  cmd.run:
    - cwd: /opt/nginx-version
    - names:
      - ./configure --prefix=/opt/nginx --with-http_stub_status_module --with-file-aio --with-http_ssl_module && make && make install
    - require:
      - pkg: nginx_pkg
    - unless: test -d /opt/nginx

接着编写配置下发脚本

vim /home/salt/nginx/conf.sls

创建Nginx配置文件目录软连接(个人习惯)

nginx_softlink:
  cmd.run:
    - name: ln -s /opt/nginx/conf/ /etc/nginx

下发Nginx配置文件

nginx_conf:
  file.managed:
    - name: /etc/nginx/nginx.conf
    - source: salt://nginx/files/nginx.conf
    - require:
      - cmd: nginx_softlink
    - unless:
      - test -e /etc/nginx/nginx.conf

下发Nginx注册服务文件,并重新加载

nginx_system:
  file.managed:
    - name: /usr/lib/systemd/system/nginx.service
    - source: salt://nginx/files/nginx.service
    - require:
      - file: nginx_conf
    - unless:
      - test -e /usr/lib/systemd/system/nginx.service

nginx_systemreload:
  cmd.run:
    - name:
      - systemctl daemon-reload
    - require:
      - file: nginx_system

Nginx内核参数调优

nginx_kernel:
  cmd.run:
    - cwd: /etc/sysctl.conf
  file.append:
    - text:
      - #set nginx kernel args
      - net.ipv4.tcp_keepalive_time = 30
      - net.ipv4.ip_local_port_range = 1024 65000
      - net.ipv4.tcp_max_tw_buckets = 15000
      - net.ipv4.tcp_tw_reuse = 1
      - net.ipv4.tcp_tw_recycle = 0
      - net.ipv4.tcp_fin_timeout = 30
      - net.core.somaxconn = 65535
      - net.core.netdev_max_backlog = 262144
      - net.ipv4.tcp_max_orphans = 262144
      - net.ipv4.tcp_max_syn_backlog = 262144
      - net.ipv4.tcp_timestamps = 0
      - net.ipv4.tcp_synack_retries = 1
      - net.ipv4.tcp_syn_retries = 1
    - unless: grep "#set nginx kernel args" /etc/sysctl.conf
  cmd.run:
    - name: /sbin/sysctl -p

启动 Nginx 并加入到开机自启动中

nginx_start:
  cmd.run:
    - name:
      - systemctl start nginx
      - systemctl enable nginx
    - require:
      - cmd: nginx_systemreload
    - unless:
      - systemctl status nginx

编写完之后我们在 master 上执行 salt 命令

salt ip地址 state.sls nginx.init

完整脚本如下:

install.sls

% set VERSION = '1.15.4' %

data_dir:
  file.directory:
    - name: /var/lib/nginx
    - user: root
    - group: root
    - makedirs: True
    - unless:
      - test -e /var/lib/nginx
      
log_dir:
  file.directory:
    - name: /var/log/nginx
    - user: root
    - group: root
    - makedirs: True
    - require:
      - file: data_dir
    - unless:
      - test -e /var/log/nginx

nginx_source:
  file.managed:
    - name: /opt/nginx-VERSION.tar.gz
    - source: salt://nginx/nginx-VERSION.tar.gz
    - require:
      - file: log_dir
    - unless:
      - test -e /opt/nginx-VERSION.tar.gz

nginx_extract:
  cmd.run:
    - cwd: /opt
    - names:
      - tar zxf nginx- VERSION.tar.gz
    - require:
      - file: nginx_source
    - unless:
      - test -e /opt/nginx-VERSION
      
nginx_pkg:
  pkg.installed:
    - pkgs:
      - gcc
      - openssl-devel
      - pcre-devel
      - zlib-devel
    - require:
      - file: nginx_extract

nginx_compile:
  cmd.run:
    - cwd: /opt/nginx-version
    - names:
      - ./configure --prefix=/opt/nginx --with-http_stub_status_module --with-file-aio --with-http_ssl_module && make && make install
    - require:
      - pkg: nginx_pkg
    - unless: test -d /opt/nginx

conf.sls

nginx_softlink:
  cmd.run:
    - name: ln -s /opt/nginx/conf/ /etc/nginx
    
nginx_conf:
  file.managed:
    - name: /etc/nginx/nginx.conf
    - source: salt://nginx/files/nginx.conf
    - require:
      - cmd: nginx_softlink
    - unless:
      - test -e /etc/nginx/nginx.conf

nginx_system:
  file.managed:
    - name: /usr/lib/systemd/system/nginx.service
    - source: salt://nginx/files/nginx.service
    - require:
      - file: nginx_conf
    - unless:
      - test -e /usr/lib/systemd/system/nginx.service

nginx_systemreload:
  cmd.run:
    - name:
      - systemctl daemon-reload
    - require:
      - file: nginx_system

nginx_kernel:
  cmd.run:
    - cwd: /etc/sysctl.conf
  file.append:
    - text:
      - #set nginx kernel args
      - net.ipv4.tcp_keepalive_time = 30
      - net.ipv4.ip_local_port_range = 1024 65000
      - net.ipv4.tcp_max_tw_buckets = 15000
      - net.ipv4.tcp_tw_reuse = 1
      - net.ipv4.tcp_tw_recycle = 0
      - net.ipv4.tcp_fin_timeout = 30
      - net.core.somaxconn = 65535
      - net.core.netdev_max_backlog = 262144
      - net.ipv4.tcp_max_orphans = 262144
      - net.ipv4.tcp_max_syn_backlog = 262144
      - net.ipv4.tcp_timestamps = 0
      - net.ipv4.tcp_synack_retries = 1
      - net.ipv4.tcp_syn_retries = 1
    - unless: grep "#set nginx kernel args" /etc/sysctl.conf
  cmd.run:
    - name: /sbin/sysctl -p

nginx_start:
  cmd.run:
    - name:
      - systemctl start nginx
      - systemctl enable nginx
    - require:
      - cmd: nginx_systemreload
    - unless:
      - systemctl status nginx

yum安装Nginx

编写 install.sls

vim /home/salt/nginx/install.sls
update_yum:
  cmd.run:
    - name: yum update -y

nginx_install:
  pkg.installed:
    - pkgs:
      - epel-release
      - nginx
    - require:
      - cmd: update_yum
    - unless:
      - systemctl status nginx

编写 conf.sls

vim /home/salt/nginx/conf.sls

yum 安装 Nginx配置目录在 /etc/nginx 下

下发 Nginx 配置文件

nginx_conf:
  file.managed:
    - name: /etc/nginx/nginx.conf
    - source: salt://nginx/files/nginx.conf
    - unless:
      - test -e /etc/nginx/nginx.conf

Nginx 内核参数调优

nginx_kernel:
  cmd.run:
    - cwd: /etc/sysctl.conf
  file.append:
    - text:
      - #set nginx kernel args
      - net.ipv4.tcp_keepalive_time = 30
      - net.ipv4.ip_local_port_range = 1024 65000
      - net.ipv4.tcp_max_tw_buckets = 15000
      - net.ipv4.tcp_tw_reuse = 1
      - net.ipv4.tcp_tw_recycle = 0
      - net.ipv4.tcp_fin_timeout = 30
      - net.core.somaxconn = 65535
      - net.core.netdev_max_backlog = 262144
      - net.ipv4.tcp_max_orphans = 262144
      - net.ipv4.tcp_max_syn_backlog = 262144
      - net.ipv4.tcp_timestamps = 0
      - net.ipv4.tcp_synack_retries = 1
      - net.ipv4.tcp_syn_retries = 1
    - unless: grep "#set nginx kernel args" /etc/sysctl.conf
  cmd.run:
    - name: /sbin/sysctl -p

启动 Nginx 并加入到开机自启动中

nginx_start:
  cmd.run:
    - name:
      - systemctl start nginx
      - systemctl enable nginx
    - require:
      - file: nginx_conf
    - unless:
      - systemctl status nginx

完整脚本如下:

install.sls

update_yum:
  cmd.run:
    - name: yum update -y

nginx_install:
  pkg.installed:
    - pkgs:
      - epel-release
      - nginx
    - require:
      - cmd: update_yum
    - unless:
      - systemctl status nginx

conf.sls

nginx_conf:
  file.managed:
    - name: /etc/nginx/nginx.conf
    - source: salt://nginx/files/nginx.conf
    - unless:
      - test -e /etc/nginx/nginx.conf

nginx_kernel:
  cmd.run:
    - cwd: /etc/sysctl.conf
  file.append:
    - text:
      - #set nginx kernel args
      - net.ipv4.tcp_keepalive_time = 30
      - net.ipv4.ip_local_port_range = 1024 65000
      - net.ipv4.tcp_max_tw_buckets = 15000
      - net.ipv4.tcp_tw_reuse = 1
      - net.ipv4.tcp_tw_recycle = 0
      - net.ipv4.tcp_fin_timeout = 30
      - net.core.somaxconn = 65535
      - net.core.netdev_max_backlog = 262144
      - net.ipv4.tcp_max_orphans = 262144
      - net.ipv4.tcp_max_syn_backlog = 262144
      - net.ipv4.tcp_timestamps = 0
      - net.ipv4.tcp_synack_retries = 1
      - net.ipv4.tcp_syn_retries = 1
    - unless: grep "#set nginx kernel args" /etc/sysctl.conf
  cmd.run:
    - name: /sbin/sysctl -p

nginx_start:
  cmd.run:
    - name:
      - systemctl start nginx
      - systemctl enable nginx
    - require:
      - file: nginx_conf
    - unless:
      - systemctl status nginx
ckets = 15000
      - net.ipv4.tcp_tw_reuse = 1
      - net.ipv4.tcp_tw_recycle = 0
      - net.ipv4.tcp_fin_timeout = 30
      - net.core.somaxconn = 65535
      - net.core.netdev_max_backlog = 262144
      - net.ipv4.tcp_max_orphans = 262144
      - net.ipv4.tcp_max_syn_backlog = 262144
      - net.ipv4.tcp_timestamps = 0
      - net.ipv4.tcp_synack_retries = 1
      - net.ipv4.tcp_syn_retries = 1
    - unless: grep "#set nginx kernel args" /etc/sysctl.conf
  cmd.run:
    - name: /sbin/sysctl -p

启动 Nginx 并加入到开机自启动中

nginx_start:
  cmd.run:
    - name:
      - systemctl start nginx
      - systemctl enable nginx
    - require:
      - file: nginx_conf
    - unless:
      - systemctl status nginx

完整脚本如下:

install.sls

update_yum:
  cmd.run:
    - name: yum update -y

nginx_install:
  pkg.installed:
    - pkgs:
      - epel-release
      - nginx
    - require:
      - cmd: update_yum
    - unless:
      - systemctl status nginx

conf.sls

nginx_conf:
  file.managed:
    - name: /etc/nginx/nginx.conf
    - source: salt://nginx/files/nginx.conf
    - unless:
      - test -e /etc/nginx/nginx.conf

nginx_kernel:
  cmd.run:
    - cwd: /etc/sysctl.conf
  file.append:
    - text:
      - #set nginx kernel args
      - net.ipv4.tcp_keepalive_time = 30
      - net.ipv4.ip_local_port_range = 1024 65000
      - net.ipv4.tcp_max_tw_buckets = 15000
      - net.ipv4.tcp_tw_reuse = 1
      - net.ipv4.tcp_tw_recycle = 0
      - net.ipv4.tcp_fin_timeout = 30
      - net.core.somaxconn = 65535
      - net.core.netdev_max_backlog = 262144
      - net.ipv4.tcp_max_orphans = 262144
      - net.ipv4.tcp_max_syn_backlog = 262144
      - net.ipv4.tcp_timestamps = 0
      - net.ipv4.tcp_synack_retries = 1
      - net.ipv4.tcp_syn_retries = 1
    - unless: grep "#set nginx kernel args" /etc/sysctl.conf
  cmd.run:
    - name: /sbin/sysctl -p

nginx_start:
  cmd.run:
    - name:
      - systemctl start nginx
      - systemctl enable nginx
    - require:
      - file: nginx_conf
    - unless:
      - systemctl status nginx

自动化运维工具saltstack

常见自动化运维工具

传统运维效率低,工作繁琐且容易出错
重复性事情反复在做,没有标准化的流程
传统运维的脚本繁多,不方便管理
自动化运维要解决的就是这些问题
常见的自动化运维工具
puppet (www.puppetlabs.com)
基于rubby开发,c/s架构,支持多平台。可管理配置文件、用户、cron任务、软件包管理、系统服务等。分为社区版(免费)和企业版(收费),企业版支持图形化配置
Saltstack(官网:https://saltstack.com,文档:docs.saltstack.com)
基于python开发,c/s架构,支持多平台,比puppet轻量,在远程执行命令时非常便捷,配置和使用都比puppet容易,且能实现puppet几乎所有的功能
Ansible (www.ansible.com)
更加简洁的自动化运维工具,不需要在客户端上安装agent用户端,基于python开发。可以实现批量操作系统配置、批量程序部署、批量运行命令
自动化运维工具和脚本自动批量执行命令有些区别,脚本若使用for、while循环一个操作指令时,实际上这个指令只会在一台服务器上操作完成后才继续传递到下一台服务器继续循环执行,这种方式像串行执行,所有任务只能在前一条完成后才能够继续执行下一条
自动化运维工具则属于并行执行,则一些操作命令同时发布到所有机器上同时进行处理,这样的处理方式要比脚本for循环的方式要快的多

saltstack安装

saltstack可以使用salt-ssh远程执行,类似于ansible,也支持c/s模式,下面介绍该模式的使用方式
准备两台测试主机
192.168.1.115位服务端
192.168.1.223为客户端两台服务器均设置hostname和hosts,hosts是用于把主机名解析到ip的,如果服务器很多,可以考虑在内部网络环境中配置一台DNS解析服务器,1.115主机名为nfs3,·1.223主机名为nfs2
两台机器需要全部安装saltstack yum源,如果这里列出的yum源失效,则需要自行在其官网上寻找yum源下载地址

http://repo.saltstack.com/#rhel
sudo yum install https://repo.saltstack.com/yum/redhat/salt-repo-latest-2.el7.noarch.rpm 

安装服务端和客户端

在服务端安装salt-master 和salt-minion,在安装时会自动解决软件包的依赖关系,在安装结果中也可以看到saltstack的安装的版本
yum安装中的zeromq包是saltstack中的消息队列服务插件

[[email protected] ~]# yum install salt-master salt-minion -y

Loaded plugins: fastestmirror

base | 3.6 kB 00:00:00 ? ? 

epel/x86_64/metalink | 8.4 kB 00:00:00 ? ? 

epel | 3.2 kB 00:00:00 ? ? 

extras | 3.4 kB 00:00:00 ? ? 

mongodb-org-4.0 ? 

--------------------省略

Dependency Installed:

  PyYAML.x86_64 0:3.11-1.el7 ? ? ? ? ? ? ? ? ? ? ?  libsodium.x86_64 0:1.0.16-1.el7 ? ? ? ? ? ? ? ? ?  libtomcrypt.x86_64 0:1.17-26.el7 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
  libtommath.x86_64 0:0.42.0-6.el7 ? ? ? ? ? ? ? ?  libyaml.x86_64 0:0.1.4-11.el7_0 ? ? ? ? ? ? ? ? ?  openpgm.x86_64 0:5.2.122-2.el7 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
  python-babel.noarch 0:0.9.6-8.el7 ? ? ? ? ? ? ? ? python-backports.x86_64 0:1.0-8.el7 ? ? ? ? ? ? ?  python-backports-ssl_match_hostname.noarch 0:3.5.0.1-1.el7 ? ? ? ? ? ?
  python-chardet.noarch 0:2.2.1-1.el7_1 ? ? ? ? ? ? python-ipaddress.noarch 0:1.0.16-2.el7 ? ? ? ? ? ? python-jinja2.noarch 0:2.7.2-2.el7 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
  python-kitchen.noarch 0:1.1.1-5.el7 ? ? ? ? ? ? ? python-markupsafe.x86_64 0:0.11-10.el7 ? ? ? ? ? ? python-requests.noarch 0:2.6.0-1.el7_1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
  python-tornado.x86_64 0:4.2.1-3.el7 ? ? ? ? ? ? ? python-urllib3.noarch 0:1.10.2-5.el7 ? ? ? ? ? ? ? python-zmq.x86_64 0:15.3.0-3.el7 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
  python2-crypto.x86_64 0:2.6.1-15.el7 ? ? ? ? ? ?  python2-futures.noarch 0:3.0.5-1.el7 ? ? ? ? ? ? ? python2-msgpack.x86_64 0:0.5.6-4.el7 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
  python2-psutil.x86_64 0:2.2.1-4.el7 ? ? ? ? ? ? ? salt.noarch 0:2018.3.3-1.el7 ? ? ? ? ? ? ? ? ? ? ? yum-utils.noarch 0:1.1.31-46.el7_5 ? 

Complete!

在用户端安装salt-minion

[[email protected] ~]# yum install -y salt-minion
Loaded plugins: fastestmirror
base | 3.6 kB 00:00:00 ? ? 
elrepo | 2.9 kB 00:00:00 ? ? 
epel/x86_64/metalink | 8.4 kB 00:00:00 ? ? 
epel | 3.2 kB 00:00:00 ? ? 
extras | 3.4 kB 00:00:00 ? ? 
mongodb-org-4.0 | 2.5 kB 00:00:00 ? ? 
salt-latest | 2.9 kB 00:00:00 ? ? 
updates | 3.4 kB 00:00:00 ? ? 
(1/3): epel/x86_64/updateinfo | 934 kB 00:00:01 ? ? 
(2/3): salt-latest/x86_64/primary_db | 42 kB 00:00:02 ? ? 
(3/3): epel/x86_64/primary | 3.6 MB 00:00:05 ? ? 
Determining fastest mirrors
 * elrepo: mirrors.tuna.tsinghua.edu.cn
 * epel: mirrors.ustc.edu.cn
----------------------------------按照结果省略,正确安装完成

saltstack相关服务配置

服务端salt服务配置文件
编辑配置文件/etc/salt/minion
找到master配置那行,将服务端(master)的解析名称(/etc/hosts中配置的)填写到这里

[[email protected] ~]# vim /etc/salt/minion
master: nfs3

服务端启动salt服务

[[email protected] ~]# systemctl start salt-minion
[[email protected] ~]# systemctl start salt-master

salt启动的是名为python进程,使用ps -aux查看启动的进程

[[email protected] ~]# ps -aux |grep salt
root ? ? ? 3218 ?0.0 ?1.1 307760 21500 ? ? ? ?  Ss ? 22:55 ? 0:00 /usr/bin/python /usr/bin/salt-minion
root ? ? ? 3221 ?0.0 ?2.4 641596 45428 ? ? ? ?  Sl ? 22:55 ? 0:02 /usr/bin/python /usr/bin/salt-minion
root ? ? ? 3229 ?0.0 ?1.0 397724 20304 ? ? ? ?  S ? ?22:55 ? 0:00 /usr/bin/python /usr/bin/salt-minion
root ? ? ? 3297 ?0.0 ?2.1 382876 40796 ? ? ? ?  Ss ? 22:55 ? 0:01 /usr/bin/python /usr/bin/salt-master
root ? ? ? 3302 ?0.0 ?1.0 306172 20176 ? ? ? ?  S ? ?22:55 ? 0:00 /usr/bin/python /usr/bin/salt-master
root ? ? ? 3307 ?0.0 ?1.8 463596 34496 ? ? ? ?  Sl ? 22:55 ? 0:00 /usr/bin/python /usr/bin/salt-master

服务端的master是需要监听端口的,salt-master进程监听4505和4506两个服务端口

[[email protected] ~]# netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address ? ? ? ? ? Foreign Address ? ? ? ? State ? ? ? PID/Program name ? ?
tcp ? ? ? ?0 ? ? ?0 127.0.0.1:6379 ? ? ? ? ?0.0.0.0:* ? ? ? ? ? ? ? LISTEN ? ? ?1615/redis-server 1 
tcp ? ? ? ?0 ? ? ?0 0.0.0.0:22 ? ? ? ? ? ? ?0.0.0.0:* ? ? ? ? ? ? ? LISTEN ? ? ?1607/sshd ? ? ? ? ? 
tcp ? ? ? ?0 ? ? ?0 0.0.0.0:4505 ? ? ? ? ? ?0.0.0.0:* ? ? ? ? ? ? ? LISTEN ? ? ?3307/python ? ? ? ? 
tcp ? ? ? ?0 ? ? ?0 127.0.0.1:25 ? ? ? ? ? ?0.0.0.0:* ? ? ? ? ? ? ? LISTEN ? ? ?2751/master ? ? ? ? 
tcp ? ? ? ?0 ? ? ?0 0.0.0.0:4506 ? ? ? ? ? ?0.0.0.0:* ? ? ? ? ? ? ? LISTEN ? ? ?3313/python

用户端启动服务
编辑配置文件/etc/salt/minion
找到master配置那行,将解析名称(/etc/hosts中配置的)填写到这里,指定master解析的名称

[[email protected] ~]# vim /etc/salt/minion
master: nfs3

用户端启动salt-minion服务只会启动python的进程,不会监听任何端口,主要功能是向服务端发送数据,因此salt-minion不会监听任何端口

[[email protected] ~]# systemctl start salt-minion
[[email protected] ~]# ps -axu |grep salt
root ? ? ? 2174 ?4.8 ?2.1 307808 21508 ? ? ? ?  Ss ? 23:45 ? 0:00 /usr/bin/python /usr/bin/salt-minion
root ? ? ? 2184 14.6 ?4.0 459064 40184 ? ? ? ?  Sl ? 23:45 ? 0:01 /usr/bin/python /usr/bin/salt-minion
root ? ? ? 2192 ?0.0 ?2.0 397752 20288 ? ? ? ?  S ? ?23:45 ? 0:00 /usr/bin/python /usr/bin/salt-minion
root ? ? ? 2251 ?0.0 ?0.0 112704 ? 964 pts/0 ?  R+ ? 23:45 ? 0:00 grep --color=auto salt

saltstack配置认证

minion与master建立通信
master服务端和minion端通信需要建立一个安全的通道,传输过程需要加密,所以需要配置认证。也就是通过密钥对来加密解密的
用户端保存公钥
minion在第一次启动是会在/etc/salt/pki/minion目录下生成minion.pen和minion.pub,其中pub为公钥,在传输时会发送给master服务端
服务端保存公钥
master第一次启动也会在/etc/salt/pki/master这个路径下生成密钥对,当master接收到minion发送过来的公钥后,需要通过salt-key工具来接受这个公钥,接受后会在/etc/salt/pki/master/minion这个目录下存储接受的公钥
同时客户端也会接受master服务端发送过来的公钥,将其存储在/etc/salt/pki/minion目录下,并命名为minion_master.pub的公钥文件

需要通过借助salt-key工具实现
在使用salt-key工具之前,需要如下配置正确
1.用户端和服务端都需要修改/etc/salt/minion 配置文件,将master配置的那行都改为服务端的解析名地址。
2.在测试环境中,修改自己的hosts解析,解析名对应服务端的ip地址
完成这些后在服务端可以使用salt-key查看所有的minion端信息

[[email protected] ~]# salt-key
Accepted Keys:
nfs3
Denied Keys:
Unaccepted Keys:
localzabbix.com
Rejected Keys:

将用户端密钥保存至服务端

[[email protected] ~]# salt-key -A
The following keys are going to be accepted:
Unaccepted Keys:
localzabbix.com
Proceed? [n/Y] Y

Key for minion localzabbix.com accepted.
在服务端查看用户端发送过来的公钥是一致的
技术分享图片
删除所有认证过的主机,然后使用salt-key查看发现所有认证都被删除,删除认证后同时保存的公钥也会被删除掉

[[email protected] minions]# salt-key -D
The following keys are going to be deleted:
Accepted Keys:
localzabbix.com
nfs3
Proceed? [N/y] Y
Key for minion localzabbix.com deleted.
Key for minion nfs3 deleted.
[[email protected] minions]# salt-key 
Accepted Keys:
Denied Keys:
Unaccepted Keys:
Rejected Keys:
[[email protected] minions]# pwd
/etc/salt/pki/master/minions
[[email protected] minions]# ls

如果需要重新加入这个主机,需要更新master端的信息(也就是每新加一台服务器,都必须重启master和minion服务,这样服务端才会重新去检测用户端的变化)
salt-key ?语法用法
-a ? 后面跟主机名,认证指定主机
-A ?认证所有主机
-r ? 指定主机名,拒绝指定主机
-R ?拒绝所有主机
-d ?指定主机名,删除指定主机
-D ?删除全部认证过的主机
-y ?语句过程中省略掉交互式,等同于避免按Y交互确认

saltstack执行远程命令

salt ‘*‘ test.ping 测试所有已经认证过的minion端是否通信正常,返回true则表示状态互通,命令也可以指定单独一台主机进行测试

[[email protected] minions]# salt ‘*‘ test.ping
localzabbix.com:
 ?  True
nfs3:
 ?  True
[[email protected] minions]# salt ‘localzabbix.com‘ test.ping
localzabbix.com:
 ?  True

执行远程命令
salt ‘*’ cmd.run "命令" ? 指定主机或多主机来执行远程命令。如下操作过程

[[email protected] minions]# salt ‘*‘ cmd.run "w"
localzabbix.com:
 ? ? 02:19:34 up 1:09, 1 user, load average: 0.00, 0.01, 0.05
 ?  USER TTY FROM [email protected] IDLE JCPU PCPU WHAT
 ?  root pts/0 192.168.1.112 01:11 37:34 0.14s 0.14s -bash
nfs3:
 ? ? 02:19:35 up 5:03, 2 users, load average: 0.00, 0.05, 0.12
 ?  USER TTY FROM [email protected] IDLE JCPU PCPU WHAT
 ?  root tty1 21:42 4:33m 0.06s 0.06s -bash
 ?  root pts/0 192.168.1.112 01:43 7.00s 1.22s 1.11s /usr/bin/python /usr/bin/salt * cmd.run w

这里指定的*或主机名是已经被接受认证过的客户端。可以通过salt-key来查询认证过的,通常是已经设定的id值,关于这部分内容。它支持通配、列表和正则表达式,比如,如果需要指定两台客户端,我们可以写成 salt ‘nfs*’、salt ‘nfs1[13]‘ 、salt -L ‘nfs1,nfs2’ salt -E ‘nfs(1|2)’ ?等形式,还支持列表,多个机器使用逗号进行分隔,需要加上-L选项。使用正则表达式则必须带上-E选项。还支持grains ,需要使用-G选项

以上是关于自动化运维工具-saltstack的主要内容,如果未能解决你的问题,请参考以下文章

自动化运维工具-saltstack

saltstack自动化运维

自动运维工具 -saltstack安装使用(实例演示!!!)

Saltstack 自动化运维工具详细介绍

部署自动化运维工具SaltStack

saltstack——自动运维编排工具