一、SaltStack介绍

SaltStack是一种新的基础设施管理方法开发软件,简单易部署,可伸缩的足以管理成千上万的服务器,和足够快的速度控制,与他们交流,以毫秒为单位。SaltStack提供了一个动态基础设施通信总线用于编排,远程执行、配置管理等等。SaltStack项目于2011年启动,年增长速度较快,五年期固定基础设施编制和配置管理的开源项目。SaltStack社区致力于保持盐项目集中、友好、健康、开放。 简单来说它的两大基础功能就是:配置管理、远程命令执行。剩下就是根据你的需求自由组合,实现更复杂的功能和系统管理。

Salt是一种和以往不同的基础设施管理方法,它是建立在大规模系统高速通讯能力可以大幅提升的想法上。这种方法使得Salt成为一个强大的能够解决基础设施中许多特定问题的多任务系统。远程执行引擎是Salt的核心,它能够为多组系统创建高速、安全的双向通讯网络。基于这个通讯系统,Salt提供了一个非常快速、灵活并且容易使用的配置管理系统,称之为"Salt States"。

1.1 自动化运维工具

常用的自动化运维工具有:

  • puppet
  • ansible
  • saltstack

此三款属同类工具,皆可用来提高运维管理的效率,但它们又各有优势,目前主流的自动化运维工具是ansible和saltstack。其中ansible无需安装客户端,这是其最大的优势,而saltstack则需要安装客户端工具,类似zabbix的agent。应用场景方面,ansible常用于小型企业,而saltstack则常用于中大型企业,因为ansible无法并行执行而saltstack可以并行。但不论其特点如何,本质上均属同类,所以只需要掌握一种即可轻松胜任运维工作。 可以将SaltStack理解为神笔马良的那只笔!

  • puppet

特点: puppet与其他手工操作工具有一个最大的区别是 puppet的配置具有稳定性,因此你可以多次执行puppet,一旦你更新了你的配置文件,puppet就会根据配置文件来更改你的机器配置,通常每30分钟检查一次. puppet会让你的系统状态同配置文件所要求的状态保持一致. 比如你配置文件里面要求ssh服务必须开启. 假如不小心ssh服务被关闭了,那么下一次执行puppet的时候,puppet会发现这个异常,然后会开启 ssh 服务. 以使系统状态和配置文件保持一致.puppet就象一个魔术师,会让你的混乱的系统收敛到puppet配置文件所想要的状态.

  • ansible

ansible是基于 paramiko 开发的,并且基于模块化工作,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块, ansible只是提供一种框架。ansible不需要在远程主机上安装client/agents,因为它们是基于ssh来和远 程主机通讯的。ansible目前已经已经被红帽官方收购,是自动化运维工具中大家认可度最高的,并且上手容易,学习简单。是每位运维工程师必须掌握的技能之一\ ansible 特点 部署简单,只需在主控端部署Ansible环境,被控端无需做任何操作; 默认使用SSH协议对设备进行管理; 有大量常规运维操作模块,可实现日常绝大部分操作; 配置简单、功能强大、扩展性强; 支持API及自定义模块,可通过Python轻松扩展; 通过Playbooks来定制强大的配置、状态管理; 轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可; 提供一个功能强大、操作性强的Web管理界面和REST API接口——AWX平台

  • saltstack

基于python开发的C/S架构配置管理工具 底层使用ZeroMQ消息队列pub/sub方式通信 使用SSL证书签发的方式进行认证管理,传输采用AES加密

此三款属同类工具,皆可用来提高运维管理的效率,但它们又各有优势,目前主流的自动化运维工具是ansible和saltstack。其中ansible无需安装客户端,这是其最大的优势,而saltstack则需要安装客户端工具,类似zabbix的agent。应用场景方面,ansible常用于小型企业,而saltstack则常用于中大型企业,因为ansible无法并行执行而saltstack可以并行。但不论其特点如何,本质上均属同类,所以只需要掌握一种即可轻松胜任运维工作。

1.1.1 选择Saltstack的原因

目前市场上主流的开源自动化配置公里工具有puppet、ansible、saltstack。为什么选择saltstack呢?

对比图:

对于puppet由于不支持二次开发,后续一些需求将无法满足,而且puppet有其复杂的、有将近10000行代码的代码库。而使用saltstack和ansible,用1000行左右的代码就能复制puppet的架构。

现在脱颖而出的是saltstack和ansible,再来看一下两者的比较:

一、易用性:

saltstack负载的文档结构和密集的文字,使得其学习曲线更为陡峭。虽然ansible的文档对初学者而言更简单易读,但随着项目规模的增大,saltstack的文档对开发者的帮助更大。深入分析配置文件(ansible中称为playbooks,saltstack称为stat definitions)突显了二者的区别。Saltstack保持了输入、输出、配置文件的一致性,所有文件均使用YAML格式,而ansible则使用不同的文件格式(INI、YAML)。循环和条件的实现方式也不同。ansible将逻辑部分内嵌在DSL中,而saltstack使用Jinja(一个python模板引擎)。

二、成熟度:

在成熟度方面,ansible和saltstack都能提供所有必要的性能和足够的成熟度。不过saltstack有更丰富的特性:可以以不同的文件格式输出到不同的位置;可以从不同的来源加载pillars(其本质是一种数据结构);如果以代理模式运行,可以通过reactor系统触发本地事件。

三:性能:

性能方面,saltstack速度更快,尤其是在no-change运行模式下:

在相同的应用场景下saltstack的运行速度远远快于ansible。

四、技术支持

在开发社区,saltstack更为友好,开发者数量也更多。

基于以上原因所以才选择saltstack。

1.1.2 saltstack的深入理解

SaltStack采用C/S模式,server端就是salt的master,client端就是minion,minion与master之间通过ZeroMQ消息队列通信minion上线后先与master端联系,把自己的pub key发过去,这时master端通过salt-key –L命令就会看到minion的key,接受该minion-key后,也就是master与minion已经互信master可以发送任何指令让minion执行了,salt有很多可执行模块,比如说cmd模块,在安装minion的时候已经自带了,它们通常位于你的python库中

这些模块是python写成的文件,里面会有好多函数,如cmd.run,当我们执行下图命令的时候

Master下发任务匹配到的minion上去,minion执行模块函数,并返回结果。Master监听4505和4506端口,4505对应的是ZMQ的PUB system,用来发送消息,4506对应的是REP system是来接受消息的。

系统架构图

一个基本的salt配置方式是一个master指挥一群minion,为了不再有假设使用任何单一拓扑结构,另外当minion数量达到2000以上以后salt的执行速度就会降低,在新的saltstack版本中有一个salt-syndic,主控master可以控制一群master,通过syndic将操作命令传输给受控master,受控master来完成对自己旗下minion的管理,并将结果传回主控master,从而实现了主控master对所有minion的间接管理。

目前采用的架构图如下:

1.2 saltstack的特点

  • 基于python开发的C/S架构配置管理工具
  • 底层使用ZeroMQ消息队列pub/sub方式通信
  • 使用SSL证书签发的方式进行认证管理,传输采用AES加密

SaltStack特性

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

1.3 saltstack服务架构

在saltstack架构中服务器端叫Master,客户端叫Minion。

在Master和Minion端都是以守护进程的模式运行,一直监听配置文件里面定义的ret_port(接受minion请求)和publish_port(发布消息)的端口。

当Minion运行时会自动连接到配置文件里面定义的Master地址ret_port端口进行连接认证。

saltstack除了传统的C/S架构外,其实还有一种叫做masterless的架构,其不需要单独安装一台 master 服务器,只需要在每台机器上安装 Minion端,然后采用本机只负责对本机的配置管理机制服务的模式。

SaltStack的结构 saltstack采用C/S(客户端和server端)架构,salt-master为server端,salt-minion为客户端

a)Master与Minion认证 (1)、minion在第一次启动时,会在/etc/salt/pki/minion/(该路径在/etc/salt/minion里面设置)下自动生成minion.pem(private key)和 minion.pub(public key),然后将 minion.pub发送给master。

(2)、master在接收到minion的public key后,通过salt-key命令accept minion public key,这样在master的/etc/salt/pki/master/minions下的将会存放以minion id命名的 public key,然后master就能对minion发送指令了。

