SaltStack技术入门与实践

第1章 SaltStack入门

1.2.1 SaltStack软件依赖
SaltStack有两种消息系统,一种是REAT,一种是ZeroMQ,默认使用ZeroMQ.
软件依赖列表如下:
●Python版本大于2.6或版本小于3.0:对Python版本要求
●msgpack-python:SaltStack消息交换库
●YAML:SaltStack配置解析定义语法
●Jinja2: SaltStack states配置模板
●MarkupSafe: Python unicode转换库
●apache-libcloud: SaltStack对云架构编排库
●Requests: HTTP Python库
●ZeroMQ: SaltStack消息系统
●pyzmq: ZeroMQ Python库
●PyCrypto: Python密码库
●M2Crypto: Openssl Python包装库

1.2.2 yum方式安装(采用EPEL源)
Master端安装:
SaltStack@Master: rpm -vih rpm -vih http://mirrors.zju.edu.cn/epel/6/i386/epel-release-6-8.noarch.rpm
SaltStack@Master: yum install salt-master -y
SaltStack@Master: service salt-master start

Minion端安装:
SaltStack@Minion: rpm -ivh rpm -vih http://mirrors.zju.edu.cn/epel/6/i386/epel-release-6-8.noarch.rpm
SaltStack@Minion: yum install salt-minion -y
SaltStack@Minion: sed -i 's/#master: salt/master: IPADDRESS/g' /etc/salt/minion
#IPADDRESS 为Master服务器地址
SaltStack@Minion: service salt-minion start

1.2.5 salt-bootstrap安装
salt-bootstrap主要用于解决多平台一键部署SaltStack环境。核心工程机就是维护一个庞大的bash脚本。

Master端安装:
SaltStack@Master: curl -L https://bootstrap.saltstack.com -o install_salt.sh
SaltStack@Master: sh install_salt.sh -M -N #只安装最新版的Master

Minion端安装:
SaltStack@Minion: echo "IPADDRESS salt" >> /etc/hosts #IPADDRESS为Master服务器地址
SaltStack@Minion: curl -L https://bootstrap.saltstack.com -o install_salt.sh
SaltStack@Minion: sh install_salt.sh -i Minion #只安装最新版Minion并且指定Minion id

1.3 开始SaltStack之旅

1.3.1 证书管理
对Minion进行签售证书:
SaltStack@Master: salt-key -L #查看当前证书签售情况
SaltStack@Master: salt-key -A -y #同意签证有没有接受的签证请求


#查看更多证书管理命令
SaltStack@Master: salt-key -h


SaltStack@Master: salt 'Minion' test.ping

1.3.2 日常命令参数

1.Master端
SaltStack@Master: rpm -ql salt-master
/etc/rc.d/init.d/salt-master #salt-master服务启动脚本
/etc/salt/master #salt master配置文件
/usr/bin/salt #salt-master 核心操作命令
/usr/bin/salt-cp #salt文件传输命令
/usr/bin/salt-key #salt 证书管理命令
/usr/bin/salt-master #salt master服务命令
/usr/bin/salt-run #salt master runner命令
/usr/bin/salt-unity

2.Minion端
SaltStack@Minion: rpm -ql salt-minion
/etc/rc.d/init.d/salt-minion #salt minion服务启动脚本
/etc/salt/minion #salt minion配置文件
/usr/bin/salt-call #salt call拉取命令
/usr/bin/salt-minion #salt minion服务命令

SaltStack@Minion: salt-call -h


1.4 熟悉SaltStack配置文件
SaltStack的配置文件分为Master(/etc/salt/master)和Minion(/etc/salt/minion)

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

-----------------------------------------------------------------------------------------------------------
第2章 SaltStack组件

2.1 从管理对象说起

SaltStack系统中的管理对象叫做Target, 在Master上我们可以采用不同的Target去管理不同的Minion,这些Target都是通过去管理和匹配Minion的ID来做一些集合!

1.正则匹配

#想要匹配到'Min*'字符串的Minion进行操作
SaltStack@Master: salt -E 'Min*' test.ping

2.列表匹配
SaltStack@Master: salt -L Minion,Minion1 test.ping

Minion和Minion1通过列表的方式去指定Minion ID,可直接使用。

3.Grians匹配
SaltStack@Master: salt -G 'os:MacOS' test.ping

其中os:MacOS,这里的对象是一组键值对。

4.组匹配
SaltStack@Master: salt -N groups test.ping
groups是我们在master配置文件中定义的组名称

5.复合匹配
SaltStack@Master: salt -C 'G@os:MacOS or L@Minion1' test.ping

os:MacOs or L@Minion1是一个复合组合,支持使用and和or关联多个条件

6.Pillar值匹配
SaltStack@Master: salt -I 'key:value' test.ping

key:value是Pillar系统中定义的一组键值对,跟Grains的键值对类似。

7.CIDR匹配
SaltStack@Master: salt -S '192.168.1.0/24' test.ping

192.168.1.0/24是一个指定的CIDR网段,这里匹配的IP地址是Minion连接Master 4505端口的来源地址。

2.2 管理对象属性
Grains是SaltStack记录Minion的一些静态信息的组件,简单理解为Grains里面记录着每台Minion的一些常用属性,例如CPU、内存、磁盘、网络信息等。
可以通过grains.items查看某台Minion的所有Grains信息。Minion的Grains信息是Minions启动时采集汇报给Master的。

关于自定义Grains的常用方法有以下几种:
●通过Minion配置文件定义
●通过Grains相关模块定义
●通过Python脚本定义

Grains相关命令用法:
SaltStack@Master: salt 'Minion' sys.list_functions grains
Minion:
- grains.append
- grains.delval
- grains.filter_by
- grains.get
- grains.get_or_set_hash
- grains.has_value
- grains.items
- grains.ls
- grains.remove
- grains.setval
- grains.setvals


#查看详细用法
salt 'Minion' sys.doc grains

2.2.1 通过Minion配置文件定义Grains
SaltStack的配置文件的默认格式都是YAML格式
为了统一管理Minion的Grains信息,需要把SaltStack的配置文件中定义grains的部分复制到minion.d/grains文件中:
SaltStack@Minion: cat /etc/minion.d/grains
grains:
roles:
- webserver
- memcache
deployment: datacenter4
cabinet: 13
cab_u: 14-15

然后/etc/init.d/salt-minion restart命令重启Minion服务,之后可以去Master上查看定义的Grains信息是否生效:
SaltStack@Master: salt 'Minion' grains.item roles
SaltStack@Master: salt 'Minion' grains.item deployment

2.2.2 通过Grains模块定义Grains
SaltStack@Master: salt 'Minion' grains.append saltbook 'verycool'
#设置grains信息
Minion:
---------------
saltbook:
- verycool
SaltStack@Master: salt 'Minion' grains.item saltbook #查看grains信息
Minion:
---------------
saltbook:
- verycool

可以使用grains.setvals同时设置多个Grains信息:
SaltStack@Master: salt 'Minion' grains.setvals "{'salt': 'good','book': 'cool'}"
Minion:
---------------
book:
cool
salt:
good
SaltStack@Master: salt 'Minion' grains.item salt
Minion:
---------------
salt:
good

 

上面设置的内容会被写入到Minion端的/etc/salt/grains文件中
更多用法可通过sys.doc grains命令查询(salt 'Minion' sys.doc grains)

2.3 数据管理中心
Pillar是数据管理中心。Pillar在SaltStack中主要的作用是存储和定义配置管理中需要的一些数据,比如软件版本号,用户名密码等信息
它的存储定义格式也是YAML格式。
在Master配置文件中有一段Pillar settings选项专门定义Pillar相关的一些参数:
#pillar_roots:
# base:
# - /srv/pillar

默认Base环境下Pillar工作目录在/srv/pillar目录下。
【使用默认的配置】
首先去pillar工作目录新建top.sls文件然后引用两个sls文件:
SaltStack@Master: cat /srv/pillar/top.sls
base: #指定环境
'*': #Target
- packages #引用package.sls或者packages/init.sls
- services #引用services.sls或者services/init.sls
SaltStack@Master: cat /srv/pillar/packages.sls
zabbix:
package-name: zabbix
version: 2.2.4
SaltStack@Master: cat /srv/pillar/services.sls
zabbix:
port: 10050
user: admin

#查看关于pillar相关的一些模块用法
SaltStack@Master: salt 'Minion' sys.list_functions pillar
Minion:
- pillar.data
- pillar.ext
- pillar.get
- pillar.item
- pillar.items
- pillar.raw

