SaltStack介绍
在白沙黎族等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供做网站、成都做网站 网站设计制作定制网站,公司网站建设,企业网站建设,品牌网站设计,全网整合营销推广,外贸网站制作,白沙黎族网站建设费用合理。
saltstack是一个开源的批量分发管理工具,具有非常强大的管理功能,能同时管理上万台服务器。由python语言编写,并提供API.
saltstack有四种运行方式:Local, Master/Minion, Salt SSH,Syndic
saltstack有三大功能:远程执行,配置管理(状态),云管理。
saltstack支持多种常见的操作系统,包括Windows(只能做为minion)。
saltstack是依赖于ZeroMQ来实现的(订阅发布模式),监听4505端口(发布系统端口)。所有的minion都会连接到master上的4505端口,而master上的4506端口用于接受minion返回的数据。由于使用的是TCP长连接,所以在master上对海量的服务器执行命令时,会得到非常迅速的响应。
SaltStack的安装配置
http://repo.saltstack.com/#rhel
SaltStack提供了非常丰富的安装方式,可以在官方网站找到对应的说明。
这里使用两台CS7的系统,一台作为master(node1),另一台作为Minion(node2)。
安装SaltStack仓库:
yum install -y https://repo.saltstack.com/yum/redhat/salt-repo-latest-1.el7.noarch.rpm
在master端安装服务端和客户端:
yum install salt-master salt-minion -y
在minoin安装客户端:
yum install salt-minion -y
启动master:
# systemctl start salt-master
修改master和minion端的minion配置文件,为minion指定master,:
vim /etc/salt/minion master: 172.16.10.60 #可以是主机名或IP #id: #id默认可以不改,为主机名 # systemctl start salt-minion #启动minion服务
启动成功后,会生成一个/etc/salt/minion_id的文件,记录了minion的ID信息。
# cat /etc/salt/minion_id node2
在pki目录下会生成一系列的密钥:
[root@node1 salt]# tree pki pki ├── master │ ├── master.pem #master私钥 │ ├── master.pub #master公钥 │ ├── minions │ ├── minions_autosign │ ├── minions_denied │ ├── minions_pre #未被管理的密钥 │ │ ├── node1 │ │ └── node2 │ └── minions_rejected └── minion ├── minion.pem └── minion.pub
[root@node2 salt]# tree pki pki ├── master └── minion ├── minion.pem └── minion.pub
通过MD5校验对比,可以发现master上收到的node2的密钥和node2本地的密钥相同:
# 完成分发后,路径改变 [root@node1 ~]# md5sum /etc/salt/pki/master/minions/node2 d9a0453d7d539dbcc36e1daea259aa10 /etc/salt/pki/master/minions/node2 [root@node2 ~]# md5sum /etc/salt/pki/minion/minion.pub d9a0453d7d539dbcc36e1daea259aa10 /etc/salt/pki/minion/minion.pub
在master上使用salt-key命令来查看添加minion主机:
[root@node1 salt]# salt-key Accepted Keys: Denied Keys: Unaccepted Keys: node1 node2 Rejected Keys:
加入指定的minion主机:
# salt-key -a node1 #可以使用通配符如 node*添加所有以node开头为开头的主机 The following keys are going to be accepted: Unaccepted Keys: node1 Proceed? [n/Y] Y Key for minion node1 accepted.
同意所有minion主机:
# salt-key -A
对所有的主机执行命令,测试主机是否在线:
[root@node1 ~]# salt '*' test.ping node2: True node1: True
对所有主机运行一个命令,出现下面结果说明可以进行远程管理了:
[root@node1 ~]# salt '*' cmd.run 'date' node1: Fri Nov 4 14:21:37 CST 2016 node2: Fri Nov 4 14:21:37 CST 2016
如果在使用过程中修改了主机名(不推荐这样做,会造成很多问题),可以在minion的配置文件中指定主机名(id), 然后删除修改主机的KEY,重新启动minon:
[root@node-1 ~]# salt-key -d old-key-name #删除指定的key [root@node-1 ~]# salt-key -D # 删除所有key
SaltSack配置管理
当需要对海量的机器进行配置管理的时候经常会修改各种配置文件,SaltStack的配置管理可以让我们更方便的部署服务,针对不同的服务器和不同的服务,可以通过编辑.sls文件来管理。
SaltStack的配置分发管理是使用YAML状态文件来编写的。
YAML语法:
1.缩进: 两个空格,不能使用tab键。
2.冒号:代表键值对 key: value (注意,键值对冒号后面有一个空格)
3.短横线:表示列表(短横线后面有一个空格)
基础配置
编辑配置文件,定义YAML模块:
# vim /etc/salt/master #打开基础配置 file_roots: base: - /srv/salt #配置文件根路径
在示例中又三个模块,base,dev,prod.分别代表基础环境、测试环境、生产环境的配置,可以对每个模块可以指定对应路径:
# Example: # file_roots: # base: # - /srv/salt/ # dev: # - /srv/salt/dev/services # - /srv/salt/dev/states # prod: # - /srv/salt/prod/services # - /srv/salt/prod/states
修改salt配置文件后重启:
systemctl restart salt-master
创建根路径:
mkdir /srv/salt/ # salt的根路径
批量执行相同命令
在需要对大量主机安装配置相同的内容时可以通过编辑简单的sls文件来执行。
创建base环境文件分类目录,编辑需要安装的配置:
mkdir /srv/salt/web vim /srv/salt/web/apache.sls #编写内容: apache-install: #命名ID,可随意命名 pkg.installed: #pkg模块,调用installed方法 - names: #installed方法中的参数 - httpd #需要安装的包名 - httpd-devel apache-service: #状态命名ID service.running: #调用service.running方法 - name: httpd #服务的命名为httpd - enable: True #设置开机自启动
执行.sls文件:
salt '*' state.sls web.apache #state.sls执行模块,执行根目录中apache.sls文件
此时会在两台在线的主机上安装Apache,并启动。
查看node2上的文件,同样生成了一个apache.sls的文件:
[root@node2 ~]# cat /var/cache/salt/minion/files/base/web/apache.sls apache-install: pkg.installed: - names: - httpd - httpd-devel apache-service: service.running: - name: httpd - enable: True
minion通过复制master的.sls文件到本地执行。
对不同主机指定不同的动作
在master配置文件中,指定top配置文件,top文件必须在base环境中。
#state_top: top.sls #默认不需要配置
在指定的base环境路径上编写top.sls文件,为不同的minion主机指定不同的动作:
[root@node1 salt]# cat /srv/salt/top.sls base: 'node1': - web.apache 'node2': - web.apache
执行高级状态命令,使top.sls文件生效:
salt '*' state.highstate test=True #测试top文件,对minion不做修改 salt '*' state.highstate # * 代表所有minion,执行top文件内容
SaltStack数据系统
SaltStack是通过两种数据系统来发布的,Grains和Pillar。通过数据系统来统计主机的相关信息,进而帮助用户使用多样化的方式来筛选定位我们要执行salt命令的主机。
Grans介绍
Grains: 获取静态数据 ,当minion启动的时候收集Minion本地的相关信息,如操作系统版本,内核信息,硬件信息等,也可以自定义。当minion启动后,获取的数据就不会再改变,只有重启或同步时才能获取新的变化信息。
Grains的特性可以有几种应用场景:
资产管理,信息查询。
用于目标选择。(salt -G 'key:value' cmd.run 'cmd')
配置管理中使用。
查看Grains信息:
salt 'node1' grains.ls #显示所有模块
salt 'node1' grains.items #显示所有模块的信息
salt '*' grains.item fqdn #返回所有minion端的fqdn信息
使用Grains指定信息对应的主机,执行salt命令:
[root@node1 salt]# salt '*' grains.item os node2: ---------- os: CentOS node1: ---------- os: CentOS [root@node1 salt]# salt -G 'os:CentOS' cmd.run 'date' # -G 参数指定Grains信息 node1: Sun Nov 6 17:28:36 CST 2016 node2: Sun Nov 6 17:28:36 CST 2016
自定义Grains
自定义Grains有两种方式:
在/etc/salt/minion添加配置
在/etc/salt/目录编写新的配置文件grains
在node2上的/etc/salt/minion添加配置,在grains部分取消注释,添加一个roles角色:
grains: roles: apache
重启salt-minion,并在master上获取roles的值:
[root@node2 ~]# systemctl restart salt-minion [root@node1 ~]# salt '*' grains.item roles node1: ---------- roles: node2: ---------- roles: apache
这样就可以根据Grains的匹配结果来对符合匹配结果的主机执行命令:
[root@node1 ~]# salt -G 'roles:apache' cmd.run 'date' node2: Sun Nov 6 17:51:07 CST 2016
在/etc/salt/目录编写新的配置文件grains:
[root@node2 ~]# cat /etc/salt/grains saltname: trying [root@node2 ~]# systemctl restart salt-minion #也可以在master上使用刷新命令,和重启salt-minion效果一样 [root@node1 ~]# salt '*' saltutil.sync_grains node1: node2:
master上查看:
[root@node1 ~]# salt '*' grains.item saltname node1: ---------- saltname: node2: ---------- saltname: trying
在top file中使用Grains
在top.sls中使用grains进行匹配
vim /srv/salt/top.sls base: 'node1': - web.apache 'saltname:trying': #此处grains匹配上node2 - match: grain #匹配grains,不加s. - web.apache
使用python脚本编写一个Grains
使用python脚本编写一个grains,需要存放在base环境中的_grains目录中。
[root@node1 _grains]# cat /srv/salt/_grains/my_grains.py #!/usr/bin/env python #-*- coding: utf-8 -*- def my_grains(): #init a grains grains = {} #set key-value grains['iaas'] = 'openstack' grains['blog'] = 'trying' # return value return grains
同步脚本到minion端:
[root@node1 _grains]# salt '*' saltutil.sync_grains #这里可以指定主机同步 node1: - grains.my_grains node2: - grains.my_grains
在minion端可以看到同步过来的脚本和目录:
[root@node2 ~]# tree /var/cache/salt/minion/ /var/cache/salt/minion/ ├── accumulator ├── extmods │ └── grains │ ├── my_grains.py #真正执行的脚本 │ └── my_grains.pyc ├── files │ └── base │ ├── _grains │ │ └── my_grains.py #同步的脚本文件 │ ├── top.sls │ └── web │ └── apache.sls ├── highstate.cache.p ├── module_refresh ├── pkg_refresh ├── proc └── sls.p
在master上查看执行结果,已经同步到minion上:
[root@node1 _grains]# salt '*' grains.item blog node1: ---------- blog: trying node2: ---------- blog: trying
Grains的优先级
上面给出了四种方式可以使用Grains的值,在这四种方式中,如果出现了同名的情况,会
按照以下的优先级来获取对应的值:
系统自带的值
/etc/salt/grains文件中编写的值
minion配置文件中定义的值
/srv/salt/_grains/my_grains.py 脚本中自定义的值
================
Pillar介绍
与Grains不同的是,Pillar是动态的,能给特定的minion指定特定的数据。只有指定的minion能看到自己的数据,这样常用与一些敏感的特殊数据。
默认情况下pillar的系统模块是关闭的:
[root@node1 salt]# salt '*' pillar.items node1: ---------- node2: ----------
可以在/etc/salt/master中打开注释,修改为True,系统的这些变量很少会用到:
pillar_opts: True
自定义pillar
自定义pillar需要编写一个sls文件,在文件中定义pillar. 使用YAML定义多级。
修改master配置文件,打开注释:
vim /etc/salt/master pillar_roots: base: - /srv/pillar
重启salt-master:
systemctl restart salt-master
创建pillar的目录:
mkdir /srv/pillar
和grains一样,创建分类目录和.sls的文件
vim /srv/pillar/web/apache.sls {% if grains['os'] == 'CentOS' %} apache: httpd {% elif grains['os'] == 'Debian' %} apache: apache2 {% endif %}
在pillar目录中编写top file指定主机,和grains中的一样:
# cat /srv/pillar/top.sls base: 'node2': #只指定了node2 - web.apache
刷新,使配置生效:
# salt '*' saltutil.refresh_pillar node2: True node1: True
执行查看pillar items 生效:
# salt '*' pillar.items apache node2: ---------- apache: httpd node1: ---------- apache:
使用pillar匹配上主机node2,执行命令:
# salt -I 'apache:httpd' cmd.run 'hostname' node2: node2
Grains和Pillar的对比
分类 | 类型 | 数据采集方式 | 应用场景 | 定义位置 |
Grains | 静态 | minion启动时收集 | 数据查询,目标选择,配置管理 | minion |
Pillar | 动态 | master自定义 | 目标选择,配置管理,敏感数据 | master |
SaltStack远程执行
saltstack命令语法, salt '*' cmd.run 'w'
命令:salt
目标:‘*’
模块: cmd.run 自带150+模块,也可以自定义编写模块
返回:执行后结果返回。
目标选择方式
所有匹配目标的方式都可以用top file来指定。
使用通配符:
# salt 'node*' test.ping # salt 'node[1|2]' test.ping # salt 'node[1-2]' test.ping # salt 'node[!2]' test.ping
使用列表,-L:
# salt -L 'node1,node2' test.ping
使用正则,-E:
# salt -E 'node(1|2)*' test.ping
使用IP/子网方式:
# salt -S '172.16.10.61' test.ping
# salt -S '172.16.10.0/24' test.ping
使用node_group匹配:-N
修改配置文件/etc/salt/master,在node group模块中添加匹配的组:
nodegroups: web: 'L@node1,node2'
重启salt-master:
systemctl restart salt-master
匹配node-group:
[root@node1 ~]# salt -N web test.ping node2: True node1: True
多种匹配方式命令示例:
https://www.unixhot.com/docs/saltstack/topics/targeting/index.html
https://www.unixhot.com/docs/saltstack/topics/targeting/compound.html
SaltStack自带模块
https://docs.saltstack.com/en/latest/ref/modules/all/index.html#all-salt-modules
Saltstack有很多集成的模块,大部分模块都是由python编写,使用这些模块可以很方便的返回一个信息列表或者执行某些任务。
常用的一些模块举例:
network模块:网络相关服务
https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.network.html#module-salt.modules.network
salt.modules.network.active_tcp :
这里表示了模块函数的路径和位置,salt.modules表示的就是slat模块在本机的安装位置,一般默认情况下在 /usr/lib/python2.7/site-packages/salt/modules
在执行命令的时候可以直接使用slat命令来调用
service 模块:和主机当前服务相关的模块
https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.service.html#module-salt.modules.service
在一些常用的模块中,有一些模块方法已经有了单独的命令如cp模块:
cp是复制模块,在系统中我们可以直接使用salt-cp 如:
salt-cp ‘*’ /etc/hosts /tmp/ #拷贝本地的hosts文件到所有minion的/tmp目录下。
state:执行模块
https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.state.html#module-salt.modules.state
Saltstack返回程序
数据的返回是由minion端提供的,可以将minion返回的数据直接写入到MySQL中而不经过master。
要实现minion直接返回数据到mysql,需要在所有的minion安装MySQL-python
salt '*' state.single pkg.installed name=MySQL-python
使用返回数据存入mysql,需要在master上安装数据库,并且创建表结构,授权:
https://docs.saltstack.com/en/latest/ref/returners/all/salt.returners.mysql.html
执行下面命令,创建数据库并授权:
> CREATE DATABASE `salt` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; > USE `salt`; > 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; > 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; > 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; > grant all on salt.* to salt@'%' identified by 'salt'; > show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | salt | +--------------------+ 4 rows in set (0.00 sec) > use salt Database changed > show tables; +----------------+ | Tables_in_salt | +----------------+ | jids | | salt_events | | salt_returns | +----------------+ 3 rows in set (0.00 sec) MariaDB [salt]> select * from salt_returns; Empty set (0.00 sec)
修改所有minion端salt的配置文件,加入下面配置后重启salt服务:
在配置最后添加如下信息:
mysql.host: '172.16.10.60' # mysql所在的主机地址 mysql.user: 'salt' mysql.pass: 'salt' mysql.db: 'salt' mysql.port: 3306
重启minion服务:
systemctl restart salt-minion
执行数据库测试命令:
salt '*' test.ping --return mysql
再次查看数据库,发现已经写入数据:
[root@node1 ~]# mysql -h 172.16.10.60 -usalt -p -e "use salt; select * from salt_returns\G" Enter password: *************************** 1. row *************************** fun: test.ping jid: 20161108135248194687 return: true id: node2 success: 1 full_ret: {"fun_args": [], "jid": "20161108135248194687", "return": true, "retcode": 0, "success": true, "fun": "test.ping", "id": "node2"} alter_time: 2016-11-08 13:52:48 *************************** 2. row *************************** fun: test.ping jid: 20161108135248194687 return: true id: node1 success: 1 full_ret: {"fun_args": [], "jid": "20161108135248194687", "return": true, "retcode": 0, "success": true, "fun": "test.ping", "id": "node1"} alter_time: 2016-11-08 13:52:48
执行一条命令,写入数据库:
salt '*' cmd.run 'df -h' --return mysql
再次查看数据库,会发现数据库中已经记录了操作的命令和返回值记录,以及操作的时间。
编写状态模块
我们可以根据自己的需要,自定义一些状态模块。比如,可以编写一个模块脚本,来执行复杂的操作,直接使用salt来调用这些模块就可以实现我们需要的功能。
模块存放的路径:/srv/salt/_modules
mkdir /srv/salt/_modules
编写一个显示磁盘信息的模块脚本:
[root@node1 /srv/salt/_modules]# vim /srv/salt/_modules/my_disk.py
def list(): cmd = 'df -h' ret = __salt__['cmd.run'](cmd) return ret
salt同步文件到所有minion端:
# salt '*' saltutil.sync_modules node1: - modules.my_disk node2: - modules.my_disk
运行my_disk.py模块:
# salt '*' my_disk.list node2: Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 8.5G 1.4G 7.1G 17% / devtmpfs 483M 0 483M 0% /dev tmpfs 493M 12K 493M 1% /dev/shm tmpfs 493M 20M 474M 4% /run tmpfs 493M 0 493M 0% /sys/fs/cgroup /dev/sda1 497M 165M 332M 34% /boot tmpfs 99M 0 99M 0% /run/user/0 node1: Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 8.5G 1.6G 7.0G 18% / devtmpfs 483M 0 483M 0% /dev tmpfs 493M 28K 493M 1% /dev/shm tmpfs 493M 20M 474M 4% /run tmpfs 493M 0 493M 0% /sys/fs/cgroup /dev/sda1 497M 165M 332M 34% /boot tmpfs 99M 0 99M 0% /run/user/0
可以看到salt将每一台minion运行的结果返回到我们的master端,和执行df -h 的效果一样。