b)Master与minion链接 (1)、SaltStack master启动后默认监听4505和4506两个端口。4505(publish_port)为saltstack的消息发布系统,4506(ret_port)为saltstack客户端与服务端通信的端口。如果使用lsof 查看4505端口,会发现所有的minion在4505端口持续保持在ESTABLISHED状态。

1.4 SaltStack通讯机制

SaltStack采用C/S模式,minion与master之间通过**ZeroMQ消息队列【轻量级】**通信,默认监听端口是4505端口

Salt Master运行的第二个网络服务就是**ZeroMQ REP【请求响应】**系统,默认监听4506端口

master端口:4505

minion端口:4506

altStack的master端监听4505和4506端口。其中4505为Salt的消息发布系统,4506为Salt客户端与服务端通信的端口;\ Salt客户端程序不监听端口,客户端启动后,会主动连接master端注册,然后一直保持TCP连接;\ master通过该TCP连接对客户端进行控制,若断开,master也便无法控制客户端,但是当客户端检测到断开后会定期连接master端

1.5 ZeroMQ

ZeroMQ是一种基于消息队列的多线程网络库,其对套接字类型、连接处理、帧、甚至路由的底层细节进行抽象,提供跨越多种传输协议的套接字。

ZeroMQ是网络通信中新的一层,介于应用层和传输层之间,其是一个可伸缩层,可并行运行,分散在分布式系统间

1.6 传统运维与自动化运维区别

1.6.1 传统运维

  • 传统运维效率低下且繁琐,大多工作人工完成,很容易出错
  • 传统运维工作繁琐,很容易出错
  • 传统运维每日重复做相同的事情
  • 传统运维没有标准化的流程
  • 传统运维的脚本繁多,不方便管理

1.6.2 自动化运维

Puppet:基于rubby开放,C/S架构,支持多平台,可管理配置文件、用户、cron任务、软件包、系统服务等。分为社区版和企业版,其中企业版支持图形化配置;【官网:https://puppet.com】\ \ SaltStack:基于Python开发,C/S架构,支持多平台,比Puppet清量,在远程执行命令时非常快捷,配置和使用比puppet容易,能实现puppet几乎所有的功能;【官网:https://saltstack.com】\ \ Ansible:更加简洁的自动化运维工具,不需要在客户端上安装客户端软件,基于Python开发的。可以实现批量操作系统配置、批量程序的部署、批量执行命令。【Ansible中文文档:http://www.ansible.com.cn

1.7 SaltStack四大功能与四大运行方式

SaltStack有四大功能,分别是:

远程执行 配置管理/状态管理 云管理(cloud) 事件驱动

SaltStack可以通过远程执行实现批量管理,并且通过描述状态来达到实现某些功能的目的。

SaltStack四大运行方式

local本地运行 Master/Minion传统方式 Syndic分布式 Salt ssh

二、SaltStack组件介绍

组件 功能
Salt Master 用于将命令和配置发送到在受管系统上运行的Salt minion
Salt Minions 从Salt master接收命令和配置
Execution Modules 从命令行针对一个或多个受管系统执行的临时命令。对…有用: 1. 实时监控,状态和库存 2. 一次性命令和脚本 3. 部署关键更新
Formulas (States) 系统配置的声明性或命令式表示
Grains Grains是有关底层受管系统的静态信息,包括操作系统,内存和许多其他系统属性
Pillar 用户定义的变量。这些安全变量被定义并存储在Salt Master中, 然后使用目标“分配”给一个或多个Minion。 Pillar数据存储诸如端口,文件路径,配置参数和密码之类的值
Top File 将Formulas (States)和Salt Pillar数据与Salt minions匹配
Runners 在Salt master上执行的模块,用于执行支持任务。Salt runners报告作业状态,连接状态,从外部API读取数据,查询连接的Salt minions等
Returners 将Salt minions返回的数据发送到另一个系统,例如数据库。Salt Returners可以在Salt minion或Salt master上运行
Reactor 在SaltStack环境中发生事件时触发反应
Salt Cloud / Salt Virt 在云提供商/虚拟机管理程序上提供系统,并立即将其置于管理之下
Salt SSH 在没有Salt minion的系统上通过SSH运行Salt命令

2.1 SaltStack Master

中央管理系统(服务端):用来发送命令和配置到SaltStack Minion上运行

2.2 SaltStack Minion

接受管理系统(客户端):用来接收来自SaltStack Master命令和配置

2.3 Salt具体步骤

1、SaltStack的master与minion之间通过ZeroMQ来进行消息传递,使用了ZeroMQ的发布-订阅模式,连接方式包括:TCP、IPC。\ 2、Salt命令其中以ls为例。将cmd.run ls命令从salt.client.LocalClient.cmd_cli发布到master,获取一个jobid,根据jobid获取命令执行结果。\ 3、master接收到命令后,将要执行的命令发送给客户端minion。\ 4、minion从消息总线上接收到要处理的命令,交给minion.handle_aes处理。\ 5、minion._handle_aes发起一个本地线程调用cmdmod执行ls命令。线程执行完ls后,调用minion._return_pub方法,将执行结果通过消息总线返回给master。\ 6、master接收到客户端返回的结果,调用master._handle_aes方法,将结果写的文件中。\ 7、salt.client.LocalClient.cmd_cli通过轮询获取Job执行结果,将结果输出到终端。

2.4 saltstack配置文件

saltstack的配置文件在/etc/salt目录

saltstack配置文件说明:

配置文件 说明
/etc/salt/master 主控端(控制端)配置文件
/etc/salt/minion 受控端配置文件

配置文件/etc/salt/master默认的配置就可以很好的工作,故无需修改此配置文件

配置文件/etc/salt/minion常用配置参数

  • master:设置主控端的IP
  • id:设置受控端本机的唯一标识符,可以是ip也可以是主机名或自取某有意义的单词

在日常使用过程中,经常需要调整或修改Master节点的配置文件,SaltStack大部分配置都已经指定了默认值,只需根据自己的实际需求进行修改即可。下面的几个参数是比较重要的

max_open_files:可根据Master将Minion数量进行适当的调整 timeout:可根据Master和Minion的网络状况适当调整 auto_accept和autosign_file:在大规模部署Minion时可设置自动签证 master_tops和所有以external开头的参数:这些参数是SaltStack与外部系统进行整合的相关配置参数

三、SaltStack安装及部署

3.1 环境规划

系统版本: CentOS7.9.2009

主机类型 IP 要安装的应用
控制机 10.0.0.20 salt salt-cloud salt-master salt-minion salt-ssh salt-syndic salt-api
被控机 10.0.0.21 salt-minion
被控机 10.0.0.22 salt-minion

3.2 配置yum仓库

所有节点都要配置

官方中文文档网站:http://docs.saltstack.cn/

官方安装配置教程: http://docs.saltstack.cn/topics/installation/rhel.html

配置YUM仓库【可以使用官网镜像,但较慢,这里我使用阿里云镜像仓库】

  • 配置官网镜像仓库:
yum install -y  https://repo.saltstack.com/yum/redhat/salt-repo-latest.el7.noarch.rpm
或者
yum install -y  https://repo.saltstack.com/py3/redhat/salt-py3-repo-3001.el7.noarch.rpm
  • 配置阿里云镜像仓库:
yum install -y https://mirrors.aliyun.com/saltstack/yum/redhat/salt-repo-latest-2.el7.noarch.rpm
# 补充: 配置Redhat8/CentOS8 仓库
#导入key,配置salt仓库
rpm --import https://repo.saltproject.io/py3/redhat/8/x86_64/latest/SALTSTACK-GPG-KEY.pub
curl -fsSL https://repo.saltproject.io/py3/redhat/8/x86_64/latest.repo | tee /etc/yum.repos.d/salt.repo

# 教程链接 https://mirrors.aliyun.com/saltstack/#rhel

3.3 主控端部署

#清除缓存
[root@master ~]# yum clean expire-cache

# 安装saltstack主控端
[root@master ~]# yum -y install salt salt-cloud salt-master salt-minion salt-ssh salt-syndic salt-api