详细用法和例子可通过命令salt 'Minion' sys.doc pillar查看。

#查看刚刚定义的pillar:
SaltStack@Master: salt 'Minion' pillar.item zabbix

2.4 针对管理对象操作
Module用于管理对象操作,也是SaltStack通过Push方式进行管理的入口:例如执行命令、查看安装包情况、查看服务运行情况。

1.查看所有module列表
查看Minion支持的所有module列表的命令如下:
SaltStack@Master: salt 'Minion' sys.list_modules

2.查看指定module的所有function
查看cmd module的所有function的命令如下:
SaltStack@Master: salt 'Minion' sys.list_functions cmd

3.查看指定module用法
查看cmd module的详细用法与例子的命令:
SaltStack@Master: salt 'Minion' sys.doc cmd

SaltStack默认也支持一次执行多个Module,Module之间通过逗号隔开,默认传参之间也用逗号隔开,也支持指定传参分隔符号--args-separator=@即可
SaltStacke@Master: salt 'Minion' test.echo,cmd.run,service.status,saltbook,hostname,salt-master

2.5配置管理从这里开始
States是SaltStack中的配置语言,在日常进行配置管理时需要编写大量的States文件!

1.查看所有states列表
要查看Minion支持的所有states列表,命令如下:
SaltStack@Master: salt 'Minion' sys.list_state_modules

2.查看指定states的所有function
查看file.states的所有function,命令如下:
SaltStack@Master: salt 'Minion' sys.list_state_functions file

3.查看指定states用法
查看file.states的详细用法:
SaltStack@Master: salt 'Minion' sys.state_doc file

4.查看指定states指定function用法
查看file.managed states的详细用法和例子:
SaltStack@Master: salt 'Minion' sys.state_doc file.managed

5.从一个简单的例子去了解states
使用states的流程:
●编写top.sls文件(非必须)
●编写states.sls文件

top.sls是states系统的入口文件,它在大规模配置管理工作中负责指定哪些设备调用哪些states.sls文件。

例如:要简单的对某台机器进行配置管理,可直接使用state.sls命令指定states.sls文件即可,具体操作如下:
先在states的工作目录(base环境默认在/srv/salt)下新建一个one.sls states文件:
SaltStack@Master: cat /srv/salt/one.sls
/tmp/foo.conf: #id
file.mangled: #file states的mangled functions
- source: salt://foo.conf #文件来源(salt://代表states的工作目录)
- user: root #文件属主
- group: root #文件属组
- mode: 644 #文件权限
- backup:minion #备份原文件

这个states.sls文件的功能就是实现对Minion的/tmp/foo.conf文件进行统一管理。
【部署】
可以在states的工作目录下新建一个foo.conf文件,然后对Minion进行配置部署:
SaltStack@Master: echo "SaltStack Books" > /src/salt/foo.conf
SaltStack@Master: salt 'Minion' state.sls one


使用top.sls入口文件同时对多台机器进行一个简单的配置管理,操作如下:
首先在states的工作目录下新建top.sls文件:
SaltStack@Master: cat /src/salt/top.sls
base: #base环境
'*': #Target(代表所有Target)
- one #引用one.sls或者one/init.sls states文件
'Minion': #Target(代表匹配Minion)
- tow #引用tow.sls或者tow/init.sls states文件
'Minion1': #Target(代表匹配Minion1)
- three #引用three.sls或者three/init.sls states文件

然后我们新建三个states文件:one.sls、tow.sls、three.sls,并使用state.highstate命令同时对Minion和Minion1两台机器进行配置管理。

2.6执行结果处理
Return组件是SaltStack系统对执行Minion返回后的数据进行存储或者返回给其他程序。它支持多种存储方式,比如用MySQL,MongoDB,Redis,Memcache等
通过Return可以对SaltStack的每次操作进行记录,对以后日志审计提供了数据来源。
官方支持30多种Return数据存储与接口!

1.查看所有Return列表
SaltStack@Master: salt 'Minion' sys.list_returners

2.Return流程
Return是在Master端触发任务,然后Minion接受处理任务后直接与Return存储服务器建立连接,然后把数据Return存到存储服务器。

3.使用Redis作为Return存储方式
需要修改的配置信息:
●Minion配置文件
●在Minion上安装Redis Python Client

(1)在Minion配置文件中定义Redis存储服务器信息
redis.db: '0' #redis数据库
redis.host: 'vps.shencan.net' #redis主机(ip地址和域名都行)
redis.port: 6379 #redis端口

(2)安装依赖包
SaltStack@Minion: python -c 'import redis; print redis.VERSION'
如果能显示出版本号,说明当前Python版本下的Redis Client已经安装好!


2.7 Job管理
在SaltStack里面执行任何一个操作都会在Master上产生一个jid号。Minion端会在cache目录下的proc目录创建一个以jid为名称的文件,这个文件里面的内容就是
此次操作的记录,当操作处理完成后该文件会自动删除。而Master端会记录每次操作的详细信息,这个记录都是存到在Master端cache目录下的jobs下。

1.通过salt-run来管理job
查看salt-run对job管理的一些用法:
SaltStack@Master: salt-run -d |grep jobs

[root@SaltStack-Master salt]# salt-run -d|grep jobs
/usr/lib64/python2.6/site-packages/Crypto/Util/randpool.py:40: RandomPool_DeprecationWarning: This application uses RandomPool, which is BROKEN in older releases. See http://www.pycrypto.org/randpool-broken
RandomPool_DeprecationWarning)
'jobs.active:'
Return a report on all actively running jobs from a job id centric
salt-run jobs.active
'jobs.last_run:'
List all detectable jobs and associated functions
salt-run jobs.last_run
salt-run jobs.last_run target=nodename
salt-run jobs.last_run function='cmd.run'
salt-run jobs.last_run metadata="{'foo': 'bar'}"
'jobs.list_job:'
salt-run jobs.list_job 20130916125524463507
'jobs.list_jobs:'
List all detectable jobs and associated functions
Search for jobs where the start time of the job is greater than
Search for jobs where the start time of the job is less than
salt-run jobs.list_jobs
salt-run jobs.list_jobs search_function='test.*' search_target='localhost' search_metadata='{"bar": "foo"}'
salt-run jobs.list_jobs start_time='2015, Mar 16 19:00' end_time='2015, Mar 18 22:00'
'jobs.list_jobs_filter:'
List all detectable jobs and associated functions
salt-run jobs.list_jobs_filter 50
salt-run jobs.list_jobs_filter 100 filter_find_job=False
'jobs.lookup_jid:'
salt-run jobs.lookup_jid 20130916125524463507
salt-run jobs.lookup_jid 20130916125524463507 outputter=highstate
'jobs.print_job:'
salt-run jobs.print_job 20130916125524463507

关于每个参数的解释可以通过命令来查看:
salt-run -d jobs

可以通过salt-run job管理来查看job的信息。
查看某个job的运行结果:
SaltStack@Master: salt-run jobs.lookup_jid 20150503205732787057

查看这个job的详细记录:
SaltStack@Master: salt-run jobs.list_job 20150503205732787057


2.通过SaltStack Module来管理job
salt-run对job管理功能比较局限,目前salt-run不支持kill某个job.

#查看相关Module的用法
SaltStack@Master: salt \* sys.doc saltutil | grep job

[root@SaltStack-Master salt]# salt \* sys.doc saltutil | grep job
saltutil.find_cached_job: #查询job cache信息
Return the data for a specific cached job id
salt '*' saltutil.find_cached_job <job id>
saltutil.find_job: #查询job信息
Return the data for a specific job id
salt '*' saltutil.find_job <job id>
saltutil.kill_job: #杀掉job(发送SIGTERM 9信号方式)
Sends a kill signal (SIGKILL 9) to the named salt job's process
salt '*' saltutil.kill_job <job id>
salt '*' saltutil.runner jobs.list_jobs
saltutil.signal_job: #发送指定信号
Sends a signal to the named salt job's process
salt '*' saltutil.signal_job <job id> 15
saltutil.term_job: #删掉job(发送SIGTERM 15信号方式)
Sends a termination signal (SIGTERM 15) to the named salt job's process
salt '*' saltutil.term_job <job id>

使用Module来管理job
SaltStack@Master: salt 'Minion' saltutil.find_job 20150503205732787057

