saltstack取经之路
Posted 运维军团
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了saltstack取经之路相关的知识,希望对你有一定的参考价值。
1 选择saltstack的初衷
原先线上服务器都是使用puppet来做配置管理,而saltstack的出现,除了能拥有puppet的配置管理外,远程命令执行,结果返回,modules自定义扩展使用都非常方便,salt本身也是使用python编写,运维后台也是python编写,利用salt做二次开发为运维自动化后台管理提供了很大的帮助。
2 saltstack配置管理
2.1 多主机配置
saltstack2014.7版本之后,salt支持同个minion配置多个master
master:
- 1.1.1.1
- 2.2.2.2
不过这种方式存在很多的极限性,两个master的pki必须做同步,master的key同步稍微有点问题,就会影响到了minion客户端。
saltstack2015之后的版本增加了一个参数—saltfile
这个参数应该很少人会注意到,也是用于配置多个master,可以启动多一个实例,这会就出现了两个master,两个minion,客户端起到很好的一个备用效果,关键在于两个master即使接收客户端的key不一样,也不会影响到客户端的启动
2.2 纯py sls渲染
大家看到sls 纯py渲染应该会很陌生,这块在网上的资料就近乎于无,今天既然说到高级篇,就来介绍下纯py sls渲染器,有些功能可以更灵活的定制。就来说下sls py的渲染器,我们看下系统默认的sls模版
/root/.toprc:
file.managed:
- source: salt://files/environment/toprc
- user: root
- group: root
- mode: 0644
传统的sls语法格式大家都熟悉,我们下面来看下纯py渲染sls格式
#!py
#coding: utf-8
def run():
goldfile = '/root/.toprc'
source = 'salt://files/environment/toprc'
user = 'root'
group = 'root'
mode = 644
values = {}
values[goldfile] = {}
FileManged = []
FileManged.append('managed')
FileManged.append({'source': source})
FileManged.append({'user': user})
FileManged.append({'group': group})
FileManged.append({'mode': mode})
values[goldfile]['file'] = FileManged
return values
第一行声明的是使用py渲染器,不使用默认的渲染器,后面就是我们自己的自定义函数,只要返回结果符合salt返回的数据结果就好,和默认的执行方式是一样的,使用我们自己编写的函数,可以更加方便的引入模块,定制自己的功能,灵活性会高很多。
3 saltstack在应用上遇到的问题
3.1 结果统计
saltstack终端执行缺少统计功能,结果返回丢失或者节点挂掉,执行完成后并没有进行统计哪些成功或者哪些失败。原理是发出去的minion个数-返回的minion个数,就是节点丢失的个数,关键代码是:
for fn_ret in self.get_cli_event_returns(
pub_data['jid'],
pub_data['minions'],
self._get_timeout(timeout),
tgt,
expr_form,
verbose,
progress,
**kwargs):
if not fn_ret:
continue
minions_ret_info.append((fn_ret.keys())[0])
if fn_ret.values()[0].get('out',None) == "no_return":
minions_ret_notinfo.append(fn_ret.keys()[0])
else:
count_success=count_success+1
yield fn_ret
for m in pub_data['minions']:
if 0==minions_ret_info.count(m):
minions_ret_notinfo.append(m)
效果如下:
[root@dev-release-1.1.1.1 ~]# salt '1.1.1.1' test.ping
1.1.1.1:
Minion did not return. [No response]
salt_log:
----------
information_returned_fail:
1
information_returned_success:
0
jid:
20170221154124875498
minions_ret_notinfo:
- 1.1.1.1
total_minion:
1
3.2 脚本解析
cmd.script执行脚本被解析,导致脚本执行报错(这个在2015.8版本看官网已经修复)
测试案例脚本
# cat /srv/salt/scripts/test.sh
#!/bin/bash
echo ${#aaa}
这个脚本脚本正常在cmd.script执行后应该返回0,结果是返回空的
解决方案:
modules/cmdmod.py 的def script 函数的template改为None,不对脚本进行解析
template=None
3.3 环境变量
环境变量这个问题比较恶心,经常本地执行没问题,通过master跑完后包含中文的各种乱码,这个会导致什么问题呢?
1. 脚本里面有中文或者有中文输出到日志里面变成乱码
2. 通过cmd.script对数据库执行包含中文的sql时,到数据变成了乱码,很严重的一个问题。。。。。
查看下本机系统的环境变量
[root@localhost ~]# locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
saltstack cmd.run执行locale后的环境变量为:
[root@localhost ~]# salt '127.0.0.1' cmd.run 'locale'
127.0.0.1:
LANG=en_US..UTF-8
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=C
通过上面可以发现,通过saltstack执行后环境变量都变了。
解决方案:
modules/cmdmod.py对应修改常用的函数有
def run
def run_all
def script
saltstack默认是env=None,修改为env={"LC_ALL": "en_US.UTF-8"}
3.4 文件同步
saltstack有个文件传输模块cp.get_file,类似于scp,这个模块存在的问题是文件传输过后文件属主和权限没有进行同步,saltstack也有个rsync模块,说到rsync,那还需配置rsync模块和白名单等都比较麻烦,这时cp.rsync_file出现了,解决了文件权限属主同步的问题。原理就是在文件传输的时候,获取该文件的相关信息,传输到目的后对改文件信息进行相应的修改。
部分关键源码如下:
utils/parsers.py 接收参数这里修改,获取文件的相关信息
修改函数 def _mixin_after_parsed(self):
else判断增加
if self.config['fun'] == "cp.rsync_file":
import pwd
import grp
path = self.args[2]
if path.startswith('salt://'):
full = os.path.join(self.config['file_roots']['base'][0],path[7:])
if os.path.isfile(full):
file_stat = os.stat(full)
st_user = pwd.getpwuid(file_stat.st_uid).pw_name
st_group = grp.getgrgid(file_stat.st_gid).gr_name
st_mode = file_stat.st_mode
self.args.append('st_user=%s'%st_user)
self.args.append('st_group=%s'%st_group)
self.args.append('st_mode=%s'%st_mode)
fileclient.py的 class RemoteClient(Client): 增加rsync_file函数
#目的机器对文件进行相应的授权
fn_ = salt.utils.fopen(dest, 'wb+')
try:
import pwd
import grp
st_uid = pwd.getpwnam(st_user).pw_uid
st_gid = grp.getgrnam(st_group).gr_gid
os.chown(dest, st_uid, st_gid)
os.chmod(dest, st_mode)
except:
pass
[root@dev-release scripts]# ll test.xml
-rw------- 1 admin www 0 Feb 17 11:33 test.xml
[root@dev-release scripts]# salt '192.168.10.11' cp.rsync_file salt://scripts/test.xml /tmp/test.xml
192.168.10.11:
/tmp/test.xml
salt_log:
----------
information_returned_fail:
0
information_returned_success:
1
jid:
20170217113408596055
minions_ret_notinfo:
total_minion:
1
[root@dev-release scripts]# salt '192.168.10.11' cmd.run 'ls -l /tmp/test.xml'
192.168.10.11:
-rw------- 1 admin www 0 Feb 17 11:34 /tmp/test.xml
salt_log:
----------
information_returned_fail:
0
information_returned_success:
1
jid:
20170217113430065398
minions_ret_notinfo:
total_minion:
1
可以看到,文件的权限和属组都同步过去了
3.5 结果丢失
国内网络错综复杂,客户端到服务端之间也常会出现网络丢包情况,如果某个时刻刚好返回结果的时候网络出现丢包,就会出现结果返回到master丢失,master收不到结果.通过增加重发功能,能大大的提高master的结果接收
源码修改:
minion.py的def _return_pub 函数
except SaltReqTimeoutError: 修改为
except SaltReqTimeoutError:
msg = ('The minion failed to return the job information for job '
'{0}. Retry send to backup master {1} again and send success. ').format(jid,self.opts['master'])
try:
ret_val = channel.send(load, timeout=timeout)
log.warn(msg)
except SaltReqTimeoutError:
msg = ('The minion failed to return the job information for job '
'{0}. Retry send to backup master {1} again and send fail. ').format(jid,self.opts['master'])
log.warn(msg)
return ''
4 saltstack打包
大家知道,如果管理的机器众多,不可能每台机器都是通过yum来安装,yum安装还会出现不同系统不同版本,比如centos5用yum出来的zeromq消息中间件就是比较老的版本,经常会出现结果返回问题,客户端挂掉等情况,其次是yum版本更新的又快,还需要对定制的功能进行重新的覆盖,不同版本的管理就会非常的混乱。这时对saltstack进行打包,将相关的插件都打包进一个目录,解析后就能直接使用,就会相当的方便。
打包工具:virtualenv
下面附上一个saltstack 2014.7.0版本的打包过程,其他版本的也是类似
安装
使用 pip 安装
$ pip install virtualenv
使用yum安装
yum install python-virtualenv python-pip python-devel
创建 virtualenv
cd /usr/local
virtualenv saltstack
激活 virtualenv
cd /usr/local/saltstacksource ./bin/activate
这时vitualenv已经激活,可以看到终端发生了变化
开始salt的打包
#安装这个swig是为了后面安装M2Crypto所需要的,不然会报错
yum install swig
#zeromq
wget https://archive.org/download/zeromq_4.1.3/zeromq-4.1.3.tar.gz
./configure --prefix=/usr/local/saltstack
make
make install
pip install pyzmq --install-option="--zmq=/usr/local/saltstack"
pip install msgpack-python MarkupSafe requests PyYAML pycrypto jinja2
#M2Crypto
wget http://pypi.python.org/packages/source/M/M2Crypto/M2Crypto-0.21.1.tar.gz#md5=f93d8462ff7646397a9f77a2fe602d17 --no-check-certificate
#32位系统需要增加
#ln -s /usr/include/openssl/opensslconf-i386.h /usr/include/openssl/opensslconf-i686.h./fedora_setup.sh install
#salt
wget --no-check-certificate https://pypi.python.org/packages/source/s/salt/salt-2014.7.0.tar.gz
cd salt-2014.7.0
python setup.py install
就是把相关的配置文件、启动文件放到对应的目录下就好,这些可以自己定义,到时从各种对应的目录拷贝到系统的对应目录就可以了
退出vitualenv
$ deactivate
生成可打包环境$virtualenv --relocatable ./
当前的 ENV
相关的可执行文件都被修改为相对路径,你可以打包当前目录,上传到其 它位置直接使用,但是salt是不行的,因为zeromq的特殊性,是使用编译到/usr/local/saltstack下的,所以只能放到/usr/local下,不然会因为没法读取到libzmq.so.5而运行不了
END
全中国只有不到1% 的人关注了运维军团
你是个有眼光的人!
(由于交流群人数已超100人,需要进群的小伙伴可以添加运维小编的微信:Alxy0819)
ywjtshare
运维军团
专注运维技术与传承,分享丰富原创干货
以上是关于saltstack取经之路的主要内容,如果未能解决你的问题,请参考以下文章