# 修改主控端的minion配置文件  修改 #id和#master:salt 这两行 (注意书写规范:每个冒号后面都要跟一个空格)
# #master:salt  指向管理端地址,这里是指向salt-master服务器,可以是IP、域名或主机名
# #id           minion主机标识必须唯一
[root@master ~]# sed -i 's/^#master: salt/master: 10.0.0.20/g' /etc/salt/minion   #注意master:后的空格
[root@master ~]# sed -n '/^master:/p'  /etc/salt/minion
master: 10.0.0.20
[root@master ~]# sed -i 's/^#id:/id: master/g'  /etc/salt/minion   #注意id:后的空格
[root@master ~]# sed -n '/^id:/p'  /etc/salt/minion
id: master

# 启动salt-master与salt-minion
[root@master ~]# systemctl enable --now salt-master
[root@master ~]# systemctl enable --now salt-minion

#4505和4506都是salt-master的端口号,4505是publish_port    4506是ret_port
[root@master ~]# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1024/sshd           
tcp        0      0 0.0.0.0:4505            0.0.0.0:*               LISTEN      1286/python3        
tcp        0      0 0.0.0.0:4506            0.0.0.0:*               LISTEN      1298/python3

3.4 被控制端安装、配置salt-minion

所有salt-minion节点都要操作

[root@node1 ~]# yum install -y salt-minion
[root@node1 ~]# sed -i 's/^#master: salt/master: 10.0.0.20/g' /etc/salt/minion   #注意master:后有空格
[root@node1 ~]# sed -n '/^master:/p'  /etc/salt/minion
master: 10.0.0.20
[root@node1 ~]# sed -i 's/^#id:/id: master/g'  /etc/salt/minion   #注意id:后的空格
[root@node1 ~]# sed -n '/^id:/p'  /etc/salt/minion
id: node1
# 启动salt-minion
[root@node1 ~]# systemctl enable --now salt-minion
[root@node1 ~]# systemctl status salt-minion
● salt-minion.service - The Salt Minion
   Loaded: loaded (/usr/lib/systemd/system/salt-minion.service; enabled; vendor preset: disabled)
   Active: active (running) since 三 2021-08-18 09:46:58 CST; 2h 5min ago

# node2 被控端部署同上

3.5 salt-minion与salt-master认证过程

  • minion在第一次启动时,会在/etc/salt/pki/minion/下自动生成一对密钥,然后将公钥发给master
  • master收到minion的公钥后,通过salt-key命令接受该公钥。此时master的/etc/salt/pki/master/minions目录将会存放以minion id命名的公钥,然后master就能对minion发送控制指令了

master 秘钥对默认存储在/etc/salt/pki/master/master.pub /etc/salt/pki/master/master.pem master 端认证的公钥存储在:/etc/salt/pki/master/minions/ minion 秘钥对默认存储在/etc/salt/pki/minion/minion.pub /etc/salt/pki/minion/minion.pem minion 存放的master公钥/etc/salt/pki/minion/minion_master.pub minion_id 默认存储在/etc/salt/minion_id\ \若想修改minion名称,需删除原来的minion_id,重启重新生成一个minion_id**

# salt-key常用选项
    -L             列出所有公钥信息
    -a minion      接受指定minion等待认证的key
    -A             接受所有minion等待认证的key
    -r minion      拒绝指定minion等待认证的key
    -R             拒绝所有minion等待认证的key
    -f minion      显示指定key的指纹信息
    -F             显示所有key的指纹信息
    -d minion      删除指定minion的key
    -D             删除所有minion的key
    -y             自动回答yes

# 查看当前证书情况
[root@master ~]# salt-key  -L
Accepted Keys:
Denied Keys:
Unaccepted Keys:
master
node1
node2
Rejected Keys:

# 接受指定minion的新证书
[root@master ~]# salt-key -a -y 'master'
The following keys are going to be accepted:
Unaccepted Keys:
master
Key for minion master accepted.

# 接受所有minion的新证书
[root@master ~]# salt-key -y -A
The following keys are going to be accepted:
Unaccepted Keys:
node1
node2
Key for minion minion accepted.
[root@master ~]# salt-key -L
Accepted Keys:
master
node1
node2
Denied Keys:
Unaccepted Keys:
Rejected Keys:

3.6 测试saltstack远程执行

# 测试所有受控端主机是否存活
# '*'表示所有目标机器 test.ping 只是模块里的一个功能,用来测试连通性
[root@master ~]# salt "*" test.ping  
node1:
    True
node2:
    True
master:
    True

# 测试指定受控端主机是否存活
[root@master ~]# salt "node1" test.ping
node1:
    True

# 万能模块cmd.run 执行命令
[root@master ~]# salt 'node1' cmd.run 'hostname'
node1:
    node1
# salt '*' cmd.run 'uptime'
# salt '*' cmd.run 'w'


命令: salt 
目标: '*' 
模块: cmd.run 
返回: 执行后返回结果 Returnners

3.7 salt命令使用

# 语法:salt [options] '<target>' <function> [arguments]
# Salt命令主要由三个主要部分构成:salt '<target>' <function> [arguments]   

target:指定哪些minion,默认的规则是使用glob匹配minion id        # salt '*' test.ping
Targets也可以使用正则表达式        # salt -E 'server[1-3]' test.ping

Targets也可以指定列表              # salt -L 'server2,server3' test.ping

funcation:module提供的功能,Salt内置了大量有效的functions

arguments:通过空格来界定参数


# 常用的options
    --version             查看saltstack的版本号
    --versions-report     查看saltstack以及依赖包的版本号
    -h       查看帮助信息
    -c CONFIG_DIR         指定配置文件目录(默认为/etc/salt/)
    -t TIMEOUT            指定超时时间(默认是5s)
    --async     异步执行
    -v      verbose模式,详细显示执行过程
    --username=USERNAME      指定外部认证用户名
    --password=PASSWORD      指定外部认证密码
    --log-file=LOG_FILE      指定日志记录文件

# 常用target参数
    -E       正则匹配
    -L       列表匹配 
    -S       CIDR匹配网段
    -G       grains匹配
    --grain-pcre     grains加正则匹配
    -N       组匹配
    -R       范围匹配
    -C       综合匹配(指定多个匹配)
    -I       pillar值匹配

# 示例
[root@master ~]# salt -E 'master*' test.ping
master:
    True

[root@master ~]# salt -L master,node1 test.ping 
node1:
    True
master:
    True

[root@master ~]# salt -S '10.0.0.21' test.ping
node1:
    True

[root@master ~]# salt -S '10.0.0.0/8' test.ping
master:
    True
node1:
    True
node2:
    True


# 【 匹配minion主机  与minion ID有关】
   1 通配符
      salt '*' test.ping
      salt 'node*' test.ping

   2 主机ID
      salt 'node1' test.ping
      salt -L 'master,node1,node2' test.ping

   3 正则表达式
      salt 'node[1|2]' test.ping
      salt 'node[1-2]' test.ping
      salt 'node[!2]' test.ping
      salt -E 'node1|node2' test.ping
      salt -E 'node(1|2)' test.ping

# 【与minion ID无关,通过grains或者pillar匹配目标主机】

常用命令如下:

# 1.测试连通
salt '*' test.ping
# '*'表示所有目标机器 test.ping 只是模块里的一个功能,用来测试连通性

# 2.常用命令结构
salt [options] ‘<目标机><功能> [arguments]

# 例如:
#对机器node1使用w命令
test 'node1' cmd.run 'w'

# 3.常用命令
# salt-run
# 该命令执行runner(salt带的或者自定义的,runner以后会讲),通常在master端执行,比如经常用到的manage
salt-run [options] [runner.func]
salt-run manage.status   ##查看所有minion状态
salt-run manage.down     ##查看所有没在线minion
salt-run manged.up       ##查看所有在线minion

# 4 安装软件
salt 'node1' pkg.install httpd
# 卸载软件
salt 'node1' pkg.remove httpd

# 5 测试
salt '*' test.echo 'hello'
salt '*' network.ping baidu.com        # 使用ping命令测试到某主机的连通性
salt '*' network.connect baidu.com 80  # #测试minion至某一台服务器的网络是否连通
salt '*' network.get_hostname  # 获取主机名
salt '*' network.active_tcp    # 返回所有活动的tcp连接
salt '*' network.ip_addrs      # 返回一个IPv4的地址列表
alt '*' network.get_fqdn       # 查看主机的fqdn(完全限定域名)