直接杀掉这个job
SaltStack@Master: salt 'Minion' saltutil.kill_job 20150503205732787057

2.8 EVENT和Reactor系统
EVENT是SaltStack里面对每一个事件的一个记录,它相对job更加底层,Event能记录更加详细的SaltStack事件。
例如:Minion服务启动后请求Master签发证书或者证书校验的过程,都能通过Event事件来查看整个过程。
Event也为扩展SaltStack提供了更加友好的接口。

1.查看Event事件
SaltStack@Master: salt-run state.event pretty=True

2.在Master上配置Reactor
Reactor是基于Event的每个事件来做相应的操作。可以理解为Reactor系统是一直监听着Event,然后触发一些States操作。
当大规模新机器上线时,都希望Minion第一次起来时就能完成所有的配置,这就能通过Reactor实现。

●在Master配置文件里面添加如下内容:
reactor:
- 'salt/auth': #监听证书认证event
- /srv/reactor/Minion.sls #执行states sls文件
- 'salt/minion/Minion/start': #监听Minion start event
- /srv/reactor/auto.sls #执行states sls文件

●配置states文件
SaltStack@Master: cat /srv/reactor/Minion.sls
{% if 'act' in data and data['act'] == 'pend' and data['id'].startswith('Min') %}
key_accept:
wheel.key.accept:
- match: {{ data['id'] }}
{% endif %}

上述文件主要是取event里面的数据,然后根据Minion的ID进行证书签发。

初始的auto.sls文件
SaltStack@Master: cat /srv/reactor/auto.sls
run_state:
local.state.sls
- tgt: {{ data['id'] }}
- arg:
- shencan
run_init:
local.cmd.run:
- tgt: {{ data['id'] }}
-arg:
- echo initsok >>/tmp/cpis

上述文件运行了两个Module,一个是states.sls进行,一个是cmd.run.
run_state是针对Minion运行state.sls shencan
run_init: 是针对Minion运行cmd.run 'echo initok >> /tmp/cpis'

2.9 Renderer组件
默认SaltStack的Renderers是YAML+Jinja,可以通过查看Master配置文件得知当前的Renderer.
三种应用范围比较广的Renderer : YAML、Jinja、py

使用Python语言去定义state文件:
SaltStack@Master: cat /srv/salt/test.sls
#!py #指定renderer,这里为Python
def run():
example={}
example['/tmp/test'] = {
'file.managed': [
{'source': 'salt://test'},
{'mode': '644'},
{'user': 'root'},
{'template':'jinja'},
{'group':'root'},
{'context':{
'a': __grains__['os'],
'b': __pillar__['a'],
},
},
],
}
return example

state.sls文件的用途就是使用Jinja模板去同步/tmp/test文件。
通过Python定义一个run函数,函数返回一个dict。

使用Python编写的state就是使用YAML编写的state.
在state里面调用Pillar Grains,使用python编写时可直接使用__grains__ __pillar__这两个Python方法进行引用。
使用YAML编写的state里面引入Jinja来调取grains['key'] pillar['key']

2.10 其他组件

2.10.1 Mine
Mine是SaltStack收集Minion数据存储到Master的一个组件,功能和Grains类似!
Mine可以指定任何Minion模块去采集数据。
Master只能存储Minion收集上来的最近一段的数据,Mine的主要应用场景是配合前端负载均衡动态获取Mine汇报信息,来动态生成配置文件!

Mine支持两种配置方式:(1)通过在Minion配置文件中定义;(2)通过模块的方式去下发Mine采集任务。

#查看Mine模块的更多用法
sys.doc mine

2.10.2 Peer
Peer组件是SaltStack中Minion向Master发布任务的一个组件,使用Peer可以直接在Minion上向Master发布一些任务。
【配置Peer】
peer:
Minion:
- test.ping
peer_run:
Minion:
- manage.up

Peer是控制Minion执行模块的,peer_run是控制Minion执行runner的。
下面通过在Minion上向Master发布任务:
●执行test.ping
SaltStack@Minion: salt-call publish.publish 'Minion' test.ping
●其他任务
SaltStack@Minion: salt-call publish.publish 'Minion' test.echo saltstack
●调用runner
SaltStack@Minion: salt-call publish.runner manage.up
SaltStack@Minion: salt-call publish.runner manage.down
-----------------------------------------------------------------------------------------------
第3章 SaltStack实践案例

使用SaltStack进行生产环境配置管理,主要包括以下功能和服务:
●系统初始化
●Haproxy服务
●Keepalived服务
●Nginx服务
●PHP(FastCGI)服务
●Memcached服务

3.1环境规划

3.1.2 SaltStack环境设置
本案例使用两个环境base和prod,base环境用来存放初始化的功能;prod环境用于放置生产的配置管理功能。
vi /etc/salt/master

#File Server Setting
file_roots:
base:
- /srv/salt/base
prod:
- /srv/salt/prod

#Pillar setting
pillar_roots:
base:
- /srv/pillar/base
prod:
- /srv/pillar/prod


创建目录结构并重启salt-master:
mkdir -p /srv/salt/{base,prod}
mkdir -p /srv/pillar/{base,prod}

/etc/init.d/salt-master restart

3.2 YAML编写技巧

3.2.1 什么是YAML
YAML语法:结构使用空格来表示;项目使用"-"来表示;键值使用":"来分割。

3.2.2 规则一:缩进
YAML使用一个固定的缩进风格表示数据层级结构关系。
SaltStack需要每个缩进级别由两个空格组成。

3.2.3 规则二:冒号
value可以通过缩进与key进行连接。
my_key:
my_value

对字典进行嵌套:
first_level_dict_key:
second_level_dict_key: value_in_second_level_dict

3.2.4 规则三:短横杠
表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表的一部分。
- list_value_one
- list_value_two
- list_value_three

注意:每个冒号的后面都有一个空格(表示路径的除外)!

3.3 Jinja使用技巧

3.3.1 什么是Jinja
Jinja是基于Python的模板引擎。SaltStack默认使用yaml_jinja渲染器。
yaml_jinja的流程是先用jinja2模板引擎处理SLS,然后再调用YAML解析器。

3.3.2 如何区分模板文件
在SaltStack中,files和templates都使用file这个states模块。
通过使用template指令指定类型来区分是模板还是普通文件资源:
/etc/zabbix_agentd.conf:
file.mangled:
- name: /etc/zabbix_agentd.conf
- source: salt://zabbix/files/zabbix_agentd.conf
- templates: jinja
- defaults:
Server: {{ pillar['zabbix-agent'] ['Zabbix_Server']}}

3.3.3 Jinja基本使用
Jinja有三个步骤:
1) File状态使用template参数 -template:jinja
2)模板文件里面变量使用{{名称}},比如{{PORT}}
3)File状态模块要指定变量列表:
- defaults:
PORT:8080

Jinja变量使用Grains:
{{ grains['fqdn_ip4']}}
Jinja变量使用执行模块:
{{ salt[network.hw_addr]('eth0') }}
Jinja变量使用Pillar:
{{ pillar['apache'] ['PORT'] }}

3.3.4 Jinja逻辑关系
Jinja用来给状态增加逻辑关系。
例如:当你的环境同时存在CentOS和Ubuntu时,Apache软件包的名字是不同的,通过Jinja的逻辑语法来指定:
{% if grains['os'] == 'RedHat' %}
apache: httpd
{% elif grains['os'] == 'Debian' %}
apache: apache2
{% endif %}

3.4 系统初始化
建议将所有的服务器都会涉及的基础配置或者软件部署归类放在base环境下。

3.4.1 DNS配置
只需要使用SaltStack的File状态模块中的Mangled方法管理resolv.conf文件即可:
vi /srv/salt/base/init/dns.sls
/etc/resolv.conf
file.mangled:
- source: salt://init/files/resolv.conf
- user: root
- group: root
- mode: 644

编写完毕后,需要将resolv.conf放置在/srv/salt/base/init/files/目录下!

3.4.2 history记录时间
使用SaltStack的File状态模块的Append方法,在/etc/profile里面追加设置:
vi /srv/salt/base/init/history.sls
/etc/profile
file.append:
- text:
- export HISTTIMEFORMAT="%F %T `whomi` "

3.4.3 命令操作审计
使用logger将输入的命令写入到messages,也是使用SaltStack的File模块的Append方法。
vi /srv/salt/base/init/audit.sls
/etc/bashrc:
file.append:
- text:
- export PROMPT_COMMAND='{ msg=$(history 1 | read x y; echo $y;}); logger "[euid=$(whomi)]":$(who am i):['pwd']"$msg"; }'

