自动化运维工具-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的架构图

自动化运维工具-saltstack_第1张图片

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.认证

自动化运维工具-saltstack_第2张图片

2.连接

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

安装&部署

自动化运维工具-saltstack_第3张图片

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

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] ''  [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端执行

自动化运维工具-saltstack_第4张图片

  • salt-call

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

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

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

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

salt-cp [options] '' 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 做列表匹配,例如:[email protected],minion3.domain.com orbl*.domain.com 
使用 L 列表的方式,必须把 minion 列出来,或者是列出几台后,在后面接 or 或者 and 表达式, or 或者 and 后面接的表达式后面可以使用正则表达式。

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

S -- 针对子网或是 IP 做匹配,例如:[email protected]/24 or [email protected]

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

N -- 针对 nodegroup 做匹配

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

[root@master ~]#vim /etc/salt/master.d/nodegroups.conf
nodegroups:
group1: '[email protected],192.168.244.130'
group2: '[email protected]'
group3: '[email protected]/24'
group4: '[email protected][2-3]'

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

案例:

[root@master ~]# vim  /etc/salt/master.d/nodegroup.conf
nodegroups:
  web: '[email protected],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: '[email protected][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  #只能看到顶级的
salt '*' pillar.get : #可以取到更小粒度的

刷新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_第5张图片

今天来学习一下如何通过编写 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)