# salt-key
# 密钥管理,通常在master端执行
salt-key [options]
salt-key -L              ##查看所有minion-key
salt-key -a <key-name>   ##接受某个minion-key
salt-key -d <key-name>   ##删除某个minion-key
salt-key -A              ##接受所有的minion-key
salt-key -D              ##删除所有的minion-key

# salt-call
# 该命令通常在minion上执行,minion自己执行可执行模块,不是通过master下发job
salt-call [options] <function> [arguments]
salt-call test.ping           ##自己执行test.ping命令
salt-call cmd.run 'ifconfig'  ##自己执行cmd.run函数

# salt-cp
# 分发文件到minion上,不支持目录分发,通常在master运行
salt-cp [options] '<target>' SOURCE DEST
salt-cp '*' testfile.html /tmp
salt-cp 'node*' /opt/index.html /tmp/a.html

# 常用模块命令
salt '*' network.active_tcp      # 查看tcp连接情况
salt '*' network.get_hostname    # 查看主机名
salt '*' service.available sshd  # 查看ssh服务是否可达
salt '*' service.get_all         # 查看所有启动的服务
salt '*' service.status nginx    # 查看指定服务是否在线
salt '*' state.show_top          # 查看top_file情况
salt '*' state.single pkg.installed name=lsof  # 安装lsof

# 查看模块文档
salt '*' sys.doc pkg           #查看pkg模块文档 

# salt内置的执行模块列表
http://docs.saltstack.cn/ref/modules/all/index.html

四、state.sls介绍及使用

state.sls SLS(代表SaLt State文件)是Salt State系统的核心。SLS描述了系统的目标状态,由格式简单的数据构成。这经常被称作配置管理。首先,在master上面定义salt的主目录,默认是在/srv/salt/下面。

sls文件命名:

sls文件以”.sls”后缀结尾,但在调用时是不需要写后缀的。
使用子目录来做组织是个很好的选择。  
init.sls 在一个子目录里面表示引导文件,也就表示子目录本身, 所以``apache/init.sls`` 就是表示``apache``. 如果同时存在apache.sls 和 apache/init.sls,则 apache/init.sls 被忽略,apache.sls将被用来表示apache.
# 编辑master节点配置文件  vim  /etc/salt/master   
# 修改配置如下  注意空格缩进
file_roots:
  base:
    - /srv/salt
# 重启salt-master
systemctl restart salt-master

# 创建目录
mkdir -p /srv/salt

# cd /srv/salt/

4.1 yaml语法

由于SaltStack也是用python编写,默认的SLS文件的renderer是YAML rendere,因此也要使用yaml语法。

YAML是一个由很多强大特性的标记性语言。Salt使用了一个YAML的小型子集,用来映射常用的数据结构,像列表和字典。YAML renderer的工作就是将YAML数据格式的结构编译成为Python数据结构给Salt使用。

掌握三个规则即可使用YAML语法书写SLS文件

4.1.1 三个规则

  • 规则一:缩进

YAML使用一个固定的缩进风格表示数据结构的层结构关系。Salt需要每个缩进级别由 两个空格 组成,若要使用Tab,先修改.vimrc来设置Tab的缩进格数。

  • 规则二:冒号

Python的字典当然理所当然是简单的键值对。其他语言的用户应该知道这个数据类型叫哈希表或者关联数组。 字典的keys在YAML中的表现形式是一个以冒号结尾的字符串。Values的表现形式冒号下面的每一行,用一个空格隔开:\ my_key: my_value 在Python中,上面的将映射为: {'my_key': 'my_value'}\ 注解: 上面的语法是有效的YAML,但是在SLS文件罕见,因为通常情况下,一个key的value不是单一的,而是一个 列表 的values。 在Python中,上面的将映射为:{'my_key': 'my_value'} 字典可以被嵌套: first_level_dict_key: second_level_dict_key: value_in_second_level_dict 在Python中: { 'first_level_dict_key': { 'second_level_dict_key': 'value_in_second_level_dict' } }

  • 规则三:短横杠

表示列表项:一个短横杠加一个空格,多项则使用同样缩进级别来作为同一列表的一部分

- list_value_one
- list_value_two

做键值对的value

my_dictionary:
  - list_value_one
  - list_value_two

在Python中,上面的映射关系可以书写为:

{'my_dictionary': ['list_value_one', 'list_value_two']}

4.2 编写sls文件

# 切换目录
# cd /srv/salt

常用模块

4.2.1 用户管理

# 1 添加用户  vim create_user.sls
# 创建用户
add-test-user:     # 项目id,最好能见名知意,--推荐此方式写sls文件,让ID声明有意义
  user.present:    # 模块和方法
    - name: test   # 用户名
    - home: /home/test   # 用户的家目录
    - shell: /bin/bash   # 指定用的shell
    - uid: 1001          # 用户UID
    - gid: 1001          # 用户组GID

# 写法二
test:     # 这里项目id就是用户名
  user.present:    # 模块和方法
    - home: /home/test   # 用户的家目录
    - shell: /bin/bash   # 指定用的shell
    - uid: 1001          # 用户UID
    - gid: 1001          # 用户组GID

# 命令行  salt '*' user.add name <uid> <gid> <groups> <home> <shell>
# 执行远程命令
[root@master /srv/salt]# salt 'node1' state.sls create_user
node1:
----------
          ID: add-test-user
    Function: user.present
        Name: test
      Result: True
     Comment: New user test created
     Started: 16:04:58.123286
    Duration: 257.96 ms
     Changes:   
              ----------
              fullname:
              gid:
                  1001
              groups:
                  - test
              home:
                  /home/test
              homephone:
              name:
                  test
              other:
              passwd:
                  x
              roomnumber:
              shell:
                  /bin/bash
              uid:
                  1001
              workphone:

Summary for node3
------------
Succeeded: 1 (changed=1)
Failed:    0
------------
Total states run:     1
Total run time: 257.960 ms
# 2 删除用户 vim delete_user.sls
del_test:
  user.absent:
  - name: test
  - purge: True 
  - force: True
#purge类似userdel -r force为用户在线也强制删除
[root@master /srv/salt 16:20:14]# salt 'node1' state.sls del_user
node1:
----------
          ID: del_test
    Function: user.absent
        Name: test
      Result: True
     Comment: Removed user test
     Started: 16:20:30.003342
    Duration: 103.256 ms
     Changes:   
              ----------
              test:
                  removed
              test group:
                  removed

Summary for node3
------------
Succeeded: 1 (changed=1)
Failed:    0
------------
Total states run:     1
Total run time: 103.256 ms
# 查看user模块文档  salt '*' sys.doc user

4.2.2 包管理

# yum安装包  vim install_nginx.sls
# 安装单个包  方式1
nginx:           # ID声明就是安装包的名称
  pkg.installed  # 状态声明
# 安装单个包  方式2
install-only-nginx:   # ID声明
  pkg.installed:      # 状态声明
    - name: nginx     # 选项声明
salt 'node1' state.sls install_nginx
# 安装多个包 vim lnmp.sls
# 安装多个包   方式1
lnmp_config:
  pkg.installed:
    - pkgs:
      - nginx
      - mariadb
      - mariadb-server
      - python3
# 安装多个包  # 方式2 
lnmp_config:
  pkg.installed:
    - names:
      - nginx
      - mariadb
      - mariadb-server
      - python3
salt 'node3' state.sls lnmp

4.2.3 服务状态管理

# 启动服务 设置开机启动
# vim start-nginx.sls
nginx:
  pkg.installed

start-nginx:
  service.running:
    - name: nginx
    # 设置开机启动
    - enable: True
    # 设置重新载入,当文件发生变化时,如果不设置reload,则会重启
    - reload: True
    # 监控服务是否安装
    - watch:
      - pkg: nginx
salt 'node1' state.sls start_nginx
# 示例2 安装多个服务并同时启动
# vim more-services.sls
install-services:
  pkg.installed:
    - pkgs:
      - nginx
      - mariadb
      - mariadb-server
      - redis

start-services:
  service.running:
    - names: 
      - nginx
      - mariadb
      - redis
    # 设置开机启动
    - enable: True
    # 设置重新载入,当文件发生变化时,如果不设置reload,则会重启
    - reload: True
    # 监控服务是否安装
    - watch:
      - pkg: install-services