3.4.4 内核参数优化
SaltStack提供了Sysctl状态模块用来进行内核参数的设置。

vi /srv/salt/base/init/sysctl.sls

#设置本地TCP可以使用的端口范围
net.ipv4.ip_local_port_range:
sysctl.present:
- value: 10000 65000

#设置可以打开的最大文件数
fs.file-max:
sysctl.present:
- value: 2000000

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

#尽量不使用交换分区
vm.swappiness:
sysctl.present:
- value: 0

3.4.5 epel仓库
下面安装Zabbix Agent就需要epel仓库。我们需要使用到SaltStack的pkg状态模块,同时还使用了unless做状态执行的判断。
vi /srv/salt/base/init/epel.sls
yum_repo_release:
pkg.installed:
- sources:
- epel-release: http://mirrors.aliyun.com/epel/6/x86_64/epel-release-6-8.noarch.rpm
- unless: rpm -qa| grep epel-release-6-8

3.4.6 Zabbix Agent安装
在所有Minion都应该安装上Zabbix Agent,主要涉及SaltStack的pkg,file,service状态模块以及pillar的使用。

通过使用Pillar来设置Zabbix Server的IP地址:
vi /srv/pillar/base/top.sls
base:
'*':
- zabbix

vi /srv/pillar/base/zabbix.sls
zabbix-agent:
Zabbix_Server: 192.168.1.100

安装并启动Zabbix Agent:
cat /srv/salt/base/init/zabbix_agent.sls
zabbix-agent:
pkg.installed:
- name: zabbix22-agent
file.mangled:
- name: /etc/zabbix_agent.conf
- source: salt://zabbix/files/zabbix_agentd.conf
- template:jinja
- defaults:
Server: {{ pillar['zabbix-agent'] ['Zabbix_Server'] }}
- require:
- pkg: zabbix-agent
service.running:
- enable: True
- watch:
- pkg: zabbix-agent
- file: zabbix-agent

Zabbix配置文件目录用来存放用户自定义的配置:
zabbix_agentd.conf.d:
file.directory:
- name: /etc/zabbix_agentd.conf.d
- watch_in:
- service: zabbix-agent
- require:
- pkg: zabbix-agent
- file: zabbix-agent

编写完毕后,将zabbix_agentd.conf文件放置/srv/salt/base/init/files/目录下,同时修改如下:
Include=/etc/zabbix_agentd.conf.d #修改或增加
Server={{Server}} #修改此行

3.4.7 初始化环境引用
再编写一个sls将初始化的功能都包括进来:
vi /srv/salt/base/init/env_init.sls
include:
- init.dns
- init.history
- init.audit
- init.sysctl
- init.epel
- zabbix_agent


在top.sls里面给Minion指定状态并执行:
vi /srv/salt/base/top.sls
base:
'*':
- init.env_init


#对执行状态进行测试
salt '*' state.highstate test=true

#在所有Minion上执行状态
salt '*' state.highstate


3.5 Haproxy配置管理
Haproxy支持四层和七层的负载均衡,多种负载均衡算法和健康检查。

创建目录结构:
mkdir -p /srv/salt/prod/pkg
mkdir -p /srv/salt/prod/haproxy/files
mkdir -p /srv/salt/prod/keepalived/files

3.5.1 pkg配置
使用pkg模块将源码编译依赖的各种包都安装上,使用pkg状态模块的installed方法,同时使用了names列表。

vi /srv/salt/prod/pkg/pkg-init.sls
pkg-init:
pkg.installed:
- names:
- gcc
- gcc-c++
- glibc
- make
- autoconf
- openssl
- openssl-devel

3.5.2 Haproxy服务管理
首先将haproxy源码包和管理脚本放置在/srv/salt/prod/haproxy/files目录下。

●将软件包复制到haproxy的files目录下
cd /usr/local/src/
cp haproxy-1.5.3.tar.gz /srv/salt/test/haproxy/files/
tar zxf haproxy-1.5.3.tar.gz
cd /usr/local/src/haproxy-1.5.3/examples/

该目录下存放了haproxy启动脚本,修改下路径:
sed -i 's/\/usr\/sbin\/'\$BASENAME'/\/usr\/local\/haproxy\/sbin\/'\$BASENAME/g' haproxy.init
●复制到haproxy的files目录下
cp haproxy.init /srv/salt/test/haproxy/files/

3.5.3 编写haproxy安装SLS
安装脚本:
vi /srv/salt/prod/haproxy/install.sls
include:
- pkg.pkg-init
haproxy-install:
file.managed:
- name: /usr/local/src/haproxy-1.5.3.tar.gz
- source: salt://haproxy/files/haproxy-1.5.3.tar.gz
- mode: 755
- user: root
- group: root
cmd.run:
- name: cd /usr/local/src && tar zxf haproxy-1.5.3.tar.gz && cd haproxy-1.5.3 && TARGET=linux26 PREFIX=/usr/local/haproxy && make install PREFIX=/usr/local/haproxy
- unless: test -d /usr/loca/haproxy
- require:
- pkg: pkg-init
- file: haproxy-install


Haproxy的服务管理脚本:
/etc/init.d/haproxy:
file.managed:
- source: salt://haproxy/files/haproxy.init
- mode: 755
- user: root
- group: root
- require:
- cmd: haproxy-install

设置可以监听非本地IP:
net.ipv4.ip_nonlocal_bind:
sysctl.present:
- value: 1

Haproxy的配置文件存放目录:
haproxy-config-dir:
file.directory:
- name: /etc/haproxy
- mode: 755
- user: root

将Haproxy加入到系统服务中:
haproxy-init:
cmd.run:
- name:chkconfig --add haproxy
- unless: chkconfig --list|grep haproxy
- require:
- file: /etc/init.d/haproxy

管理Haproxy的配置文件的两种方法:
●直接在需要使用haproxy的地方引用haproxy的安装,然后加入haproxy的配置文件管理和服务管理。
●使用Jinja模板,将haproxy的基础配置编写完成后,其他的配置通过Pillar来进行自动生成;

3.5.4 Haproxy业务引用
现在编写一个业务模块Cluster,然后调用Haproxy来完成配置管理。这样可以很好的把基础服务的配置管理和业务分开。
●创建cluster目录,并且在cluster目录创建files目录,用来存放配置文件:
mkdir -p /srv/salt/prod/cluster/files
●将haproxy配置文件放置在/srv/salt/prod/cluster/files目录下,以下为最小化配置:
cat /srv/salt/prod/cluster/files/haproxy-outside.cfg
global
maxconn 100000
chroot /usr/local/haproxy
uid 99
gid 99
daemon
nbproc 1
pidfile /usr/local/haproxy/logs/haproxy.pid
log 127.0.0.1 local3 info
●默认参数配置如下:
defaults
option http-keep-alive
maxconn 100000
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
●开启haproxy Status状态监控,增加验证:
listen stats
mode http
bind 0.0.0.0:8888
stats enable
stats uri /haproxy-status
stats auth haproxy:saltstack
●前端设置如下:
frontend frontend_www_example_com
bind 192.168.56.20:80
mode http
option httplog
log global
default_backend backend_www_example_com

●后端设置如下:
backend backend_www_example_com
option forwardfor header X-REAL-IP
option httpchk HEAD / HTTP/1.0
balance source
server web-node1 192.168.56.21:8080 check inter 2000 rise 30 fall 15
server web-node2 192.168.56.22:8080 check inter 2000 rise 30 fall 15

编写haproxy服务管理:
vi /srv/salt/prod/cluster/haproxy-outside.sls
include:
- haproxy.install
haproxy-service:
file.managed:
- name: /etc/haproxy/haproxy.cfg
- source: salt://cluster/files/haproxy-outside.cfg
- user: root
- group: root
- mode: 644
service.running:
- name: haproxy
- enable: True
- reload: True
- require:
- cmd: haproxy-init
- watch:
- file: haproxy-service

3.5.5 执行haproxy状态
在top file中给Minion指定状态。
SaltStack-node1: vi /srv/salt/base/top.sls
base:
'*':
- init.env_init
prod:
'*':
- cluster.haproxy-outside

测试并执行状态:
[root@saltstack-node1 ~]# salt '*' state.highstate test=True
[root@saltstack-node1 ~]# salt '*' state.highstate

