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

saltstack取经之路


saltstack取经之路 saltstack取经之路
saltstack取经之路
saltstack取经之路

ywjtshare

运维军团

saltstack取经之路

专注运维技术与传承,分享丰富原创干货


以上是关于saltstack取经之路的主要内容,如果未能解决你的问题,请参考以下文章

多线云改变了西天取经之路

开启Python取经之路-CLASS-6(Part 1)

算法篇:地图算法取经之路

算法篇:地图算法取经之路

saltstack之路--saltstack 使用命令

linux运维架构之路-SaltStack快速入门