4.2.4 目录管理

# 创建目录   vim  createdir.sls
create_testdir:
  file.directory:
    - name: /opt/salt_test
    - user: root
    - group: root
    - file_mode: 644
    - dir_mode: 755
    - makedirs: True
    - include_empty: True
    - backup: minion
salt 'node1' state.sls createdir

4.2.5 逻辑关系

在/srv/salt/目录下创建webs目录
将前面创建的sls文件移动到webs目录中
webs/
├── append_java_config.sls
├── createdir.sls
├── create_user.sls
├── del_user.sls
├── install_nginx.sls
├── lnmp.sls
└── manage_nginx_conf.sls
# 1 继承(include)   vim test_include.sls
include:
    # 目录名.sls文件名(不带后缀)
  - webs.install_nginx
  - webs.createdir
  - webs.lnmp
  - webs.manage_nginx_conf
# include应用场景说明,例如部署lnmp/lamp时,把初始化系统,安装软件,修改配置等环节标准化,做成初始化系统模块,安装软件模块等,实现在其它项目中复用,这样就不用每次部署新环境时都要写重复sls文件内容
salt 'node1' state.sls test_include
# 2 依赖(require)   依赖某个state,在运行此state前,先运行依赖的state,依赖可以有多个
# vim test_require.sls
test_require:
  pkg.installed:
    - pkgs:
      - nginx
      - mariadb
      - mariadb-server
      - python3

setconfigfiles:
  file.managed:
    - name: /opt/nginx.conf
    - source: salt://files/nginx.conf
    - user: root
    - group: root
    - mode: 644
    - backup: minion
    - template: jinja
    #  定义jinja模板引用的变量
    - defaults:
        port: 90
        worker_connections: 10241
        # 依赖nginx安装成功
    - require:
      - test_require
salt 'node1' state.sls test_require
# 3 监控(watch) 在某个state变化时运行此模块,文中的配置,相关文件变化后,立即执行相应操作
# vim test_watch.sls
install_lnmp:
  pkg.installed:
    - pkgs:
      - nginx
      - mariadb
      - mariadb-server
      - python3

setconfigfiles:
  file.managed:
    - name: /opt/nginx.conf
    - source: salt://files/nginx.conf
    - user: root
    - group: root
    - mode: 644
    - backup: minion
    - template: jinja
    #  定义jinja模板引用的变量
    - defaults:
        port: 90
        worker_connections: 10241
        # 依赖nginx安装成功
    - require:
      - install_lnmp

show_files:
  cmd.run:
    - name: cat /opt/nginx.conf
    - watch:
      - pkg: install_lnmp
      - file: setconfigfiles
salt 'node1' state.sls test_watch
# 4 顺序/优先级(order)
优先级比require和watch低,有order指定的state比没有order指定的优先级高,假如一个state模块内安装多个服务,或者其他依赖关系,可以使用。如果想让某个state最后执行,可以使用last。
# vim test_order.sls
nginx:
  pkg.installed:
    - order: 4

install-mariadb:
  pkg.installed:
    - order: 3
    - pkgs:
      - mariadb
      - mariadb-server

lsof:
  pkg.installed:
    - order: 1

nginx-conf:
  file.managed:
    - order: 2
    - name: /opt/nginx.conf
    - source: salt://files/nginx.conf
    - user: root
    - group: root
    - mode: 644
    - template: jinja
    - backup: minion
    - defaults:
        port: 90
        worker_connections: 10241      

python3:
  pkg.installed:
    - order: last
salt 'node1' state.sls test_order

# 说明,个人感觉优先级基本没啥用,只有极少数的情况能用到

4.2.6 文件管理

# 上传文件到一个目录  vim  manage_nginx_conf.sls
nginxconf:
  file.managed:
    - name: /opt/nginx.conf
    # salt:// 当前环境的根目录
    - source: salt://files/nginx.conf
    - user: root
    - group: root
    - mode: 644
# 执行命令应用
salt 'node1' state.sls manage_nginx_conf
# 本例使用了jinja模板及定义变量
nginxconf:
  file.managed:
    - name: /opt/nginx.conf
    # salt:// 当前环境的根目录
    - source: salt://files/nginx.conf
    - user: root
    - group: root
    - mode: 644
    - backup: minion
    - template: jinja
    #  定义jinja模板引用的变量
    - defaults:
        port: 80
        worker_connections: 10240