3.5.6 查看haproxy状态
启动haproxy,通过浏览器http://IP地址:8888/haproxy-status查看haproxy状态。


3.6 Keepalived配置管理
首先放置源码包、keepalived的启动脚本、sysconfig配置文件在/srv/salt/prod/keepalived/files/目录下。

3.6.1 软件包准备
cd /usr/local/src/
wget http://www.keepalived.org/software/keeaplived-1.2.17.tar.gz

复制到Keepalived的files目录下,并解压:
cp keepalived-1.2.17.tar.gz /srv/salt/prod/keepalived/files
tar xvf keepalived-1.2.17.tar.gz
cd keepalived-1.2.17

将keepalived需要的init脚本的sysconfig复制到files目录下:
cp keepalived/etc/init.d/keepalived.init /srv/salt/prod/keepalived/files/
cp keepalived/etc/init.d/keeaplived.sysconfig /srv/salt/prod/keepalived/files/

手动修改源码包里面的init脚本:
vi /srv/salt/prod/keepalived/files/keepalived.init
将daemon keepalived ${KEEPALIVED_OPTIONS}
修改为: daemon /usr/local/keepalived/sbin/keeaplived ${KEEPALIVED_OPTIONS}

3.6.2 编写keepalived安装SLS
编写keepalived安装配置:
vi install.sls
keepalived-install:
file.managed:
- name: /usr/local/src/keepalived-1.2.17.tar.gz
- source: salt://keepalived/files/keepalived-1.2.17.tar.gz
- mode: 755
- user: root
- group: root
cmd.run:
- name: cd /usr/local/src && tar zxf keepalived-1.2.17.tar.gz && cd keepalived-1.2.17 && ./configure --prefix=/usr/local/keepalived --disable-fwmark && make && make install
- unless: test -d /usr/local/keepalived
- require:
- file: keepalived-install

Keepalived的sysconfig配置文件:
/etc/sysconfig/keepalived:
file.managed:
- source: salt://keepalived/files/keepalived.sysconfig
- mode: 644
- user: root
- group: root

Keepalived的服务管理脚本:
/etc/init.d/keepalived:
file.managed:
- source: salt://keepalived/files/keepalived.init
- mode: 755
- user: root
- group: root

将Keepalived加入系统服务管理:
keepalived-init:
cmd.run:
- name: chkconfig --add keepalived
- unless: chkconfig --list|grep keepalived
- require:
- file: /etc/init.d/keepalived

Keepalived的配置文件目录:
/etc/keepalived:
file.directory:
- user: root
- group: root

3.6.3 Keepalived业务引用
下面列出Keepalived做haproxy高可用的一个最小化的配置模板,该模板文件放置在/srv/salt/prod/cluster/files/目录下。
vi /srv/salt/prod/cluster/files/haproxy-outside-keepalived.conf
! Configuration File For keepalived
global_defs {
notification_email {
saltstack@example.com
}
notification_email_from keepalived@example.com
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id {{ ROUTEID}}
}

vrrp_instance haproxy_ha {
state {{STATEID}}
interface eth0
virtual_router_id 36
priority {{PRIORITYID}}
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.56.20
}
}

在Cluster业务目录下编写Haproxy使用Keepalived做高可用的sls:
cat /srv/salt/prod/cluster/haproxy-outside-keepalived.sls
include:
- keepalived.install
keepalived-server:
file.managed:
- name: /etc/keepalived/keepalived.conf
- source: salt://cluster/files/haproxy-outside-keepalived.conf
- mode: 644
- user: root
- group: root
- template: jinja

{% if grains['fqdn'] == 'saltstack-node1.example.com' %}
- ROUTEID: haproxy_ha
- STATEID: MASTER
- PRIORITYID: 150

{% elif grains['fqdn'] == 'saltstack-node2.example.com' %}
- ROUTEID: haproxy_ha
- STATEID: BACKUP
- PRIORITYID: 100
{% endif %}
service.running:
- name: keepalived
- enable: True
- watch:
- file: keepalived-server

在这个描述文件中,使用了Jinja模板的判断函数,通过grains获取服务器的FQDN名,然后根据不同的FQDN名设置不同变量的值。将saltstack-node1.example.com设置
为Keepalived的主节点,另外一台设置为Keepalived的备节点。

3.6.4 执行Keepalived状态
编写完毕后,在top file里面指定Minion运行该状态:
vi /srv/salt/base/top.sls
base:
'*':
- init.env_init
prod:
'*':
- cluster.haproxy-outside
- cluster.haproxy-outside-keepalived

3.6.5 Haproxy+Keepalived测
可以使用ip ad li查看目前的VIP是否在该节点: ip ad li eth0


3.7 Memcached配置管理
在负载均衡环境下遇到Session问题,一般的解决方法有三种:
●Session保持
●Session复制
●Session共享

创建目录结构:
mkdir -p /srv/salt/prod/{libevent,memcached}/files
mkdir /srv/salt/prod/user

3.7.1 www用户配置
启动memcached需要使用www用户,我们将www用户的配置单独放置在user目录下:
vi /srv/salt/prod/user/www.sls
www-user-group:
group.present:
- name: www
- gid: 1000
user.present:
- name: www
- fullname: www
- shell: /sbin/nologin
- uid: 1000
- gid: 1000

3.7.2 libevent配置
源码包:
cd /srv/salt/prod/libevent/files/

编写Libevent部署SLS:
vi /srv/salt/prod/libevent/install.sls
libevent-source-install:
file.managed:
- name: /usr/local/src/libevent-2.0.22-stable.tar.gz
- source: salt://libevent/files/libevent-2.0.22-stable.tar.gz
- user: root
- group: root
- mode: 644
cmd.run:
- name: cd /usr/local/src && tar zxf libevent-2.0.22-stable.tar.gz && cd libevent-2.0.22-stable && ./configure --prefix=/usr/local/libevent && make && make install
- unless: test -d /usr/local/libevent
- require:
- file: libevent-source-install

3.7.3 Memcached配置
编写Memcached部署SLS如下:
vi /srv/salt/prod/memcached/install.sls
include:
- libevent.install
memcached-source-install:
file.managed:
- name: /usr/local/src/memcached-1.4.24.tar.gz
- source: salt://memcached/files/memcached-1.4.24.tar.gz
- user: root
- group: root
- mode: 644
cmd.run:
- name: cd /usr/local/src && tar zxf memcached-1.4.24.tar.gz && cd memcached-1.4.24 && ./configure --prefix=/usr/local/memcached --enable-64-bit --with-libevent=/usr/local/libevent && make && make install
- unless: test -d /usr/local/memcached
- require:
- cmd: libevent-source-install
- file: memcached-source-install

3.7.4 Memcache服务
使用cmd.run来启动memcached进程。
vi /srv/salt/prod/memcached/service.sls
include:
- memcached.install
- user.www

memcached-service:
cmd.run:
- name: /usr/local/memcached/bin/memcached -d -m 128 -p 11211 -c 8096 -u www
- unless: netstat -ntlp|grep 11211
- require:
- cmd: memcached-source-install
- user: www-user-group

3.7.5 执行Memcached状态
在top file里面进行定义:
vi /srv/salt/base/top.sls
base:
'*':
- init.env_init
prod:
'*':
- cluster.haproxy-outside
- cluster.haproxy-outside-keepalived
'saltstack-node2.example.com':
- memcached.service

先测试后执行状态:
salt '*' state.highstate test=True
salt '*' state.highstate

3.8 Nginx配置管理
Nginx+PHP需要安装的包首先有Nginx和PHP,需要进行编译安装,步骤如下:
1)所有源码包的编译安装需要依赖一些基础安装包,像gcc,make
2)源码编译安装Nginx时需要依赖PCRE,所以需要有一个PCRE模块来安装PCRE,然后Nginx进行include即可
3)需要编译安装PHP,除了PHP常用的模块之外,还应该支持Memcached和Redis这样的第三方模块。

需要使用到的功能如下:
●使用状态模块: file,cmd,service
●使用状态间关系: require,unless
●SLS之间的include

创建目录结构:
mkdir -p /srv/salt/prod/{pcre,nginx,php}/files
创建完目录结构后,需要把源码包放置在各个服务目录的files目录下:
wget http://nginx.org/download/nginx-1.8.0.tar.gz
cp nginx-1.8.0.tar.gz /srv/salt/prod/nginx/files
wget http://cn2.php.net/distributions/php-5.6.9.tar.gz