# nginx.conf文件修改
events {
    # worker_connections 1024; 修改为:
    worker_connections {{ worker_connections }};
}
 server {
        # listen       80;  # 修改为:
        listen       {{ port }};
salt 'node1' state.sls manage_nginx_conf
# 上传文件到多个目录
vim upload_more.sls
upload-file:
  file.managed:
    - names: 
      - /etc/hosts
      - /tmp/hosts
    # salt:// 当前环境的根目录
    - source: salt://conf/hosts
    - user: root
    - group: root
    - mode: 644
# 上传文件前检查特定文件是否存在,同时检查依赖
# vim test_upload_and_require.sls
yum_epel_release:
 pkg.installed:
   # 通过URL安装包
   - sources:
     - epel-release: https://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm

/etc/hosts:
  file.managed:
    # salt:// 当前环境的根目录
    - source: salt://conf/hosts
    - backup: minion
    - user: root
    - group: root
    - mode: 644
    # 检查/etc/hosts文件是否存在,结果为false才会执行
    - unless: test -f /etc/hosts
    # 检查依赖的服务是否已安装
    - require:
      - pkg: yum_epel_release

追加文件内容

# 追加配置示例1  vim  append_java_config.sls
append_config:
  file.append:
    # 追加配置的文件名
    - name: /etc/profile
    # 需要追加的内容
    - text:
        - "export  JAVA_HOME=/usr/local/java8"
        - "export  PATH=$JAVA_HOME/bin:$PATH"
salt 'node1' state.sls append_java_config

扩展示例

# 优化系统配置 示例2
# 给历史记录加时间和执行用户
/etc/profile:
  file.append:
    - text:
      - export HISTTIMEFORMAT="%F %T `whoami` "
# 优化内核配置 示例3
# 优化内核参数
# ipv4连接对外服务端口范围
net.ipv4.ip_local_port_range:
  sysctl.present:
    - value: 10000 65000
# 最大打开文件数量 
fs.file-max:
  sysctl.present:
    - value: 2000000

# 开启ipv4转发
net.ipv4.ip_forward:
  sysctl.present:
    - value: 1

# 不适用交换分区
vm.swappiness:
  sysctl.present:
    - value: 0
# sls文件中使用变量 示例4
# vim  user_vars.sls
# 定义变量
{% set web1 = "nginx" %}
{% set database1 = "mariadb" %}
{% set database2 = "mariadb-server" %}
{% set database3 = "redis" %}
{% set conf1 = "salt://conf/nginx.conf" %}

install-services:
  pkg.installed:
    - pkgs:
      # 引用变量
      - {{ web1 }}
      - {{ database1 }}
      - {{ database2 }}
      - {{ database3 }}

cpoy-nginx-conf:
  file.managed:
    - name: /etc/nginx/nginx.conf
    - source: {{ conf1 }}
    - backup: minion
    - user: nginx
    - group: nginx
    - mode: 644
    - template: jinja
    # 定义金甲模板中需要的变量
    - defaults:
        port: 8090
        worker_connections: 10249       
    # 需要的依赖
    - require: 
      - pkg: install-services

start-services:
  service.running:
    - names:
      - nginx
      - mariadb
      - redis
    - enable: True
    - reload: True
    - require:
      - file: cpoy-nginx-conf
      - pkg: install-services
# 开启测试  测试是否有语法问题或者错误
salt 'node1' state.sls usr_vars test=True
# 测试无误后再执行
salt 'node1' state.sls usr_vars

4.2.7 批量执行

准备Top文件

# top.sls必须在/etc/salt/mater文件中定义的salt根路径中 如下配置
file_roots:
  base:
    - /srv/salt/

# 创建并编辑top.sls
vim /srv/salt/top.sls
base:
  # base环境下的所有主机都执行
  '*':
    - webs.usr_vars

  # 指定node1执行
  'node1':
    - webs.lnmp
    - webs.create_user
    - webs.del_user

# 本例只配置了base环境,实际生产环境应加上类似于下面的配置
###################################
devp:
  # devp环境下的所有主机都执行
  '*':
    - webs.usr_vars
prod:
  # prod环境下的所有主机都执行
  '*':
    - webs.usr_vars
test:
  # test环境下的所有主机都执行
  '*':
    - webs.usr_vars
webs/
├── append_java_config.sls
├── createdir.sls
├── create_user.sls
├── del_user.sls
├── install_nginx.sls
├── lnmp.sls
├── manage_nginx_conf.sls
├── start_nginx.sls
├── test_file_and_require.sls
├── test_include.sls
├── test_order.sls
├── test_require.sls
├── test_watch.sls
└── usr_vars.sls
# 测试top.sls
salt 'node*' state.highstate test=True
# 执行
salt 'node*' state.highstate

以上是通过saltstack内置模块实现用户管理,文件管理,软件安装等操作,介绍的 比较简单,详细了解需要看官方文档

官方文档地址: http://docs.saltstack.cn/

下面介绍自定义模块

五、saltstack自定义模块

# master节点
# 确保master配置文件/etc/salt/master中的base环境已开启
file_roots:
  base:
    - /srv/salt
# 重启 systemctl restart salt-master   # 本例前面已经配置过
# 切换目录
cd /srv/salt
# 创建文件夹
mkdir _modules   # 名字必须是_modules,官方规定的
# 进入_modules目录
cd _modules

# 开始编写python文件,因为saltstack是python开发的,所以自定义的模块文件必须.py结尾的python文件
# 示例1   mymodules.py
def  w():
    shellcmd = "w"
    return __salt__['cmd.run'](shellcmd)

def df():
    shellcmd = "df -hT"
    return __salt__['cmd.run'](shellcmd)

def top():
    shellcmd = "top"
    return __salt__['cmd.run'](shellcmd)

def ls():
    shellcmd = "ls /"
    return __salt__['cmd.run'](shellcmd)

def hostname():
    shellcmd = "hostname"
    return __salt__['cmd.run'](shellcmd)

def install_nginx():
    shellcmd = "yum install -y nginx"
    return __salt__['cmd.run'](shellcmd)

def start_nginx():
    shellcmd = "nginx"
    return __salt__['cmd.run'](shellcmd)
# 同步模块到所有节点,也可以同步到某个节点
salt '*'  saltutil.sync_modules

####如果自定义模块文档发生变化,必须先同步然后再执行,否则执行的还是修改之前的内容####
# 调用模块
# 语法格式
# salt 命令  '*' 目标主机(这里是全部主机)  mymodules上面.py文件名  w 函数名

salt '*' mymodules.w
salt 'node1' mymodules.df 
salt 'node1' mymodules.hostname
salt 'node1' mymodules.install_nginx
salt 'node1' mymodules.start_nginx

六、grains与pillar

6.1 grains

6.1.1 grains简介

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

当salt-minion启动时会把收集到的数据静态存放在Grains当中,只有当minion重启时才会进行数据的更新。由于grains是静态数据,因此不推荐经常修改~

Salt提供了一个接口来获取有关底层系统的信息。这被称为grains接口,因为它向salt呈现了信息的颗粒。收集操作系统、域名、IP地址、内核、操作系统类型、内存和许多其他系统属性的粒度。 grains接口可用于Salt模块和组件,以便在正确的系统上自动使用正确的Salt minion命令。 grains数据是相对静态的,但是如果系统信息发生变化(例如,网络设置更改),或者如果为自定义grains指定了新值,则需要将grains数据刷新。 注意 Grains解析为小写字母。例如,FOO和foo的目标是相同的颗粒。

应用场景:

  • 信息查询,可用作CMDB
  • 在target中使用,匹配minion
  • 在state系统中使用,配置管理模块

6.1.2 信息查询

用于查询minion端的IP、FQDN等信息

  • 默认可用的grains
salt '*' grains.ls              # 获取所有grains的key-只显示key
salt '*' grains.items           # 获取所有的grains键值对 key:value
salt '*' grains.item osrelease  # 获取某个grain
salt '*' grains.item username
salt '*' grains.item fqdn_ip4 
salt '*' grains.item os

salt '*' saltutil.sync_grains   # 同步grains配置到所有minion-此命令可无需重启salt-minion刷新grains数据
salt 'node1' grains.list  列出node1所有的静态数据键
salt 'node1' grains.items 列出node1所有的静态数据键与值
salt '*' grains.item os   列出所有机器的os

-G 用于对匹配到的进行操作 (目标选择)
# -G使用grains匹配目标
salt -G 'os:CentOS' cmd.run 'echo "hello world"'

# 自定义grains的3种方式
# 1.直接在/etc/salt/minion中定义---【node节点操作】
grains:
   roles:
      - webserver
      - python3
# salt '*' saltutil.sync_grains  同步grains
# salt -G 'roles:python3' cmd.run 'echo "hello world"'

# ------------------------------------------------------

# 2./etc/salt/grains---【node节点操作】
# vim /etc/salt/grains
webhost: nginx
database1: mariadb
database2: mariadb-server
database3: redis
dev-tools: python3
# salt '*' saltutil.sync_grains  同步grains
# salt -G 'webhost:nginx' cmd.run 'echo "hello world"'
# salt -G 'dev-tools:python3' cmd.run 'echo "hello world"'

# -----------------------------------------------------

# 开发grains 即自定义grains---【master节点操作】
# 3.用python 写一个python脚本,返回一个字典就可以了
# 在 /srv/salt/ 下创建一个 _grains 的目录,然后在目录中创建一个.py文件
#!/usr/bin/python3
def  my_grains():
     mygrains = {"webmaster": "nginx", "web-slave": "httpd"}
     mygrains['database'] = "mysql"
     mygrains['cache'] = "redis"
     mygrains['devp-tool'] = 'python3'
     return mygrains

# salt '*' saltutil.sync_grains   同步grains
# salt '*' grains.items           # 查看所有grains
# salt '*' grains.item webmaster  # 查看指定grain
# salt -G 'webmaster:nginx' cmd.run 'echo "hello world"'   # 引用grains选择目标


# grains的优先级
1.系统自带
2.grains文件写的
3.minion配置文件写的
4.自己写的

# 每次修改数据都需要重启服务或刷新grains操作才会生效,这也印证了是静态数据
# 命令 salt ‘*’ saltutil.sync_grains 用于刷新grains的数据

6.1.3 grains匹配运用

6.1.3.1 在target中匹配minion

# 在前面实验的基础上执行以下命令
salt -G 'os:CentOS' cmd.run 'echo "hello world"'
salt -G 'webhost:nginx' cmd.run 'echo "hello world"'
salt -G 'dev-tools:python3' cmd.run 'echo "hello world"'

6.1.3.2 在top.sls文件中匹配

vim /srv/salt/top.sls
base:
  '*':
    - webs.install_nginx

  'webhost:nginx':
      # 根据grains匹配
    - match: grain
    - webs.install_nginx
salt '*' state.highstate test=True  # 测试
salt '*' state.highstate  # 执行

6.2 pillar

6.2.1 pillar简介

  • pillar和grains一样也是一个数据系统,两个区别是应用场景不同
  • pillar是将信息动态的存放在master端,主要存放私密、敏感信息(如用户名密码等),而且可以指定某一个minion才可以看到对应的信息
  • pillar更加适合在配置管理中运用

Pillar在salt中是非常重要的组成部分,利用它可以完成很强大的功能,它可以指定一些信息到指定的minion上。不像grains一样是分发到所有Minion上的,它保存的数据可以是动态的。Pillar以sls来写的,格式是键值对。

6.2.2 适用情景:

  • 1.比较敏感的数据,比如密码,key等
  • 2.特殊数据到特定Minion上
  • 3.动态的内容
  • 4.其他数据类型

6.2.3 pillar示例

# 1  查看Minion的Pillar信息
salt '*' pillar.items

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

# 3 编写pillar数据
# 指定pillar_roots,默认是/srv/pillar(可通过修改master配置文件修改),建立目录
# 开启pillar_roots
# vim /etc/salt/master
pillar_roots:
  base:
    - /srv/pillar
# 修改配置后重启服务 systemctl restart salt-master

# 4 创建目录
mkdir /srv/pillar
cd /srv/pillar

# 5 编辑一个pillar数据文件
# vim test_pillar.sls
name: 'salt'
 users:
   hadoop: 1010
   redhat: 1011
   ubuntu: 1012

# 6 建立top file指定minion到pillar数据文件
# vim /srv/pillar/top.sls
 base:
   '*':
     - test_pillar

# 7 刷新pillar数据
salt '*' saltutil.refresh_pillar

#测试是否生效
salt '*' pillar.get name
salt '*' pillar.item name


# 8 在state中通过jinja使用pillar数据
# vim /srv/salt/users.sls
 {% for user,uid in pillar.get('users', {}).items() %}
 {{user}}:
   user.present:
     - uid: {{uid}}
 {% endfor %}

# salt '*' state.sls users test=True


# 9 通过jinja模板配合grains指定pillar数据
# vim /srv/pillar/pkgs.sls 
pkgs:
  {% if grains['os_family'] == 'RedHat' %}
  database: mariadb
  database-server: mariadb-server
  vim: vim
  {% elif grains['os_family'] == 'Debian' %}
  database: mysql
  vim: vim
  {% elif grains['os'] == 'CentOS' %}
  database: mariadb-server
  database-server: mariadb-server
  vim: vim
  {% endif %} 

 # 更新/srv/pillar/top.sls
  base:
   '*':
     - test_pillar
   'node2':
     - pkgs
# 10 刷新pillar数据
salt '*' saltutil.refresh_pillar

#测试是否生效
salt '*' pillar.get database
salt '*' pillar.item database 

# 11 目标选择测试
salt -I 'database:mariadb' test.ping

# 12 调用pillar数据
# vim /srv/salt/database.sls
install-database:
  pkg.installed:
    # 使用pillar选择目标数据
    - names: 
      - {{ pillar['pkgs']['database'] }}
      - {{ pillar['pkgs']['database-server'] }}

# 使用pillar选择目标主机执行
salt  -I 'pkgs:database:mariadb' state.sls database test=True
salt  -I 'pkgs:database:mariadb' state.sls database

七、jinja模板

7.1 Jinja模板简介

  • Jinja是一种基于python的模板引擎,在SLS文件里可以直接使用jinja模板来做一些操作。 通过jinja模板可以为不同服务器定义各自的变量。

7.2 Jinja模板使用方式

7.2.1 控制结构包装条件

# vim /srv/salt/testjinjia.sls
install-pkgs:
  pkg.installed:
    - pkgs:
      {% if grains['fqdn'] == 'node1' %}
      - soft: nginx
      - database1: mariadb
      - database2: mariadb-server
      {% elif grains['fqdn'] == 'node2' %}
      - soft: wget
      - websrv: net-tools
      - database1: redis
      {% else %}
      - soft: tree
      {% endif %}
salt '*' state.sls testjinja test=True
salt '*' state.sls testjinja

7.2.2 Jinja在普通文件的使用

  • 复制一份nginx配置文件到salt目录files下
cp /etc/nginx/nginx.conf  /srv/salt/files
  • 修改模板文件(引用变量port)
server {
        listen       {{ port }}; # 修改80
# vim  test_jinjia2.sls
nginx-conf-copy:
  file.managed:
    - name: /opt/nginx.conf
    - source: salt://files/nginx.conf
    - user: root
    - group: root
    - mode: 644
    - backup: millon
    - template: jinja
    # 定义jinja模板中引用的变量
    - defaults:
      port: 81
salt '*' state.sls test_jinjia2  test=True
salt '*' state.sls test_jinjia2

7.2.3 import方式,可在state文件之间共享

  • 定义变量文件
# vim /srv/salt/vars.sls
{% set port = 81 %}
{% set worker_connections = 20480 %}
  • 导入
# vim /srv/salt/files/nginx.conf
{# 写在文件顶部 #} 
{% from '../vars.sls' import port %}
{% from '../vars.sls' import worker_connections %}

此时注意:

nginx-conf-copy:
  file.managed:
    - name: /opt/nginx.conf
    - source: salt://files/nginx.conf
    - user: root
    - group: root
    - mode: 644
    - backup: millon
    # 因为jinja模板文件已经引入变量文件,这里配置必须删除或者注释掉,否则会冲突
    # - template: jinja
    # 定义jinja模板中引用的变量
    # - defaults:
      # port: 81
      # worker_connections: 20480
salt 'node3' state.sls test_jinjia2 test=True
salt 'node3' state.sls test_jinjia2

八、Job管理

8.1 Job简介

  • master在下发指令任务时,会附带上产生的jid
  • minion在接收到指令开始执行时,会在本地的/var/cache/salt/minion/proc目录下产生该jid命名的文件,用于在执行过程中master查看当前任务的执行情况
  • 指令执行完毕将结果传送给master后,删除该临时文件

8.2 Job cache

Job缓存默认保存24小时

vim /etc/salt/master
#keep_jobs: 24

master端Job缓存目录:/var/cache/salt/master/jobs

[root@master /srv/salt ]# ls /var/cache/salt/master/jobs
00  09  11  18  1f  28  2e  39  3f  48  4e  56  5b  66  6b  74  7a

8.3 Job持久化(存储到数据库)

可以从master存储到数据库也可以从minion存储,这里我们选择从master端存储

官方文档:http://docs.saltstack.cn/ref/returners/all/index.html

配置mysql作为返回器: http://docs.saltstack.cn/ref/returners/all/salt.returners.mysql.html#module-salt.returners.mysql

修改master端配置

vim /etc/salt/master
# 增加如下配置
master_job_cache: mysql
mysql.host: 'localhost'
mysql.user: 'salt'
mysql.pass: 'salt'
mysql.db: 'salt'
mysql.port: 3306
# 需要安装并配置mysql

重启salt-master服务

systemctl restart salt-master

安装数据库以及相关插件

yum install -y mariadb mariadb-server MySQL-python python36-mysql.x86_64
# MySQL-python  python36-mysql插件必须安装,否则salt无法与mysql通信

启动数据库

systemctl start mariadb
# 这里为了方便未对数据库初始化

# 如需设置mysql密码等初始化配置使用如下命令:
#  mysql_secure_installation

创建sql模板

# vim /srv/salt/returner-mysql.sql
CREATE DATABASE IF NOT EXISTS `salt`
  DEFAULT CHARACTER SET utf8
  DEFAULT COLLATE utf8_general_ci;

USE `salt`;

--
-- Table structure for table `jids`
--

DROP TABLE IF EXISTS `jids`;
CREATE TABLE `jids` (
  `jid` varchar(255) NOT NULL,
  `load` mediumtext NOT NULL,
  UNIQUE KEY `jid` (`jid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- CREATE INDEX jid ON jids(jid) USING BTREE;
--
-- Table structure for table `salt_returns`
--

DROP TABLE IF EXISTS `salt_returns`;
CREATE TABLE `salt_returns` (
  `fun` varchar(50) NOT NULL,
  `jid` varchar(255) NOT NULL,
  `return` mediumtext NOT NULL,
  `id` varchar(255) NOT NULL,
  `success` varchar(10) NOT NULL,
  `full_ret` mediumtext NOT NULL,
  `alter_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  KEY `id` (`id`),
  KEY `jid` (`jid`),
  KEY `fun` (`fun`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Table structure for table `salt_events`
--

DROP TABLE IF EXISTS `salt_events`;
CREATE TABLE `salt_events` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`tag` varchar(255) NOT NULL,
`data` mediumtext NOT NULL,
`alter_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`master_id` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `tag` (`tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

导入数据库

mysql -uroot -p < returner-mysql.sql

数据库授权

# 登陆数据库
MariaDB [(none)]> grant all on salt.* to salt@'%' identified by 'salt';  # 授权,若连不上把%换成localhost
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> flush privileges;  # 刷新
Query OK, 0 rows affected (0.00 sec)

因为master和数据库在同一主机,所以授权本机就可以,如果从minion上传数据库,那也要进行相应的授权

查看数据库

MariaDB [salt]> select * from salt_returns
Empty set (0.00 sec)

MariaDB [salt]> select * from salt_events
Empty set (0.00 sec)

执行一次远程任务

salt '*' cmd.run 'hostname'

再次查看数据库

MariaDB [salt]> select * from salt_returns \G;
*************************** 1. row ***************************
       fun: cmd.run
       jid: 20210820090412144409
    return: "master"
        id: master
   success: 1
  full_ret: {"cmd": "_return", "id": "master", "success": true, "return": "master", "retcode": 0, "jid": "20210820090412144409", "fun": "cmd.run", "fun_args": ["hostname"], "_stamp": "2021-08-20T09:04:12.345698"}
alter_time: 2021-08-20 17:04:12
*************************** 2. row ***************************
       fun: cmd.run
       jid: 20210820090412144409
    return: "node1"
        id: node1
   success: 1
  full_ret: {"cmd": "_return", "id": "node1", "success": true, "return": "node1", "retcode": 0, "jid": "20210820090412144409", "fun": "cmd.run", "fun_args": ["hostname"], "_stamp": "2021-08-20T09:04:12.342927"}
alter_time: 2021-08-20 17:04:12
*************************** 3. row ***************************
       fun: cmd.run
       jid: 20210820090412144409
    return: "node2"
        id: node2
   success: 1
  full_ret: {"cmd": "_return", "id": "node2", "success": true, "return": "node2", "retcode": 0, "jid": "20210820090412144409", "fun": "cmd.run", "fun_args": ["hostname"], "_stamp": "2021-08-20T09:04:12.390078"}
alter_time: 2021-08-20 17:04:12
4 rows in set (0.00 sec)
salt '*' test.ping  --return mysql   # 指定返回器为mysql

8.4 Job管理

查看所有minion当前正在运行的jobs(在所有minions上运行saltutil.running

salt '*' saltutil.running       # 查看job及job_id
salt '*' saltutil.kill job_id   # 停止指定job 

salt-run jobs.active     # 查看当前正在运行的job
salt-run jobs.list_jobs  # 列出当前master jobs cache中所有job

salt-run manage.status
salt-run manage.up
salt-run manage.down

九、 Salt-ssh和Salt-syndic

9.1 Salt-ssh

9.1.1 Salt-ssh简介

  • salt-ssh可以独立运行的,不需要minion端。
  • salt-ssh 用的是sshpass进行密码交互的。
  • 以串行模式工作,性能下降。

9.1.2 Salt-ssh安装与配置

  • 安装salt-ssh
yum install -y salt-ssh
  • 配置roster(相当于ansible的inventory清单)文件
# vim /etc/salt/roster
# Sample salt-ssh config file
#web1:
#  host: 192.168.42.1 # The IP addr or DNS hostname
#  user: fred         # Remote executions will be executed as user fred
#  passwd: foobarbaz  # The password to use for login, if omitted, keys are used
#  sudo: True         # Whether to sudo to root, not enabled by default
#web2:
#  host: 192.168.42.2
node1:
  host: 10.0.0.21   # 主机名
  user: root        # 用户
  port: 22          # 端口
  # passwd: 123456  # 密码 考虑到安全一般不建议在配置文件配置密码
node2:
  host: 10.0.0.22
  user: root
  port: 22
  • 测试
# 如果没有配置密码,第一次连接需要手动输入密码,之后不用再输密码
[root@master ~ ]# salt-ssh '*' test.ping -i
node2:
    True
node1:
    True

9.2 Salt-syndic

9.2.1 Salt-syndic简介

  • syndic其实就是个代理,隔离master与minion
  • Syndic必须要运行在master上,再连接到另一个topmaster上
  • Topmaster 下发的状态需要通过syndic来传递给下级master,minion传递给master的数据也是由syndic传递给topmaster。
  • top master并不知道有多少个minion
  • syndic与topmaster的file_roots和pillar_roots的目录要保持一致

9.2.2 Salt-syndic配置

配置顶级master

# salt-syndic
# 架构 简单理解就是salt-syndic所处的master节点之上还有master即master的master,这个master下发指令到salt-syndic
# 然后salt-syndic通知所处同级的salt-master下发指令到minion
                         ->master1[salt-master + salt-syndic  ]  ->minion1,minion2,minion3..... 
     master[salt-master] ->master2[salt-master + salt-syndic  ]  ->minion1,minion2,minion3.....
                         ->master2[salt-master + salt-syndic  ]  ->minion1,minion2,minion3.....


# 新部署一台机器 10.0.0.24 
yum install -y salt-master  # 仅安装salt-master

# 1 修改master配置文件,使其成为顶级master
# vim /etc/salt/master
# masters' syndic interfaces.
order_masters: True

# 重启服务
systectem start salt-master

配置下级master端

  • 安装salt-syndic
yum install -y salt-syndic
  • 修改master配置文件
# 可配置多个顶级master的ip,本例只配置1个
syndic_master:
  - 10.0.0.24
  # - 10.0.0.25
【补充】minion端配置多master如下
master:
  - master1
  - master2
  - master3
  • 重启服务
systemctl restart salt-master 
systemctl start salt-syndic

顶级master端查看

salt-key  -L   
salt-key -A -y
  • 测试
salt '*' test.ping

十、 salt-api

10.1 salt-api简介

SaltStack 官方提供有REST API格式的 salt-api 项目,将使Salt与第三方系统集成变得尤为简单。

官方提供了三种api模块:

rest_cherrpy

rest_tornado

rest_wsgi

官方链接:https://docs.saltstack.com/en/latest/ref/netapi/all/index.html#all-netapi-modules

中文链接: http://docs.saltstack.cn/ref/netapi/all/index.html#all-netapi-modules

10.2 salt-api配置

  • 安装salt-api
yum install -y salt-api python-cherrypy
  • 生成证书
cd /etc/pki/tls/private

openssl genrsa 2048 > localhost.key
cd /etc/pki/tls/certs 

make testcert         # 根据提示填写相关信息
  • 创建用户认证文件
useradd -s /sbin/nologin saltapi 

echo redhat | passwd --stdin saltapi
更改用户 saltapi 的密码 。
passwd:所有的身份验证令牌已经成功更新。
vim /etc/salt/master.d/auth.conf
external_auth:
  pam:
    saltapi:
      - .*
      - '@wheel'
      - '@runner'
      - '@jobs'
  • 激活rest_cherrypy模块
vim /etc/salt/master.d/api.conf
rest_cherrypy:
  host: 10.0.0.20
  port: 8000
  ssl_crt: /etc/pki/tls/certs/localhost.crt
  ssl_key: /etc/pki/tls/private/localhost.key
  • 打开include加载自配置文件
vim /etc/salt/master
# as the main master config file).
default_include: master.d/*.conf   # 打开这行的主食
  • 重启服务
systemctl restart salt-master 
systemctl start salt-api

10.3 salt-api使用

  • 获取认证token
curl -sSk https://10.0.0.20:8000/login \
      -H 'Accept: application/x-yaml' \
      -d username=saltapi \
      -d password=redhat \
      -d eauth=pam
# 执行结果
return:
- eauth: pam
  expire: 1629729789.8010104
  perms:
  - .*
  - '@wheel'
  - '@runner'
  - '@jobs'
  start: 1629686589.8010097
  token: ffa3d1fa269736a542e8a83a8cc32315a5eaa326
  user: saltapi
  • 推送任务
curl -sSk https://10.0.0.20:8000 \
     -H 'Accept: application/x-yaml' \
     -H 'X-Auth-Token: ffa3d1fa269736a542e8a83a8cc32315a5eaa326' \
     -d client=local \
     -d tgt='*' \
     -d fun=test.ping
# 执行结果
return:
- master: true
  node1: true
  node2: true
  node3: true
curl -sSk https://10.0.0.20:8000 \
     -H 'Accept: application/x-yaml' \
     -H 'X-Auth-Token: ffa3d1fa269736a542e8a83a8cc32315a5eaa326' \
     -d client=local \
     -d tgt='*' \
     -d fun=network.get_fqdn
return:
- master: master
  node1: node1
  node2: node2
  node3: syndic-master

11 saltstack综合模板集合

综合模板案例地址: https://github.com/saltstack-formulas/

结语: 限于水平,本文仅作为引导和入门,若需全面细致研究请阅读官方中文文档,地址如下:

http://docs.saltstack.cn/

摘自:https://zhuanlan.zhihu.com/p/433968130

Copyright © https://yan-jian.com 2023 all right reserved更新时间: 2024-01-17 10:36:11

results matching ""

    No results matching ""