3.8.1 PCRE模块
编写状态文件如下:
vi /srv/salt/prod/pcre/install.sls
pcre-source-install:
file.managed:
- name: /usr/local/src/pcre-8.37.tar.gz
- source: salt://pcre/files/pcre-8.37.tar.gz
- user: root
- group: root
- mode: 755
cmd.run:
- name: cd /usr/local/src && tar zxf pcre-8.37.tar.gz && cd pcre-8.37 && ./configure --prefix=/usr/local/pcre && make && make install
- unless: test -d /usr/local/pcre
- require:
- file: pcre-source-install

3.8.2 Nginx模块
编写状态文件:
vi /srv/salt/prod/nginx/install.sls
#将PCRE的安装包含进来
include:
- pcre.install
- user.www
#Nginx编译安装
nginx-source-install:
file.managed:
- name: /usr/local/src/nginx-1.9.1.tar.gz
- source: salt://nginx/files/nginx-1.9.1.tar.gz
- user: root
- group: root
- mode: 755
cmd.run:
- name: cd /usr/local/src && tar zxf nginx-1.9.1.tar.gz && cd nginx-1.9.1 && ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-http_stub_status_module --with-file-aio --with-http_dav_module --with-pcre=/usr/local/src/pcre-8.37 && make && make install && chown -R www:www /usr/local/nginx
- unless: test -d /usr/local/nginx
- require:
- user: www-user-group
- file: nginx-source-install
- pkg: pkg-init
- cmd: pcre-source-install

3.8.3 Nginx配置文件
Nginx模块作为基础模块,nginx.conf里面写的是所有业务公用的配置,然后每个业务具体的Server配置通过Nginx的include指令来实现。
vi /srv/salt/prod/nginx/files/nginx.conf
user www;
worker_processes 16;
error_log logs/error.log error;
worker_rlimit_nofile 30000;
pid logs/nginx.pid;
events {
use epoll;
worker_connections 65535;
}

http {
include mime.type;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
underscores_in_headers on;
keepalive_timeout 10;
send_timeout 60;
include /usr/local/nginx/conf/vhost/*.conf;
server {
listen 8080;
server_name 127.0.0.1
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
}

3.8.4 编写Nginx服务SLS
单独编写Nginx的service.sls以启动服务和增加配置文件。
vi /srv/salt/prod/nginx/service.sls
include:
- nginx.install
nginx-init:
file.managed:
- name: /etc/init.d/nginx
- source: salt://nginx/files/nginx-init
- mode: 755
- user: root
- group: root
cmd.run:
- name: chkconfig --add nginx
- unless: chkconfig --list|grep nginx
- require:
- file: nginx-init
/usr/local/nginx/conf/nginx.conf
file.managed:
- source: salt://nginx/files/nginx.conf
- user: www
- group: www
- mode: 644
nginx-service:
file.directory:
- name: /usr/local/nginx/conf/vhost
- require:
- cmd: nginx-source-install
service.running:
- name: nginx
- enable: True
- reload: True
- require:
- cmd: nginx-init
- watch:
- file: /usr/local/nginx/conf/nginx.conf

3.8.5 PHP(FastCGI)配置管理
对于PHP的源码编译安装,使用FastCGI模式,FastCGI模式涉及三个文件:php.ini, php-fpm.conf和fastcgi的启动脚本。
vi /srv/salt/prod/php/install.sls
pkg-php:
pkg.installed:
- names:
- mysql-devel
- openssl-devel
- swig
- libjpeg-turbo
- libjpeg-turbo-devel
- libpng
- libpng-devel
- freetype
- freetype-devel
- libxml2
- libxml2-devel
- zlib
- zlib-devel
- libcurl
- libcurl-devel
php-source-install:
file.managed:
- name: /usr/local/src/php-5.6.9.tar.gz
- source: salt://php/files/php-5.6.9.tar.gz
- user: root
- group: root
- mode: 755
cmd.run:
- name: cd /usr/local/src && tar zxf php-5.6.9.tar.gz && cd php-5.6.9 && ./configure --prefix=/usr/local/php-fastcgi --with-pdo-mysql=mysqlnd --with-mysqli=mysqlnd --with-mysql=mysqlnd
--with-jpeg-dir --with-png-dir --with-zlib --enable-xml --with-libxml-dir --with-curl --enable-bcmatch --enable-shmop
--enable-sysvsem --enable-inline-optimization --enable-mbregex --with-openssl --enable-mbstring --with-gd --enable-gd-native-ttf
--with-freetype-dir=/usr/lib64 --with-gettext=/usr/lib64 --enable-sockets --with-xmlrpc --enable-zip --enable-soap
--disable-debug --enable-opcache --enable-zip --with-config-file-path=/usr/local/php-fastcgi/etc --enable-fpm
--with-fpm-user=www --with-fpm-group=www && make && make install
- require:
- file: php-source-install
- user: www-user-group
- unless: test -d /usr/local/php-fastcgi

pdo-plugin:
cmd.run:
- name: cd /usr/local/src/php-5.6.9/ext/pdo_mysql/ && /usr/local/php-fastcgi/bin/phpize && ./configure --with-php-config=/usr/local/php-fastcgi/bin/php-config && make && make install
- unless: test -f /usr/loca/php-fastcgi/lib/php/extensions/*/pdo_mysql.so
- require:
- cmd: php-source-install

php-ini:
file.managed:
- name: /usr/local/php-fastcgi/etc/php.ini
- source: salt://php/files/php.ini-production
- user: root
- group: root
- mode: 644

php-fpm:
file.managed:
- name: /usr/local/php-fastcgi/etc/php-fpm.conf
- source: salt://php/files/php-fpm.conf.default
- user: root
- group: root
- mode: 644

php-fastcgi-service:
file.managed:
- name: /etc/init.d/php-fpm
- source: salt://php/files/init.d.php-fpm
- user: root
- group: root
- mode: 755
cmd.run:
- name: chkconfig --add php-fpm
- unless: chkconfig --list | grep php-fpm
- require:
- file: php-fastcgi-service
service.running:
- name: php-fpm
- enable: True
- require:
- cmd: php-fastcgi-service
- watch:
- file: php-ini
- file: php-fpm

3.8.6 PHP Redis模块
vi /srv/salt/prod/php/php-redis.sls
redis-plugin:
file.managed:
- name: /usr/local/src/phpredis-2.2.7.tgz
- source: salt://php/files/phpredis-2.2.7.tgz
- user: root
- group: root
- mode: 755
cmd.run:
- name: cd /usr/local/src && tar zxf phpredis-2.2.7.tgz && cd phpredis-2.2.7 && /usr/local/php-fastcgi/bin/phpize && ./configure --with-php-config=/usr/local/php-fastcgi/bin/php-config && make && make install
- unless: test -f /usr/local/php-fastcgi/lib/php/extensions/*/redis.so
- require:
- file: redis-plugin
- cmd: php-install
/usr/local/php-fastcgi/etc/php.ini:
file.append:
- text:
- extensions=redis.so

3.8.7 PHP Memcached模块
PHP连接memcache有两个扩展模块:Memcache和Memcached.

PHP memcache扩展包如下:
vi /srv/salt/prod/php/php-memcache.sls
memcache-plugin:
file.managed:
- name: /usr/local/src/memcache-2.2.7.tgz
- source: salt://php/files/memcache-2.2.7.tgz
- user: root
- group: root
- mode: 755
cmd.run:
- name: cd /usr/local/src && tar zxf memcache-2.2.7.tgz && cd memcache-2.2.7 && /usr/local/php-fastcgi/bin/phpize && ./configure --enable-memcache --with-php-config=/usr/local/php-fastcgi/bin/php-config && make && make install
- unless: test -f /usr/local/php-fastcgi/lib/php/extensions/*/memcache.so
- require:
- file: memcache-plugin
- cmd: php-install
/usr/local/php-fastcgi/etc/php.ini:
file.append:
- text:
- extension=memcache.so

3.9 业务应用模块

3.9.1 BBS论坛案例
安装Nginx+PHP环境和PHP Memcache模块!
(1)创建目录结构
mkdir -p /srv/salt/prod/web/files/
(2)给一个Nginx虚拟主机配置文件的例子
vi /srv/salt/prod/web/files/bbs/conf
server {
listen 8080;
root /usr/local/nginx/html;
index index.htm index.html index.php
location ~ \.php\$
{
fastcgi_pass unix:/usr/local/php-fastcgi/php-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
}

编写bbs.sls
vi /srv/salt/prod/web/bbs.sls
include:
- php.install
- nginx.service

web-bbs:
file.managed:
- name: /usr/local/nginx/conf/vhost/bbs.conf
- source: salt://web/files/bbs.conf
- user: root
- group: root
- mode: 644
- require:
- service: php-fastcgi-service
- watch:
- service: nginx-service

3.9.2 修改top.sls
vi /srv/salt/base/top.sls
base:
'*':
- init.env_init
prod:
'*':
- cluster.haproxy-outside
- cluster.haproxy-outside-keepalived
- web.bbs
'saltstack-node2.example.com':
- memcached.service


3.9.4 案例扩展的思路
●使用Grains区分不同的操作系统
●使用Pillar实现更灵活的配置文件管理
●修改案例的状态文件,使用更好的编写方法
●如何将现有环境中的各种服务使用SaltStack进行管理


----------------------------------------------------------------------------------------------------------------------------------------

第4章 扩展SaltStack组件

4.1 扩展Grains
Grains能收集Minion的各种静态信息!

4.1.1 理解扩展Grains流程
扩展Grains流程:
(1)在Master上编写一个Python脚本。这个脚本的主要内容是定义如何收集你想要的信息。在脚本的最后把采集到的各种信息返回。
(2)需要把这个脚本sync同步到所有的Minion上。

Python脚本内容如下:
cat /srv/salt/_grains/example.py
#!/bin/python
def grains():
local={}
test={'key':'value','key1':'value1','key2':'value2'}
local['list']= [1,2,3,4]
local['string'] = 'str'
local['dict'] = test
return local

将脚本同步到minion上:
SaltStack@Master: salt 'Minion' saltutil.sync_grains
文件默认被同步到Minion端的/var/cache/salt/minion/extmods/grains/目录下!

第二种方法:
salt '*' cp.get_file salt://_grains/example.py /tmp/example.py

说明:Python脚本存放在Master端的/srv/salt/_grains目录下,将其复制到Minion端的/tmp目录下。其中salt://表示的就是/srv/salt,这个参数在Master配置文件/etc/salt/master中的file_roots进行定义。

#查看Python脚本是否复制到Minion端
salt '*' cmd.run 'ls /var/cache/salt/minion/extmods/grains/'

#在Master端查看使用脚本定义的Grains信息
salt '*' grains.item list string dict

4.1.2 扩展Grains案例


[root@SaltStack-Master _grains]# more info.py
#!/usr/bin/python
import commands
import simplejson
import urllib

def role():
information={}
information['disk_num'] = commands.getoutput('fdisk -l|grep Disk|wc -l')
information['disk_big'] = commands.getoutput("fdisk -l|grep Disk|grep /dev/sda1|awk '{print $3}'")
f=open('/etc/sysconfig/network')
line=f.readlines()
for i in list(line):
if i.split('=')[0] == 'HOSTNAME':
host=i.split('=')[1]
a=urllib.urlopen('http://192.168.236.101:36000/device/' + host).read()
ldev = simplejson.loads(a)
for dev in ldev:
if dev.has_key('appList'):
for app in dev['appList']:
if app.startswith('CPISF'):
information['type']= app
information['node']= '-'.join(host.split('-')[1:3])
return information

4.2 扩展Module

4.2.1 理解扩展Module原理
cat /usr/lib/python2.6/site-packages/salt/modules/dig.py

# -*- coding:utf-8 -*-
'''
compendium of generic DNS utilities
'''
from __future__ import absolute_import

#Import python libs
import logging
import re
import socket

log = logging.getLogger(__name__)

__virtualname__ = 'dig'

def __virtual__():
'''
Only load module if dig binary is present
'''
return True if salt.utils.which('dig') else False


def A(host,nameserver=None):
'''
Return the A record for ``host``.
Always returns a list.
CLI Example:
.. code-block:: bash
salt nsl dig.A.www.google.com
'''
dig = ['dig','+short',str(host),'A']
if nameserver is not None:
dig.append('@{0}'.format(nameserver))

cmd = __salt__['cmd.run_all'](dig,python_shell=False)
#In this case,0 is not the same as False
if cmd['recode'] !=0:
log.warn(
'dig returned exit code \'{ 0}\'.Returning empty list as '
'failback.'.format(
cmd['retcode']
)
)
return []
return [x for x in cmd['stdout'].split('\n') if check_ip(x) ]

4.2.2 扩展Module案例
cat /srv/salt/_modules/puppet.py
#!/usr/bin/python
# -*- coding:utf-8 -*-

from __future__ import absolute_import
from salt.ext.six.moves.urllib.request import urlopen as _urlopen
import salt.utils
import salt.utils.decorators as decorators
@decorators.memoize
def __detect_os():
return salt.utils.which('puppet')

def __virtual__():
if __detect_os():
return True
return False

def setmaster(master='www.shencan.net',config_file='/etc/puppet/puppet.conf'):
'''
salt \* puppet.setmaster www.shencan.net
:param master:
:param config_file:
:return:
'''
check = 'grep server {0}'.format(config_file)
outcheck = __salt__['cmd.run'](check)
if outcheck:
cmdline = 'sed -i "s/server = .*/server = {0}/g" {1}'.format(master,config_file)
output = __salt__['cmd.run'](cmdline)
return 'has change server to {0}'.format(master)
else:
cmdline = 'echo " server = {0}" >> {1}'.format(master,config_file)
output = __salt__['cmd.run'](cmdline)
return 'has change server to {0} need restart the service'.format(master)

def version():
'''
salt '*' puppet.version
:return:
'''
cmd = 'rpm -qf {0}'.format(__detect_os())
output = __salt__['cmd.run'](cmd).splitlines()
ret = output[0].split(':')
return ret[-1]

def service(signal=None):
'''
salt '*' puppet.service start
:param signal:
:return:
'''
status = ('start','stop','status','restart','reload','force-reload','condrestart','once','genconfig')
if signal not in status:
return 'puppet can not support this signal'
cmdline = '/etc/init.d/puppet' + '{0}'.format(signal)
output = __salt__['cmd.run'](cmdline)
return output

def master(config_file='/etc/puppet/puppet.conf'):
'''
salt \* puppet.master
:param config_file:
:return:
'''
cmdline='grep server' + '{0}'.format(config_file)
output = __salt__['cmd.run'](cmdline,python_shell=False)
if output:
return output
else:
return 'puppet server not setting'


上述脚本包含的4个主要函数,实现4个功能:
●setmaster函数主要指定puppetserver地址
●version函数是查看minion上puppet的版本
●service函数是去管理puppet的服务状态
●master函数是查看目前puppet配置文件里面定义的server地址

4.3 扩展state

4.3.1 理解扩展state原理

4.4 ext_pillar与ext_nodes

4.4.2 理解ext_nodes流程和案例
官方关于top.sls通过动态方式的方式只有四种形式:
1)通过从MongoDB里面获取Minion与state.sls文件的对应关系:
master_tops:
mongo:
collection:tops
id_field: _id
re_replace:""
re_pattern: \.example\.com
states_field: states
environment_field: environment
2)通过ext_nodes的形式:
master_tops:
ext_nodes: cobbler-ext-nodes
3)通过reclass_adapter的形式:
master_tops:
reclass:
storage_type:yaml_fs
inventory_base_uri: /srv/salt

4)通过cobbler直接获取的方式:
master_tops:
cobbler: {}
cobbler.url: https://example.com/cobbler_api #defauts is http://localhost/cobbler_api
cobbler.user: username #default is no username
cobbler.password: password #default is no password

4.5 SaltStack Git 文件服务器

 

 


----------------------------------------------------------------------------------------------------------
第5章 第三方调用SaltStack

除了salt命令之外,SaltStack还提供了另外两个与其交互的途径:
●只有在salt Master本机才能使用Python API
●可以在远程通过HTTP调用的API

5.1 通过Python API调用

5.1.1 Python API工作原理

1.实例以及工作流程解析
Salt本身的操作实际上在底层都是以一个消息来传输并解析执行的,实际上API要做的就是模拟一个消息并发送到该发送的地方;
Python API就是提供了一个程序的接口,让大家可以很容易的通过这个接口来给SaltStack发送消息。

2.通过API获取SaltStack配置
有些Salt的API接口需要读取SaltStack的opts的目录。

【获取Master配置信息】
#导入saltstack的配置模块
import salt.config

#读取saltstack的配置文件(/etc/salt/master)并赋值给master_opts
master_opts=salt.config.client_config('/etc/salt/master')

#查看master_opts的属性
dir(master_opts)

#查看master_opts类型
type(master_opts)

#以字典形式打印
print dict(master_opts)


【获取Minion配置信息】
#导入salt客户端
import salt.client

#获取客户端配置,并赋值给minion_opts
minion_opts=salt.config.minion_config('/etc/salt/minion')

#查看minion_opts属性
dir(minion_opts)

#查看minion_opts类型
type(minion_opts)

#查看minion_opts的key
minion_opts.keys()


5.1.2 Python API介绍

1.LocalClient
SaltStack默认使用此接口。该接口默认只能在Salt Master本机调用:
>>>import salt.config
>>>local = salt.client.LocalClient()
>>>local.cmd('*','cmd.run',['whoami'])

核心方法
cmd(tgt,fun,arg=(),timeout=None,expr_form='glob',ret='',jid='',kwarg=None,**kwargs)
●tgt: 即target,执行该命令的目标机器、字符串或列表
●fun: 字符串或列表,执行的模块

支持一次执行多个模块命令、一次对多个模块进行调用时,需要arg和fun都是一个列表,而且两者的顺序要一一对应。
当某个模块没有参数时,在arg里放一个空列表。代码如下:
local.cmd('*',[
'grains.items',
'sys.doc',
'cmd.run',
],
[
[],
[],
['uptime'],
])

参数说明如下:
●arg: 列表或者一个由列表组成的列表,对应模块的参数;
●timeout: Minion返回的超时时间
●expr_form: 匹配模式,可选项:glob,pcre,list,grain,grain_pcre,pillar,pillar_pcre,noegroup,range,compund
●ret: 使用的returner,一个或者多个returner(多个用逗号隔开)
●kwarg: 方法的字典形式参数
●kwargs: 可选的参数

使用external_auth时,token可以当作一个可选参数,如:
local.cmd('*','test.ping',username='saltdev',password='saltdev',eauth='pam')
local.cmd('*','test.ping',token='5871821a51754fdcea8153c1c745433')

其他方法

●异步执行
cmd_async(tgt,fun,arg=(),expr_form='glob',ret='',jid='',kwarg=None, **kwargs)
●批量执行
cmd_batch(tgt,fun,arg=().expr_form='glob',ret='',kwarg=None,batch='10%',**kwargs)
●随机执行
cmd_subset(tgt,fun,arg=(),expr_form='glob',ret='',kwarg=None,sub=3,cli=False,progress=False,**kwargs)

 

2.Salt Caller
Salt Caller的功能是在Minion端通过API调用SaltStack,salt-call后端调用的就是这个接口。

3.RunnerClient
RunnerClient的功能是在Master端通过Python调用runner(调用此接口的系统用户需与运行Master的用户一致).
Salt-run后端调用的是这个接口。

4.WheelClient
为SaltStack wheel模块提供的程序接口(调用此接口的系统用户需与运行Master的用户一致)
>>>opts=salt.config.master_config('/etc/salt/master')
>>>wheel=salt.wheel.Wheel(opts)
>>>wheel.call_func('key.list_all')

5.2 通过RESTful API调用
当我们在其他机器或者通过第三方调用SaltStack时,就需要这个。

5.2.1 SaltStack的API是在Master和Minion之外的一个独立的服务,所以需要独立部署,API服务需要部署在Master服务器上。

1.部署Salt-API服务
yum install gcc make python-devel libffi-devel
pip-python install PyOpenSSL

#生成证书
salt-call tls.create_self_signed_cert

#安装软件
yum install -y salt-api

2.配置用户以及权限
cat /etc/salt/master.d/eauth.conf
external_auth:
pam: 认证模式
saltapi: #用户名
- . #用户权限
- '@wheel'
- '@runner'


#添加用户
useradd -M -s /sbin/nologin saltapi
echo "spassword" |passwd saltapi --stdin

3.配置salt-api服务
cat /etc/salt/master.d/api.conf
rest_cherrypy:
port:8000
ssl_crt: /etc/pki/tls/certs/localhost.crt #使用前面生成的证书
ssl_key: /etc/pki/tls/certs/localhost.key

4.启动服务
/etc/init.d/salt-api restart
netstat -lnp|grep 8000

5.2.2 通过Restfu API实现日常操作
1)运行远程模块
2)查询指定job
3)运行runner

 

 

---------------------------------------------------------------------------------------------
第6章 SaltStack架构扩展

6.1 无Master架构

6.1.1 设置无Master运行
让Salt Minion在无Master的架构下运行,需要修改Minion的配置文件。
将file_client修改为local,默认是remote。同时还需要和Salt Master一样,设置file_roots和pillar_roots
vi /etc/salt/minion
file_client: local
file_roots:
base:
- /srv/salt/
pillar_roots:
base:
- /srv/pillar


6.1.2 关闭salt-minion
/etc/init.d/salt-minion stop


6.1.3 使用salt-call执行状态
使用salt-call命令,如下所示:
salt-call --local state.highstate

--local: 告诉salt-minion在本地文件系统上寻找state tree,而不是连接Salt Master.


6.2 多Master架构

6.2.1 配置多Master
yum -y install salt-master

6.2.2 Master数据存储
哪些master上的数据需要在所有Master之间进行数据的同步,有如下几种:
1.Master Keys
多Master的配置中,所有的Master使用同样的private key.这些private key是在Master第一次启动时自动生成的,所以在多Master环境建立时,
需要从原始的Master上复制其private key和public key至第二个Master,覆盖掉冗余Master自动生成的Key(只要启动过第二个Master就会自动生成).

Master的private key默认存储在/etc/salt/pki/master/master.perm,public key默认存储在/etc/salt/pki/master.pub.
将key复制到新增的master上需要确保新增的master上并没有minion连接进来。

2.Minion keys
Minion的keys需要每个Master都进行accept,可以使用salt-key手动接受Minion的key,也可以在Master间保持key目录的同步。需要同步的目录有:
●/etc/salt/pki/master/minions
●/etc/salt/pki/master/minions_pre
●/etc/salt/pki/master/minions_rejected

3.file_roots
file_roots的内容需要在Master间同步以保持一致。这里存放Salt State配置管理文件。推荐同步内容使用gifs backend,或者直接将file_roots存储在共享存储上。


4.pillar_roots
需保持Pillar数据一致。

5.Master Configuration
确保有关Master的配置选项在所有Master节点间是同步的。建议直接将原始的Master配置文件复制过去即可。

6.2.3 设置Minion
多Master在Minion节点,就是在Minion的配置文件中设置多个master列表即可。
vi /etc/salt/minion
master:
- 192.168.56.21
- 192.168.56.22

6.3 Salt Syndic

Syndic运行在一个master上,并且连接到另外一个Master(可称为高级Master)。
然后Syndic Minion所连接的高级Master就可以直接连接到运行Syndic的Master上的Minion.

6.3.1 Syndic配置
Syndic没有自己的配置文件,它是Salt Master的一个组件:
yum -y install salt-syndic
vi /etc/salt/master
syndic_master:192.168.56.22 #设置为高级Master的IP

/etc/init.d/salt-master restart
/etc/init.d/salt-syndic start

6.3.2 高级Master配置
高级Master需要使用order_masters参数来开启:
yum install -y salt-master
vi /etc/salt/master
order_masters:True

6.3.3 Syndic测试
高级Master可以控制一群同时运行着“syndic和master”的节点,通过syndic将操作命令传输给受控Master,受控Master来完成对自己旗下Minion的管理,
并将结果传回高级Master,从而实现高级Master对所有Minion的间接管理。

6.3.4 Syndic是如何工作的
Syndic本质上是一个特殊的Minion,其代码位于minion.py中。
Syndic需要在本地运行Master,并将需要管理的Minions的Master指向syndic所在的主机。
Syndic工作流程;
●冒充Minion,建立与高级Master的连接,订阅所有来自高级Master下发的任务
●接收高级Master下发的数据后,首先进行解密,解密完成后,将其扔到本地的Master接口上进行二次下发
●Syndic在进行二次下发之后,监听本地Event接口,获取所管理的Minions的返回
●将返回发送给高级Master

posted @ 2017-09-01 17:06  foreverfriends  阅读(1535)  评论(0编辑  收藏  举报