saltstack编译安装与小马运维开发
http://potaski.blog.51cto.com/3099084/1317853
本系列文章由初学者写,高手就不要浪费时间了
环境:centos6.2 minimum(最小化安装)
特点:无外网
测试机没有外网,就自己手动源码安装把,的确是要累一些...做个笔记记录一下
官方文档说:安装需求
python >=2.6 <3.0
zeromq >=2.1.9
pyzmp >=2.1.9
pycrypto
msgpack-python
yaml
jinja2
===== 安装流水帐如下了 =====
先安装了salt-0.17,然后一发不可收拾...
启动master报错 - ImportError: No module named yaml
解决
PyYAML-3.10.tar.gz
https://pypi.python.org/pypi/PyYAML/3.10#downloads
启动master报错 - ImportError: No module named jinja2
解决
Jinja2-2.7.1.tar.gz
https://pypi.python.org/pypi/Jinja2/2.7.1
安装jinja2报错 - error: Could not find suitable distribution for Requirement.parse('markupsafe')
解决
MarkupSafe-0.18.tar.gz
https://pypi.python.org/simple/MarkupSafe/
启动master报错 - ImportError: No module named zmq
解决
pyzmq-13.1.0.tar.gz
https://pypi.python.org/pypi/pyzmq/13.1.0#downloads
安装pyzmq报错,其中有一段 - Failed with default libzmq, trying again with /usr/local
解决
libzmq-master.zip
https://github.com/zeromq/libzmq
启动master报错 - ImportError: No module named M2Crypto
M2Crypto-0.21.1.tar.gz
https://pypi.python.org/pypi/M2Crypto/0.21.1
安装m2crypto报错 - /usr/include/openssl/opensslconf.h:31: Error: CPP #error ""This openssl-devel package does not work your architecture?"". Use the -cpperraswarn option to continue swig processing.
error: command 'swig' failed with exit status 1
解决
msgpack-python-0.3.0.tar.gz
https://pypi.python.org/pypi/msgpack-python/0.3.0
然后发现master和minion在运行一段时间后会报以下错误 - NameError: global name 'AES' is not defined
只好在源码中搜索了
[root@DFS-1 salt]# grep -R AES /usr/lib/python2.6/site-packages/salt/
/usr/lib/python2.6/site-packages/salt/crypt.py: from Crypto.Cipher import AES
然后google了一下Crypto.Cipher,解决
解决:
https://pypi.python.org/pypi/pycrypto/2.6
========================
整理一下安装过程:
unzip libzmq-master.zip
cd libzmq-master
./autogen.sh
cd ..
tar zxf PyYAML-3.10.tar.gz
cd PyYAML-3.10
/usr/bin/python setup.py install > install.log
cd ..
tar zxf MarkupSafe-0.18.tar.gz
cd MarkupSafe-0.18
/usr/bin/python setup.py install > install.log
cd ..
tar zxf Jinja2-2.7.1.tar.gz
cd Jinja2-2.7.1
/usr/bin/python setup.py install > install.log
cd ..
tar zxf pyzmq-13.1.0.tar.gz
cd pyzmq-13.1.0
/usr/bin/python setup.py install > install.log
cd ..
tar zxf M2Crypto-0.21.1.tar.gz
cd M2Crypto-0.21.1
sed -i 's/python/\/usr\/bin\/python/g' fedora_setup.sh
# 注:我的默认python版本为2.5,此举为切换运行环境到centos6.2自带的python2.6上
./fedora_setup.sh install
cd ..
tar zxf msgpack-python-0.3.0.tar.gz
cd msgpack-python-0.3.0
/usr/bin/python setup.py install > install.log
cd ..
tar zxf pycrypto-2.6.tar.gz
cd pycrypto-2.6
/usr/bin/python setup.py install > install.log
cd ..
tar zxf salt-0.17.0.tar.gz
cd salt-0.17.0
/usr/bin/python setup.py install > install.log
cd ..
注:安装完后salt在启动后仍然发现一个缺包的warning
[WARNING ] virtualenv not installed, please install first
virtualenv是啥呢,搜索得
https://pypi.python.org/pypi/virtualenv/
不影响使用,慢慢再深入学习
salt运行
源码安装后,还需要手动拷贝配置文件模板到/etc/salt/内
cp salt-0.17.0/conf/master /etc/salt/
cp salt-0.17.0/conf/minion /etc/salt/
salt的master与minion安装方式相同,启动不同的服务即可。正确安装完毕后可以看到一批salt命令
[root@DFS-1 ~]# salt
salt salt-call salt-cp salt-key salt-master salt-minion salt-run salt-ssh salt-syndic
启动master:会启动4505、4506端口
[root@DFS-1 ~]# salt-master
启动minion:不启动任何端口
[root@DFS-1 ~]# salt-minion
salt配置
基本上按配置文件模板启动就可以使用,测试中进行了一些自定义
[root@DFS-1 salt]# diff master master.bak |grep "<"
< default_include: /data1/salt/master.d/*.conf # 我在这里单独进行file_root、pillar_root、nodegroup的配置
< publish_port: 4505
< user: root
< max_open_files: 100000
< worker_threads: 1
< ret_port: 4506
< pidfile: /tmp/salt-master.pid
< root_dir: /data1/salt
< pki_dir: /data1/salt/pki/master
< cachedir: /data1/salt/cache/master
< auto_accept: True # 自动认证,免除一些手续
minion的配置没有做任何改动(除了minion id)
本文出自 “我是闪电~我是闪电~” 博客,请务必保留此出处http://potaski.blog.51cto.com/3099084/1317853
http://blog.csdn.net/app_ops/article/details/17147083
SaltStack的非标准安装
先解释下题目吧,什么是"SaltStack的非标准安装"。
简单先介绍下环境,笔者所运维的环境基本上以CentOS为主,有少部分Ubuntu。CentOS系统的版本也从5.4到6.4都有包括,进尔导致salt所依赖的python语言环境的版本也从2.4.3到2.6.6都有。因为是线上的系统,系统版本的升级或者python版本的升级,都有可能带来一定的风险性。所以从本意上来说,这次做的salt安装,最好不要对线上环境有任何的影响。(做过运维的都知道,最好不要对稳定的环境做任何的变化。)
好了,基本的思路定了,再看下新版salt的安装需求:
-
Python 2.6 >= 2.6 <3.0
-
ZeroMQ >= 2.1.9
-
pyzmq >= 2.1.9
-
PyCrypto
-
msgpack-python
-
YAML
-
Jinja2
这个列表,给了我们提供了一个好消息,一个坏消息。
先说坏消息:因为我们的python版本不统一,有部分系统的python版本不在支持的范围内;如果强行安装,可能会导致稳定性的问题。
再说好消息:既然有了安装需求,我们可以自定义安装,这样可以做到完全不影响系统环境。
既然已经决定了我们要走"自定义安装"的道路,那么我们就"兵马未行,粮草先动"。(本文就当个教程写了,之前的探索过程就不写了)
-
准备所需要的程序包。
Jinja2-2.7.1.tar.gz
M2Crypto-0.21.1.tar.gz
MarkupSafe-0.18.tar.gz
PyYAML-3.10.tar.gz
Python-2.7.5.tgz
msgpack-python-0.1.12.tar.gz
pycrypto-2.6.1.tar.gz
pyzmq-13.1.0.zip
salt-0.17.1.tar.gz
setuptools-1.1.6.tar.gz
yaml-0.1.4.tar.gz
zeromq-4.0.1.tar.gz
-
安装前的准备。
安装目录:/usr/local/SaltStack (我们的目标很明确)
-
开始安装,下面是我写的一个很简单的脚本。
master和minion的安装部署是一样的,区别只是使用的配置文件不同。
M2Crypto的安装,请根据系统的具体环境参考安装说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
#!/bin/bash # # Author : john.lee.cn.do@gmail.com # Date : 2013.10.25 # Desc : Install Salt # Usage : bash install.sh # export LANG=C _IP=` ifconfig | grep 'inet addr' | grep - v '127.0.0.1' | sed 's/[ ]*/ /' | awk '{print $2}' | awk -F: '{print $NF}' | head -n 1` _MASTER=172.17.37.207 _PATH= /usr/local/src/SaltStack # Install Python cd $_PATH tar zxvf Python-2.7.5.tgz cd Python-2.7.5 . /configure --prefix= /usr/local/SaltStack/python-2 .7.5 make && make install export _PYTHON= /usr/local/SaltStack/python-2 .7.5 /bin/python # Install setuptools cd $_PATH tar zxvf setuptools-1.1.6. tar .gz cd setuptools-1.1.6 $_PYTHON setup.py install # Install MarkupSafe cd $_PATH tar zxvf MarkupSafe-0.18. tar .gz cd MarkupSafe-0.18 $_PYTHON setup.py install # Install jinja2 cd $_PATH tar zxvf Jinja2-2.7.1. tar .gz cd Jinja2-2.7.1 $_PYTHON setup.py install # Install msgpack-python cd $_PATH tar zxvf msgpack-python-0.1.12. tar .gz cd msgpack-python-0.1.12 $_PYTHON setup.py install # Install pycrypto cd $_PATH tar zxvf pycrypto-2.6.1. tar .gz cd pycrypto-2.6.1 $_PYTHON setup.py install # Install PyYAML cd $_PATH tar zxvf PyYAML-3.10. tar .gz cd PyYAML-3.10 $_PYTHON setup.py install # Install zeromq cd $_PATH tar zxvf zeromq-4.0.1. tar .gz cd zeromq-4.0.1 . /configure --prefix= /usr/local/SaltStack/zeromq-4 .0.1 make && make install # Install pyzmq cd $_PATH unzip pyzmq-13.1.0.zip cd pyzmq-13.1.0 $_PYTHON setup.py install --zmq= /usr/local/SaltStack/zeromq-4 .0.1 # Install M2Crypto # Need yum install swig cd $_PATH tar zxvf M2Crypto-0.21.1. tar .gz cd M2Crypto-0.21.1 # Modify python path in fedora_setup.sh bash fedora_setup.sh install # Install Salt cd $_PATH tar zxvf salt-0.17.1. tar .gz cd salt-0.17.1 $_PYTHON setup.py install |
4. 因为master和minion的区别,只是配置文件的不同,在请参考官方文档(salt的配置文件模板在salt-0.17.1/conf)
5. 启动脚本。
既然我们把路径都已经修改了,那么我们的启动脚本也要修改一下了。
salt-minion(此例中,将配置文件也放在了/etc/salt中,如果进行了修改,可以修改脚本即可。)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
#!/bin/sh # # Salt minion ################################### # LSB header ### BEGIN INIT INFO # Provides: salt-minion # Required-Start: $local_fs $remote_fs $network $named $time # Should-Start: $time ypbind smtp # Required-Stop: $local_fs $remote_fs $network $named $time # Should-Stop: ypbind smtp # Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Short-Description: Salt minion daemon # Description: This is the Salt minion daemon that can be controlled by the Salt master. ### END INIT INFO # chkconfig header # chkconfig: 345 97 04 # description: This is the Salt minion daemon that can be controlled by the Salt master. # # processname: /usr/bin/salt-minion SALTMINION= /usr/local/SaltStack/python-2 .7.5 /bin/salt-minion PYTHON= /usr/local/SaltStack/python-2 .7.5 /bin # Sanity checks. [ -x $SALTMINION ] || exit 0 # Source function library. . /etc/rc .d /init .d /functions SERVICE=salt-minion PROCESS=salt-minion CONFIG_ARGS= " -c /etc/salt" RETVAL=0 start() { if [ $(pidofproc $PROCESS) ]; then RETVAL=$? echo -n "already running" else echo -n $ "Starting salt-minion daemon: " daemon --check $SERVICE $SALTMINION -d $CONFIG_ARGS RETVAL=$? fi echo return $RETVAL } stop() { echo -n $ "Stopping salt-minion daemon: " killproc $PROCESS RETVAL=$? echo } restart() { stop start } # See how we were called. case "$1" in start|stop|restart) $1 ;; status) if [ -f $SUSE_RELEASE ]; then echo -n "Checking for service salt-minion " checkproc $SALTMINION rc_status - v elif [ -f $DEBIAN_VERSION ]; then if [ -f $LOCKFILE ]; then RETVAL=0 echo "salt-minion is running." else RETVAL=1 echo "salt-minion is stopped." fi else status $PROCESS RETVAL=$? fi ;; condrestart) [ -f $LOCKFILE ] && restart || : ;; reload) echo "can't reload configuration, you have to restart it" if [ -f $SUSE_RELEASE ]; then rc_status - v else RETVAL=$? fi ;; *) echo $ "Usage: $0 {start|stop|status|restart|condrestart|reload}" exit 1 ;; esac exit $RETVAL |
因为master就只有一台机器,所以就没有写脚本,手工操作也没太多的工作量,而且会更加的灵活。
其它说明:
-
我们是把python环境单独安装在了/usr/local/SaltStack/python-2.7.5中,所以每次手工执行命令时,需要使用绝对路径。
-
目前上前做的环境中,只有一台master机器,存在单点危险,而且没有做负载均衡。目前还没有想到很好的解决方案。
欢迎大家一起讨论。
- <pre code_snippet_id="98726" snippet_file_name="blog_20131205_4_6128993"></pre>
- <pre></pre>
http://www.iyunv.com/thread-40232-1-1.html
二、Master批量管理配置
服务器端写sls模,他的默认路径在 /srv/salt/下,没有就新建目录,然后新建一个top.sls就跟puppet的入口文件 site.pp 类似。
<ignore_js_op>
· Base: 默认的的起点配置项:
· '*':这个引号内的是匹配对象,针对所有受控主机
· rd.sc:就是指资源文件/srv/salt/rd/sc.sls
<ignore_js_op>
看rd目录下的资源文件
<ignore_js_op>
利用py模式的sls配置文件(其实就是python脚本,只要返回yaml格式的字典文件就好了),我们可以将以上的操作简化成1步,思路如下:
1,/srv/pillar/top.sls中编写配置:
base: '*': - custom
2,使用py模式编写/srv/pillar/custom/init.sls,自动读取pillar配置,例如salt id是:10.1.1.1-centos.game.web,那么project为game,然后根据获取的pillar_root组合成路径/srv/pillar/custom/game/10.1.1.1-centos.game.web.yaml,利用yaml模块从文件中读取信息,返回字典
3,在/srv/salt/top.sls文件中匹配所有的minion
‘*’: - centos.public_services
4,/srv/salt/centos/public_services/init.sls文件使用py模式编写,配置会获取对应的minion的pillar信息,如果包含mysql配置信息且配置正确的话,则返回mysql实例的配置。
那现在要怎么使用呢,很简单,例如你的id为10.1.1.1-centos.game.web,首先在/srv/pillar/custom/目录下建个game目录(从salt id获取的项目名),然后在game目录先新建文件10.1.1.1-centos.game.web.yaml,里面写上配置信息:
mysql: ports: - 3306 - 3307 - 3308 version: '5_5_25'
最后执行命令:salt 10.1.1.1-centos.game.web state.highstate -v -t 300
静静的等待执行完成就好了!
=======================
http://blog.liuts.com/post/240/
一、设备环境说明
有两组web业务服务器,组名分别为web1group与web2group,设备硬件配置、web根目录存在异常,见下图:

二、master配置说明
1、关键配置定义:
- nodegroups:
- web1group: 'L@SN2012-07-010,SN2012-07-011,SN2012-07-012'
- web2group: 'L@SN2013-08-021,SN2013-08-022'
- file_roots:
- base:
- - /srv/salt
- pillar_roots:
- base:
- - /srv/pillar
2、定义的文件树结构(具体文件后续说明)

三、自定义grains_module
1)#vi /srv/salt/_grains/nginx_config.py
- import os,sys,commands
- def NginxGrains():
- '''
- return Nginx config grains value
- '''
- grains = {}
- max_open_file=65536
- #Worker_info={'cpus2':'01 10','cpus4':'1000 0100 0010 0001','cpus8':'10000000 01000000 00100000 00010000 00001000 00000100 00000010 00000001'}
- try:
- getulimit=commands.getstatusoutput('source /etc/profile;ulimit -n')
- except Exception,e:
- pass
- if getulimit[0]==0:
- max_open_file=int(getulimit[1])
- grains['max_open_file'] = max_open_file
- return grains
2)同步grains模块
salt '*' saltutil.sync_all
3)刷新模块(让minion编译模块)
salt '*' sys.reload_modules
4)验证max_open_file key的value
[root@SN2013-08-020 _grains]# salt '*' grains.item max_open_file
SN2013-08-022:
max_open_file: 1024
SN2013-08-021:
max_open_file: 1024
SN2012-07-011:
max_open_file: 1024
SN2012-07-012:
max_open_file: 1024
SN2012-07-010:
max_open_file: 1024
四、配置pillar
本例使用分组规则定义pillar,即不同分组引用各自的sls属性
1)定义入口top.sls
#vi /srv/pillar/top.sls
- base:
- web1group:
- - match: nodegroup
- - web1server
- web2group:
- - match: nodegroup
- - web2server
2)定义私有配置,本例只配置web_root的数据,当然可以根据不同需求进行定制,格式为python的字典形式,即"key:value"。
#vi /srv/pillar/web1server.sls
- nginx:
- root: /www
#vi /srv/pillar/web2server.sls
- nginx:
- root: /data
3)验证配置结果:
#salt 'SN2013-08-021' pillar.data nginx
SN2013-08-021:
----------
root:
/data
#salt 'SN2012-07-010' pillar.data nginx
SN2012-07-010:
----------
root:
/www
五、配置States
1)定义入口top.sls
#vi /srv/salt/top.sls
- base:
- '*':
- - nginx
2)定义nginx配置及重启服务SLS,其中salt://nginx/nginx.conf为配置模板文件位置。
#vi /srv/salt/nginx.sls
- nginx:
- pkg:
- - installed
- file.managed:
- - source: salt://nginx/nginx.conf
- - name: /etc/nginx/nginx.conf
- - user: root
- - group: root
- - mode: 644
- - template: jinja
- service.running:
- - enable: True
- - reload: True
- - watch:
- - file: /etc/nginx/nginx.conf
- - pkg: nginx
3)Nginx配置文件(引用jinja模板)
功能点:
1、worker_processes参数采用grains['num_cpus'] 上报值(与设备CPU核数一致);
2、worker_cpu_affinity分配多核CPU根据当前设备核数进行匹配,分别为2\4\8\其它核;
3、worker_rlimit_nofile参数与grains['max_open_file'] 获取的系统ulimit -n一致;
4、worker_connections 参数理论上为grains['max_open_file'];
5、 root参数为定制的pillar['nginx']['root']值。
#vi /srv/salt/nginx/nginx.conf
- # For more information on configuration, see:
- user nginx;
- worker_processes {{ grains['num_cpus'] }};
- {% if grains['num_cpus'] == 2 %}
- worker_cpu_affinity 01 10;
- {% elif grains['num_cpus'] == 4 %}
- worker_cpu_affinity 1000 0100 0010 0001;
- {% elif grains['num_cpus'] >= 8 %}
- worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
- {% else %}
- worker_cpu_affinity 1000 0100 0010 0001;
- {% endif %}
- worker_rlimit_nofile {{ grains['max_open_file'] }};
- error_log /var/log/nginx/error.log;
- #error_log /var/log/nginx/error.log notice;
- #error_log /var/log/nginx/error.log info;
- pid /var/run/nginx.pid;
- events {
- worker_connections {{ grains['max_open_file'] }};
- }
- http {
- include /etc/nginx/mime.types;
- default_type application/octet-stream;
- log_format main '$remote_addr - $remote_user [$time_local] "$request" '
- '$status $body_bytes_sent "$http_referer" '
- '"$http_user_agent" "$http_x_forwarded_for"';
- access_log /var/log/nginx/access.log main;
- sendfile on;
- #tcp_nopush on;
- #keepalive_timeout 0;
- keepalive_timeout 65;
- #gzip on;
- # Load config files from the /etc/nginx/conf.d directory
- # The default server is in conf.d/default.conf
- #include /etc/nginx/conf.d/*.conf;
- server {
- listen 80 default_server;
- server_name _;
- #charset koi8-r;
- #access_log logs/host.access.log main;
- location / {
- root {{ pillar['nginx']['root'] }};
- index index.html index.htm;
- }
- error_page 404 /404.html;
- location = /404.html {
- root /usr/share/nginx/html;
- }
- # redirect server error pages to the static page /50x.html
- #
- error_page 500 502 503 504 /50x.html;
- location = /50x.html {
- root /usr/share/nginx/html;
- }
- }
- }
4)同步配置
#salt '*' state.highstate

(由于非第一次运行,看不到配置文件比对的信息)
5)验证结果:
1、登录root@SN2013-08-021
#vi /etc/nginx/nginx.conf


2、登录root@SN2012-07-010
#vi /etc/nginx/nginx.conf


=========================================================
http://www.xiaomastack.com/2014/09/20/yunweipingtai2/
第一个运维平台_第二版
其实这个版本与第一个 http://www.xiaomastack.com/2014/07/05/yunweipingtai/ 比已经是脱胎换骨了,该版本后端采用Django,前端用BootStrap。底层还是用的saltsatck、saltAPI、zabbix、zabbixAPI、git等,毕竟整体架构是不能随随便便就改变的。我来简单的介绍下原理和功能。
1、配置管理。
配置管理主要用saltstack来做,与saltstack的通信用saltAPI来完成。”执行salt命令“ 的功能就是在WEB界面执行saltstack命令(安全简单选择预置的命令就可以了,关键是命令可以预置这样在应用层就防止了误操作,虽然我们在salt的代码层也做了类似的处理)。”配置下发“ 这个基于salt命令,依次执行salt命令就好了。
2、资产管理。
资产管理主要分为硬件资产和软件资产,硬件资产由saltsatck的grains来采集,软件资产的收集由saltstack下发执行采集脚本来完成。所有的这些操作都自动完成(采集、入库、展示)。打码的地方太多我用PS来打吧!
3、版本发布。
版本发布实现功能
a、能从操作者本地上传zip更新包,更新到正式环境或测试环境。如果更新到测试环境经过测试后没有问题再推送到正式环境。也可以直接更新到正式环境。
b、开发人员提供包名后,根据包名从ftp服务器下载zip更新包,更新到正式环境或测试环境。如果更新到测试环境后没有问题再推送到正式环境。也可以直接更新到正式环境。
c、能够回滚到上一个版本(测试或正式环境)。
4、数据展示。
主要做的是Zabbix监控数据的展示,分类、分应用、分主机。原始数据由Zabbix采集,然后另外的机器用ZabbixAPI向Zabbix取监控数据存放到rrd文件,最后由RRDTool绘图展示监控数据。
硬件监控数据展示分类沿用Zabbix自身的分类,软件应用监控数据的分类采用再绘图时的自定义的分类。
点击一台主机,监控数据默认展示的是1天的监控数据。
点击图可以进入该监项在过去1天、1周、1月、1年的监控图,默认30秒刷新一次(也可以手动刷新)
点击1天的监控图,可以进入该监控项2小时的监控图,默认30秒刷新,也可以手动刷新。
转载请注明出处:http://www.xiaomastack.com/2014/09/20/yunweipingtai2/ 谢谢!
11 Comments
Add your comment
==========
http://www.xiaomastack.com/2014/11/18/salt-api/
配置管理(3) salt-api安装、配置、使用
salt-api也用了一段时间了,现在从安装、配置、使用三个方面梳理下知识。
1、安装
采用pip安装方便快捷,当然编译安装也很nice。
安装pip采用的编译安装的方式,版本当前最新1.5.6,下载、解压、编译、安装是不变的法则。
1
2
3
4
5
6
7
|
[root@saltstack ~] #wget https://pypi.python.org/packages/source/p/pip/pip-1.5.6.tar.gz#md5=01026f87978932060cc86c1dc527903e --no-check-certificate [root@saltstack ~] #tar xvfz pip-1.5.6.tar.gz [root@saltstack ~] #cd pip-1.5.6 [root@saltstack pip-1.5.6] #python setup.py build [root@saltstack pip-1.5.6] #python setup.py install #安装完成后可以用pip freeze查看已安装的packages [root@saltstack pip-1.5.6] #pip freeze |
安装CherryPy,版本3.2.3
1
|
[root@saltstack ~] #pip install cherrypy==3.2.3 |
安装salt-api,版本0.8.3
1
|
[root@saltstack ~] #pip install salt-api==0.8.3 |
2、配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
[root@saltstack ~] # cd /etc/pki/tls/certs [root@saltstack certs] # make testcert umask 77 ; \ /usr/bin/openssl genrsa -aes128 2048 > /etc/pki/tls/private/localhost .key Generating RSA private key, 2048 bit long modulus ...+++ ..................................................................+++ e is 65537 (0x10001) Enter pass phrase: #键入加密短语,4到8191个字符 Verifying - Enter pass phrase: #确认加密短语 umask 77 ; \ /usr/bin/openssl req -utf8 -new -key /etc/pki/tls/private/localhost .key -x509 -days 365 -out /etc/pki/tls/certs/localhost .crt -set_serial 0 Enter pass phrase for /etc/pki/tls/private/localhost .key: #再次输入相同的加密短语 You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.' , the field will be left blank. ----- Country Name (2 letter code) [XX]:CN #都可以选填 State or Province Name (full name) []:Shanghai Locality Name (eg, city) [Default City]:Shanghai Organization Name (eg, company) [Default Company Ltd]: Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname ) []: Email Address []:1989051805@qq.com [root@saltstack certs] # cd ../private/ [root@saltstack private] # openssl rsa -in localhost.key -out localhost_nopass.key Enter pass phrase for localhost.key: #输入之前的加密短语 writing RSA key |
如果遇到这样的错误
1
2
3
4
5
6
|
[root@saltstack certs] # make testcert umask 77 ; \ /usr/bin/openssl req -utf8 -new -key /etc/pki/tls/private/localhost .key -x509 -days 365 -out /etc/pki/tls/certs/localhost .crt -set_serial 0 unable to load Private Key 139696733648712:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:703:Expecting: ANY PRIVATE KEY make : *** [ /etc/pki/tls/certs/localhost .crt] |
删掉文件/etc/pki/tls/private/localhost.key文件,然后再make testcert。
为salt-api创建用户并设定密码,用户名没有特别要求,我就用saltapi好了。
1
2
3
|
[root@saltstack ~] #useradd -M -s /sbin/nologin saltapi #由于是测试,故采用了弱密码"password",正式环境必须采用强密码,多用特殊字符 [root@saltstack ~] # passwd saltapi |
新增加配置文件/etc/salt/master.d/api.conf和/etc/salt/master.d/eauth.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#该配置文件给予saltapi用户所有模块使用权限,出于安全考虑一般只给予特定模块使用权限 [root@saltstack master.d] # cat eauth.conf external_auth: pam: saltapi: - .* [root@saltstack master.d] # [root@saltstack master.d] # cat api.conf rest_cherrypy: port: 8888 ssl_crt: /etc/pki/tls/certs/localhost .crt ssl_key: /etc/pki/tls/private/localhost_nopass .key [root@saltstack master.d] # |
寻找salt-api的启动脚本,我比较懒就不自己写了,在页面https://github.com/saltstack/salt-api/releases下载salt-api的tar.gz包,启动脚本在解压包的这个位置./pkg/rpm/salt-api。
不过提供的脚本貌似有个小的bug,就是使用restart参数时,salt-api能够stop但是不能start,如下:
1
2
3
|
[root@saltstack ~] # /etc/init.d/salt-api restart Stopping salt-api daemon: [确定] Starting salt-api daemon: [失败] |
我估计可能是有些相关资源在下次启动前没有来得及释放造成的,解决方法很简单在脚本的restart函数的stop和start之间加上sleep语句。
1
2
3
4
5
|
restart() { stop sleep 1 start } |
然后重启就没有问题了
1
2
3
4
|
[root@saltstack ~] # /etc/init.d/salt-api restart Stopping salt-api daemon: [确定] Starting salt-api daemon: [确定] [root@saltstack ~] # |
最后重启salt-master在启动salt-api并将salt-api加入开机启动,安装就完成了。
1
2
3
4
5
6
7
8
|
[root@saltstack ~] # chkconfig salt-api on [root@saltstack ~] # /etc/init.d/salt-master restart Stopping salt-master daemon: [确定] Starting salt-master daemon: [确定] [root@saltstack ~] # /etc/init.d/salt-api restart Stopping salt-api daemon: [确定] Starting salt-api daemon: [确定] [root@saltstack ~] # |
3、使用(基本的使用方法)
登录获取token
1
2
3
4
5
6
7
8
9
|
[root@syndic02 ~] # curl -k https://192.168.186.134:8888/login -H "Accept: application/x-yaml" -d username='saltapi' -d password='password' -d eauth='pam' return : - eauth: pam expire: 1416324685.2597771 perms: - .* start: 1416281485.2597761 token: 6171a922a9718ccb40e94ee7c8eb8768f4eea4e5 user: saltapi |
获取token后就可以使用token通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#相当于在salt-master本地执行salt \* test.ping [root@syndic02 ~] # curl -k https://192.168.186.134:8888/ -H "Accept: application/x-yaml" -H "X-Auth-Token: 6171a922a9718ccb40e94ee7c8eb8768f4eea4e5" -d client='local' -d tgt='*' -d fun='test.ping' return : - syndic01: true syndic01-minion02: true syndic02: true syndic02-minion02: true #相当于在salt-master本地执行salt \* test.echo 'hello world' [root@syndic02 ~] # curl -k https://192.168.186.134:8888/ -H "Accept: application/x-yaml" -H "X-Auth-Token: 6171a922a9718ccb40e94ee7c8eb8768f4eea4e5" -d client='local' -d tgt='*' -d fun='test.echo' -d arg='hello world' return : - syndic01: hello world syndic01-minion02: hello world syndic02: hello world syndic02-minion02: hello world [root@syndic02 ~] # |
运维开发这样使用还是不方便的,下面写的是一个salt-api的类(其它的文章也提到过)可以参考。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
#!/usr/bin/env python #coding=utf-8 import urllib2, urllib, json, re class saltAPI: def __init__( self ): self .__user = 'saltapi' #salt-api用户名 self .__password = 'password' #salt-api用户密码 self .__token_id = self .salt_login() def salt_login( self ): params = { 'eauth' : 'pam' , 'username' : self .__user, 'password' : self .__password} encode = urllib.urlencode(params) obj = urllib.unquote(encode) headers = { 'X-Auth-Token' :''} url = self .__url + '/login' req = urllib2.Request(url, obj, headers) opener = urllib2.urlopen(req) content = json.loads(opener.read()) try : token = content[ 'return' ][ 0 ][ 'token' ] return token except KeyError: raise KeyError def postRequest( self , obj, prefix = '/' ): url = self .__url + prefix headers = { 'X-Auth-Token' : self .__token_id} req = urllib2.Request(url, obj, headers) opener = urllib2.urlopen(req) content = json.loads(opener.read()) return content[ 'return' ] def saltCmd( self , params): obj = urllib.urlencode(params) obj, number = re.subn( "arg\d" , 'arg' , obj) res = self .postRequest(obj) return res def main(): #以下是用来测试saltAPI类的部分 sapi = saltAPI() params = { 'client' : 'local' , 'fun' : 'test.ping' , 'tgt' : '*' } #params = {'client':'local', 'fun':'test.ping', 'tgt':'某台服务器的key'} #params = {'client':'local', 'fun':'test.echo', 'tgt':'某台服务器的key', 'arg1':'hello'} #params = {'client':'local', 'fun':'test.ping', 'tgt':'某组服务器的组名', 'expr_form':'nodegroup'} test = sapi.saltCmd(params) print test if __name__ = = '__main__' : main() |
测试效果
1
2
3
|
[root@syndic02 ~] # python salt-api.py [{u 'syndic02' : True, u 'syndic02-minion02' : True, u 'syndic01' : True, u 'syndic01-minion02' : True}] [root@syndic02 ~] # |
以上只是一些基本的实例,salt-api还可以实现更多功能。
文章出处:http://www.xiaomastack.com/2014/11/18/salt-api/
配置管理篇(2)_SaltStack grains
grains主要负责采集并返回客户端minion的一些基本信息, saltstack自带grains模块可以采集机器的很多基本信息,对于比较特别的信息grains可以在客户端或服务器端自定义item后采集,不管是那种方式自定义grains的item,最终grains的item值都是由客户端minion采集完成后上报给服务端master的,采集动作只在启动客户端或有新的grains添加时触发,grains采集上报的数据可以作为资产管理的元数据。一个客户端在启动时就将自定义或基本的item信息值读取到内存了,这些值是个常量在下次重启客户端之前不会改变。
先看看怎样使用,然后瞧瞧怎样自定义(4种自定义方法)
查看所有的grains项 grains.ls
1
2
3
4
5
6
7
8
9
|
[root@saltstack ~] # salt minion01 grains.ls minion01: - biosreleasedate - biosversion - cpu_flags - cpu_model - cpuarch - defaultencoding ... ... ... |
查看所有的grains项的详细信息 grains.items
1
2
3
4
5
|
[root@saltstack ~] # salt minion01 grains.items minion01: biosreleasedate: 07 /02/2012 biosversion: 6.00 ... ... ... |
查看grains指定的item信息
1
2
3
4
5
6
7
8
9
10
11
|
[root@saltstack ~] # salt minion01 grains.item shell minion01: shell: /bin/sh [root@saltstack ~] # salt minion01 grains.item os minion01: os: CentOS [root@saltstack ~] # salt minion01 grains.item ipv4 minion01: ipv4: 127.0.0.1 192.168.186.135 |
grains添加自定义items
1、在master端添加
在配置文件file_roots指定的目录(默认是/srv/salt)下创建_grains目录,编写可以返回一个字典的py文件(需要懂点python)。
1
2
3
4
5
6
7
8
|
[root@saltstack ~] # grep -Ev "^$|^#" /etc/salt/master file_roots: base: - /srv/salt pillar_roots: base: - /srv/pillar [root@saltstack ~] # |
例如grains添加自定义item(disk_size)返回磁盘的大小,注意python脚本返回值是一个字典。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
[root@saltstack _grains] # cat disk.py #coding=utf-8 import os def disk_size(): ''' get disk size ''' disk = os.statvfs( "/" ) capacity = disk.f_bsize * disk.f_blocks ret = int ( float (capacity) / 1000 / 1000 / 1000 ) if ret > 1000 : obj = ret / 1000.0 disk_size = ( "%.1f" % obj) + 'T' else : ret = str (ret) disk_size = ret + 'G' return { 'disk_size' : disk_size} |
用saltutil.sync_grains或者saltutil.sync_all将自定义的grains item 同步到minion端,如果只同步grains建议使用saltutil.sync_grains。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@saltstack _grains] # salt minion01 saltutil.sync_grains minion01: - grains.__init__ - grains.disk [root@saltstack _grains] # salt minion01 saltutil.sync_all minion01: ---------- grains: modules: outputters: renderers: returners: states: |
从结果可以看到sync_grains和sync_all不同之处了吧。
同步完成后在minion端的以下目录中可以找到master下发的grains文件
1
2
|
[root@minion01 minion.d] # ls /var/cache/salt/minion/extmods/grains/ disk.py disk.pyc __init__.py |
看看是否同步成功
1
2
3
4
|
[root@saltstack _grains] # salt minion01 grains.item disk_size minion01: disk_size: 19G [root@saltstack _grains] # |
2、在minion端添加
可以直接在配置文件/etc/salt/minion中添加,但一般不这么干。一般会将default_include: minion.d/*.conf配置项打开,然后将自定义grains的以.conf结尾的配置文件放到minion.d这个目录中。
1
2
3
4
|
[root@minion01 ~] # grep -Ev "^$|#" /etc/salt/minion default_include: minion.d/*.conf master: 192.168.186.134 id : minion01 |
在minion.d目录中添加并编辑grains.conf文件(文件名随意)
1
2
3
4
5
|
[root@minion01 minion.d] # cat grains.conf grains: IDC: xxx-xxx-xxx dFlag: 2014 /10/31 [root@minion01 minion.d] # |
重启salt-minion后生效,然后在master端查看自定义的grains
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@saltstack _grains] # salt minion01 grains.get IDC minion01: xxx-xxx-xxx [root@saltstack _grains] # salt minion01 grains.get dFlag minion01: 2014 /10/31 [root@saltstack _grains] # salt minion01 grains.item dFlag minion01: dFlag: 2014 /10/31 [root@saltstack _grains] # salt minion01 grains.item IDC minion01: IDC: xxx-xxx-xxx [root@saltstack _grains] # |
3、在master端直接用grains.setval为指定minion的grains设定一个item
设定welcome的值为’hello world’
1
2
3
|
[root@saltstack _grains] # salt minion01 grains.setval welcome 'hello world' minion01: welcome: hello world |
查看定义的item的值
1
2
3
4
5
6
7
|
[root@saltstack _grains] # salt minion01 grains.item welcome minion01: welcome: hello world [root@saltstack _grains] # salt minion01 grains.get welcome minion01: hello world [root@saltstack _grains] # |
这次定义的grains保存在minion端的配置文件/etc/salt/grains中
1
2
3
4
|
[root@minion01 salt] # pwd /etc/salt [root@minion01 salt] # cat grains welcome: hello world |
4、在master端通过states的grains方法也可以自定义grains
为了方便管理,在文件夹/salt/srv下再创建文件夹gitems,然后再该文件夹下编辑新的sls文件gtest.sls
1
2
3
4
5
6
7
8
9
|
[root@saltstack gitems] # pwd /srv/salt/gitems [root@saltstack gitems] # ls gtest.sls [root@saltstack gitems] # cat gtest.sls country: grains.present: - value: china [root@saltstack gitems] # |
下发到minion端,并查看新添加的item
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[root@saltstack gitems] # salt minion01 state.sls gitems.gtest minion01: ---------- ID: country Function: grains.present Result: True Comment: Set grain country to china Changes: ---------- country: china Summary ------------ Succeeded: 1 Failed: 0 ------------ Total: 1 [root@saltstack gitems] # salt minion01 grains.get country minion01: china |
该方法定义的grains同样保存在minion端的配置文件/etc/salt/grains中
1
2
3
4
|
[root@minion01 salt] # cat grains country: china welcome: hello world [root@minion01 salt] # |
转载请注明出处:http://www.xiaomastack.com/2014/10/31/saltstack-grains/ 谢谢!
配置管理篇(1)_SaltStack常用可执行模块(execution modules)及解决rm -f带来的困惑
所有的可执行模块(execution modules)可以查看官方文档,记录下我常用到的模块test、status、cmdmod、useradd、system、systemd、file和解决rm -f带来困惑的方法。使用方法除了查看官方文档和手册外,查看源代码(源代码中也详细描述了使用方法和示例)也是一个好的方法。
1、test
test模块提供对minion端有限项的任意测试,常见的有ping、echo、version等,源码在minion端/usr/lib/python2.6/site-packages/salt/modules/test.py,详细的使用方法查源码最直接了。
1
2
3
4
5
6
7
8
9
10
|
[root@saltstack ~] # salt minion01 test.ping minion01: True [root@saltstack ~] # salt minion01 test.echo 'hello world' minion01: hello world [root@saltstack ~] # salt minion01 test.version minion01: 2014.1.10 [root@saltstack ~] # |
2、status
status可以查看minion的基本状态如CPU、内存、硬盘、网络等,常见的有all_status、uptime、w、netstats等,源码在minion端/usr/lib/python2.6/site-packages/salt/modules/status.py。
对于all_status方法查看源码可以看到这个版本支持的可查询状态有cpuinfo、cpustatus、… …等
1
2
3
4
5
6
7
8
9
10
11
12
13
|
def all_status(): ... ... ... return { 'cpuinfo' : cpuinfo(), 'cpustats' : cpustats(), 'diskstats' : diskstats(), 'diskusage' : diskusage(), 'loadavg' : loadavg(), 'meminfo' : meminfo(), 'netdev' : netdev(), 'netstats' : netstats(), 'uptime' : uptime(), 'vmstats' : vmstats(), 'w' : w()} |
使用方法很简单,例如:
1
2
3
4
|
[root@saltstack ~] # salt minion01 status.uptime minion01: 14:27:49 up 4:43, 1 user, load average: 0.00, 0.00, 0.00 [root@saltstack ~] # |
3、cmdmod与rm -f带来的困惑
这个模块中的run可以执行在bash里执行的所有命令,很强大但是也得注意在run中执行类似rm这样的命令是很危险的。源码位置在minion端的/usr/lib/python2.6/site-packages/salt/modules/cmdmod.py。
cmd.run执行命令就像在minion端本地执行命令一样亲切。
1
2
3
4
5
6
7
|
[root@saltstack ~] # salt minion01 cmd.run 'df -hT' minion01: Filesystem Type Size Used Avail Use% Mounted on /dev/sda3 ext4 19G 2.5G 15G 15% / tmpfs tmpfs 242M 0 242M 0% /dev/shm /dev/sda1 ext4 504M 39M 440M 9% /boot [root@saltstack ~] # |
亲切的同时也会带来困惑,如果误操作是这样的,后果很可怕。
1
|
[root@saltstack ~] # salt \* cmd.run "rm -rf /" |
可以修改源代码禁止执行rm这种较危险的命令,打开minion端的文件/usr/lib/python2.6/site-packages/salt/modules/cmdmod.py找到run()函数,在其调用_run()函数的时候判断参数cmd中是否包含rm命令,如果包含了就返回并提示”rm命令很危险,任务执行失败”,这样一来master上cmd.run就不能执行rm命令了。
1
2
3
4
5
6
7
8
9
10
|
''' ... ... ... salt '*' cmd.run "grep f" stdin='one\\ntwo\\nthree\\nfour\\nfive\\n ''' #在以下位置添加代码 if r 'rm ' in cmd: return "'rm' is dangerous!!! MISSION FAILED!!!" #在以上位置添加代码 ret = _run(cmd, ... ... ... |
修改文件后重启minion后生效,测试下效果
1
2
3
4
|
[root@saltstack ~] # salt minion01 cmd.run "rm -rf /" minion01: 'rm' is dangerous!!! MISSION FAILED!!! [root@saltstack ~] # |
可以看出修改已经生效,再也不用担心cmd.run误操作了。不过有个问题就是,在cmdmod模块中不仅cmd.run可以执行rm命令还有cmd.run_all、cmd.run_stdout等都可以执行rm命令,为了更彻底的封掉rm这个命名,仔细看了下代码发现它们最终都是调用的_run()来完成任务的,可以修改_run()这个函数(在/usr/lib/python2.6/site-packages/salt/modules/cmdmod.py文件第213行)来彻底的封掉rm这个命令。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
''' ... ... ... Do the DRY thing and only call subprocess.Popen() once ''' #在以下位置添加代码 if r 'rm ' in cmd: ret = {} ret[ 'stdout' ] = "'rm' is dangerous!!! MISSION FAILED!!!" ret[ 'stderr' ] = '' ret[ 'pid' ] = '' ret[ 'retcode' ] = 0 return ret #在以上位置添加代码 if salt.utils.is_true(quiet): ... ... ... |
如果是修改_run()函数后就不用修改run()等其它函数了,修改文件后重启minion后生效,测试下效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[root@saltstack ~] # salt minion01 cmd.run "rm -rf /" minion01: 'rm' is dangerous!!! MISSION FAILED!!! [root@saltstack ~] # salt minion01 cmd.run_all "rm -f test" minion01: ---------- pid: retcode: 0 stderr: stdout: 'rm' is dangerous!!! MISSION FAILED!!! |
将修改过的salt-minion打成rpm包后放到本地的yum源,然后重新安装所有的minion端就可以解决rm带来的困惑了。
4、useradd
这个模块主是用来用户管理的,源文件位置在minion端(下同)/usr/lib/python2.6/site-packages/salt/modules/useradd.py,记录几个常用的。
user.add添加新用户
1
2
3
|
[root@saltstack ~] # salt minion01 user.add testuser minion01: True |
user.list_users列出所有的用户,可以看到刚才添加的用户
1
2
3
|
[root@saltstack ~] # salt minion01 user.list_users | grep testuser - testuser [root@saltstack ~] # |
user.info查看用户信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
[root@saltstack ~] # salt minion01 user.info testuser minion01: ---------- fullname: gid: 500 groups : - testuser home: /home/testuser homephone: name: testuser passwd : x roomnumber: shell: /bin/bash uid: 500 workphone: |
user模块还有很多可用的方法,可以根据名称就可以知道其功能了比如
1
2
3
4
5
6
7
8
9
10
|
user.getent user.delete name remove=True force=True user.chworkphone foo "7735550123" user.chuid foo 4376 user.chshell foo /bin/zsh user.chroomnumber foo 123 user.chfullname foo "Foo Bar" user.chgid foo 4376 user.chgroups foo wheel,root True user.chhome foo /home/users/foo True |
5、system
系统管理模块,能看懂的就不记录了。源码位置/usr/lib/python2.6/site-packages/salt/modules/system.py
1
2
3
4
5
|
system.halt #停止正在运行的系统 system.init 3 #切换到字符界面,5是图形界面 system.poweroff system.reboot system. shutdown |
6、systemd
系统服务管理模块,源码位置/usr/lib/python2.6/site-packages/salt/modules/systemd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
service.available sshd #查看服务是否可用 service.disable <service name> #设置开机启动的服务 service. enable <service name> service.disabled <service name> #查看服务是不是开机启动 service.enabled <service name> service.get_disabled #返回所有关闭的服务 service.get_enabled #返回所有开启的服务 service.get_all #返回所有服务 service.reload <service name> #重新载入指定的服务 service.restart <service name> #重启服务 service.start <service name> service.stop <service name> service.status <service name> service.force_reload <service name> #强制载入指定的服务 |
7、file
文件管理模块,这个模块的方法太多,非常强大,选些常用的记一下。源文件/usr/lib/python2.6/site-packages/salt/modules/file.py中有所有方法的功能和使用说明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
file .copy /path/to/src /path/to/dst #将master文件拷贝到minion上,salt还有个专门的拷文件的命令salt-cp file .append /etc/motd "append test." #为minion的文件/etc/moth追加内容 file .check_hash /etc/fstab md5=<md5sum> #检测并对比文件的md5值,并返回布尔值 file .get_hash /etc/passwd 获取文件的md5值 file .check_perms /etc/sudoers '{}' root root 400 #检测并更改文件的用户、组、权限 file . chgrp /etc/passwd root file . chown /etc/passwd root root file .directory_exists /tmp #检测文件夹是否存在 file .file_exists /etc/passwd file .get_group /etc/passwd file .get_user /etc/passwd file .get_mode /etc/passwd #检测文件权限 file .set_mode /etc/passwd 0644 #设置权限 file .get_gid /etc/passwd file .get_uid /etc/passwd |
转载请注明出处:http://www.xiaomastack.com/2014/10/16/saltstack01/ 谢谢!
1、安装
安装saltstack用EPEL源安装简单快捷,实际部署的时候可以将saltstack相关的rpm包放到本地的yum源用本地源安装。
安装EPEL源:
1
2
|
[root@saltstack ~] #wget -c http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm [root@saltstack ~] #rpm -ivh epel-release-6-8.noarch.rpm |
安装salt-master,如果master要对自己进行配置管理则服务器master端本地也要安装minion
1
2
3
|
[root@saltstack ~] #yum install salt-master #安装salt-minion可选 [root@saltstack ~] #yum install salt-minion |
2、修改配置文件并启动服务。saltstack配置比较简单,一般不需要修改太多的参数。
salt-master端,暂时没有什么配置的,默认就好。
1
2
3
4
5
6
7
8
|
[root@saltstack ~] # grep -Ev "^#|^$" /etc/salt/master file_roots: base: - /srv/salt pillar_roots: base: - /srv/pillar [root@saltstack ~] # salt-master -d |
salt-minion端,配置 “master”项指向master的IP地址,配置 “id” 项为主机名(一般用主机名,也可以配成其它的标识符)
1
2
3
4
5
|
[root@minion01 ~] # grep -Ev "^#|^$" /etc/salt/minion master: 192.168.186.134 id : minion01 [root@minion01 ~] # salt-minion -d [root@minion01 ~] # |
1
2
3
4
5
|
[root@minion02 ~] # grep -Ev "^#|^$" /etc/salt/minion master: 192.168.186.134 id : minion02 [root@minion02 ~] # salt-minion -d [root@minion02 ~] # |
3、master认证端添minion的key,并做简单的存活测试。
salt-key管理所有的key,-L参数列出所有的key.”Unaccepted Keys”就是所有未认证minion端的key。
1
2
3
4
5
6
|
[root@saltstack ~] # salt-key -L Accepted Keys: Unaccepted Keys: minion01 minion02 Rejected Keys: |
-A参数接纳(认证)所有未被接纳(认证)的key,-a参数认证单个指定的key。
1
2
3
4
5
6
7
8
|
[root@saltstack ~] # salt-key -A The following keys are going to be accepted: Unaccepted Keys: minion01 minion02 Proceed? [n /Y ] y Key for minion minion01 accepted. Key for minion minion02 accepted. |
再查看下所有key的情况,可以看到”Accepted Keys”已经认证的key。
1
2
3
4
5
6
|
[root@saltstack ~] # salt-key -L Accepted Keys: minion01 minion02 Unaccepted Keys: Rejected Keys: |
用test.ping测试下minion端的存活,可以从返回值看到minion01和minion02在线
1
2
3
4
5
6
|
[root@saltstack ~] # salt \* test.ping minion01: True minion02: True [root@saltstack ~] # |
用test.ping命令测试时,如果等待的返回时间较长有可能是某些minion已经不在线了,可以用salt-run来查看所有minion的存活状态。
1
2
3
4
5
6
|
[root@saltstack ~] # salt-run manage.status down: up: - minion01 - minion02 [root@saltstack ~] # |
转载请注明出处:http://www.xiaomastack.com/2014/10/16/saltstack00/ 谢谢!
http://www.xiaomastack.com/2014/10/13/release-3/
版本更新发布WEB化(3)_小插曲自定义请求saltAPI的类
安装了saltAPI后就可以在任何一台服务器上调用saltAPI让saltstack执行相关的操作。之前用PHP和python写过相关的调用类,如果有兴趣可以移步以下文章《用PHP实现salt-api调用》和《用Python实现salt-api调用》。思路都是一样的,不过这两篇代码不够优雅。下面再上一个后来用python用写的比较优雅的一个类,看上去会简洁美观很多。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
#!/usr/bin/env python #coding=utf-8 import urllib2, urllib, json, re class saltAPI: def __init__( self ): self .__user = '调用saltAPI时的用户名' self .__password = '调用saltAPI时的密码' self .__token_id = self .salt_login() def salt_login( self ): params = { 'eauth' : 'pam' , 'username' : self .__user, 'password' : self .__password} encode = urllib.urlencode(params) obj = urllib.unquote(encode) headers = { 'X-Auth-Token' :''} url = self .__url + '/login' req = urllib2.Request(url, obj, headers) opener = urllib2.urlopen(req) content = json.loads(opener.read()) try : token = content[ 'return' ][ 0 ][ 'token' ] return token except KeyError: raise KeyError def postRequest( self , obj, prefix = '/' ): url = self .__url + prefix headers = { 'X-Auth-Token' : self .__token_id} req = urllib2.Request(url, obj, headers) opener = urllib2.urlopen(req) content = json.loads(opener.read()) return content[ 'return' ] def saltCmd( self , params): obj = urllib.urlencode(params) obj, number = re.subn( "arg\d" , 'arg' , obj) res = self .postRequest(obj) return res def main(): #以下是用来测试saltAPI类的部分 sapi = saltAPI() params = { 'client' : 'local' , 'fun' : 'test.ping' , 'tgt' : '某台服务器的key' } #params = {'client':'local', 'fun':'test.echo', 'tgt':'某台服务器的key', 'arg1':'hello'} #params = {'client':'local', 'fun':'test.ping', 'tgt':'某组服务器的组名', 'expr_form':'nodegroup'} test = sapi.saltCmd(params) print test if __name__ = = '__main__' : main() |
转载请注明出处:http://www.xiaomastack.com/2014/10/13/release-3/ 谢谢!
http://www.xiaomastack.com/2014/06/26/php-salt-api/
用PHP实现salt-api调用
saltstack由于其强大的配置部署及管理功能,是越来越火,被很多运维人员所认可。由于最近要开发一个运维平台,底层用到了salt-api来实现。如果你是入门的用户可以参考saltstack安装的bolg http://blog.coocla.org/category/saltstack 还有很多优秀的blog,可以百度神马的很多的,还有我们的saltstack中文站也可以逛逛 http://www.saltstack.cn/ 。
安装salt-api请参考 http://www.saltstack.cn/projects/cssug-kb/wiki/salt-api-deploy-and-use
经过saltsatck和salt-api的学习后,开始了苦逼的堆代码的工作,首先用PHP实现了对salt-api的访问,后来由于别的需求也实现了Python对salt-api的访问。
下面的代码是最初的比较原始的版本saltapi.php,不过功能够用了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
<?php function get_token(){ global $token ; $ch = curl_init( $url ); curl_setopt( $ch ,CURLOPT_POST,TRUE); curl_setopt( $ch ,CURLOPT_SSL_VERIFYHOST,2); curl_setopt( $ch ,CURLOPT_SSL_VERIFYPEER,False); curl_setopt( $ch ,CURLOPT_HTTPHEADER, Array( 'Accept: application/x-yaml' )); curl_setopt( $ch ,CURLOPT_POSTFIELDS, 'username=你的用户名&password=用户对应的密码&eauth=pam' ); curl_setopt( $ch ,CURLOPT_RETURNTRANSFER,TRUE); $token = curl_exec( $ch ); $token = strstr ( $token , 'token' , false); //取登录后返回字符串中的token $token = strstr ( $token , 'user' , true); $token = explode ( " " , $token )[1]; curl_close( $ch ); $token = rtrim( $token , "\n" ); //删掉token字符串最后面的'\n',不然后面死活登不上去 } //适用于带一个或不带参数的salt exc模块如 salt \* test.ping 或 salt \* test.echo "hello"这样的模块 function exc_salt( $tgt , $fun , $arg , $arg_num ){ global $token ; global $report ; $ch = curl_init( $url ); curl_setopt( $ch ,CURLOPT_POST,TRUE); curl_setopt( $ch ,CURLOPT_SSL_VERIFYHOST,2); curl_setopt( $ch ,CURLOPT_SSL_VERIFYPEER,False); curl_setopt( $ch ,CURLOPT_HTTPHEADER,Array( 'Accept: application/x-yaml' , "X-Auth-Token: $token" )); if ( $arg_num ) curl_setopt( $ch ,CURLOPT_POSTFIELDS, "client=local&tgt=$tgt&fun=$fun&arg=$arg" ); else curl_setopt( $ch ,CURLOPT_POSTFIELDS, "client=local&tgt=$tgt&fun=$fun" ); curl_setopt( $ch ,CURLOPT_RETURNTRANSFER,TRUE); $report = curl_exec( $ch ); curl_close( $ch ); return $report ; } //适用于带两个参数的salt exc模块 function exc_salt_2( $tgt , $fun , $arg_1 , $arg_2 ){ global $token ; global $report ; $ch = curl_init( $url ); curl_setopt( $ch ,CURLOPT_POST,TRUE); curl_setopt( $ch ,CURLOPT_SSL_VERIFYHOST,2); curl_setopt( $ch ,CURLOPT_SSL_VERIFYPEER,False); curl_setopt( $ch ,CURLOPT_HTTPHEADER,Array( 'Accept: application/x-yaml' , "X-Auth-Token: $token" )); curl_setopt( $ch ,CURLOPT_POSTFIELDS, "client=local&tgt=$tgt&fun=$fun&arg=$arg_1&arg=$arg_2" ); curl_setopt( $ch ,CURLOPT_RETURNTRANSFER,TRUE); $report = curl_exec( $ch ); curl_close( $ch ); return $report ; } //以下是测试这个脚本功能的部分,正式上线是得注释掉 get_token(); print exc_salt( '主机key' , 'test.echo' , 'hello' , 1); //带一个参数的 print exc_salt( '主机key' , 'test.ping' , '' , 0); //不带参数的 ?> |
运行结果如下:
这些函数还可以封装成一个类,方便调用。如果要求不高这样也可以满足要求了。
salt-api手册参考 http://salt-api.readthedocs.org/en/latest/
如果你的python还可以的话,直接看源代码,也是一样一样的。
转载请注明出处http://www.xiaomastack.com/2014/06/26/php-salt-api/ 谢谢!
http://www.xiaomastack.com/2014/06/30/saltminionerror/
解决启动salt-minion时“ImportError: No module named salt.scripts”错误
这是当初部署saltstack时候的问题了,saltstack用的是0.17.4的版本。正当开心minion部署到最后一台时时杀出了个程咬金,当启动 minion端时报错 “ImportError: No module named salt.scripts” 具体信息如下图:
但是明明是存在 scripts 脚本和完整的模块的,salt硬是找不到,汗!后来发现这台机器上有几个python环境,7层地狱啊!用 python –version 命令查看默认的 python环境是2.7的,而saltstack安装环境python2.6的,saltstack 模块是安装在 python2.6 的库里面的。所以会一直提示找不到模块。
好了,原因找到了问题就好解决了,手动指定 salt-minion 启动脚本的运行环境为 python2.6(2.6系统默认安装CentOS6.3) 如下:
然后,然后问题就解决了。
转载请注明出处 http://www.xiaomastack.com/2014/06/30/saltminionerror/ 谢谢!
http://www.xiaomastack.com/2014/06/30/saltstackmasterz/
解决salt-master部分僵尸子进程问题
saltstack在线上稳定的运行了一段时间,最近发现时不时 master 的少量的子进程变成了僵尸进程,最快的解决方法是重启master,但是治标不治本,一段时间后又会出现少量的僵尸进程。开始还以为是master的子进程启少了,如是修改 /etc/salt/master 配置文件增加子线程的数量,但是还是会发现僵尸进程。
经过一段时间的摸索,发现master端的超时时间默认是 5s 。由于运维平台有更多的采集任务需要master来执行,master在有任务突发的情况下,有些配置的下发或者脚本的执行很容易超时,超时的最直接结果是“配置和操作步骤都没有问题,但是批量执行时会随机的报错,把报错的任务单独执行又完全正确”。
解决方法是更改 /etc/salt/master 配置文件,将 timeout 项的注释取消,将时间改成 5s 的倍数(这只是我改参数的习惯。其它也行,只要比5s大合适就行)。然后重启 master 就不会出现僵尸进程了。
转载请注明出处 http://www.xiaomastack.com/2014/06/30/saltstackmasterz/ 谢谢!
http://www.xiaomastack.com/2014/06/27/python-salt-api/
之前写过用PHP实现salt-api调用,由于业务需求又整了个Python版的,实现的思路和PHP一样,这里只贴出访问带1个参数或不带参数salt执行模块的代码,如果需要使用更多的参数,多堆几段代码就好了。如果不懂 saltstack 或 salt-api 建议参考PHP那篇中给的链接先好好学习学习(saltsatck是个运维利器,值得你这么做)。
先贴出我的代码,不好勿喷:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
#!/usr/bin/python # -*- coding: utf-8 -*- import pycurl import StringIO #登录salt-api,获取token def api_login(): global token ch = pycurl.Curl() ch.setopt(ch.URL, url) info = StringIO.StringIO() ch.setopt(ch.WRITEFUNCTION, info.write) ch.setopt(ch.POST, True ) #如果是https就要开启这两行 ch.setopt(ch.SSL_VERIFYPEER, 0 ) ch.setopt(ch.SSL_VERIFYHOST, 2 ) ch.setopt(ch.HTTPHEADER, [ 'Accept: application/x-yaml' ]) ch.setopt(ch.POSTFIELDS, 'username=你的用户名&password=对应用户的密码&eauth=pam' ) #要包头信息 #ch.setopt(ch.HEADER, True) #不要包头信息 ch.setopt(ch.HEADER, False ) ch.perform() html = info.getvalue() #提取token token = html.split( "\n" )[ - 3 ].replace( "\n" , '') token = token.split( ' ' )[ 3 ] info.close() ch.close() def api_exec(target, fun, arg = '', arg_num = 0 ): global token ch = pycurl.Curl() ch.setopt(ch.URL, url) info = StringIO.StringIO() ch.setopt(ch.WRITEFUNCTION, info.write) ch.setopt(ch.POST, True ) ch.setopt(ch.SSL_VERIFYPEER, 0 ) ch.setopt(ch.SSL_VERIFYHOST, 2 ) ch.setopt(ch.HTTPHEADER, [ 'Accept: application/x-yaml' , "X-Auth-Token: %s" % (token)]) if arg_num = = 0 : ch.setopt(ch.POSTFIELDS, "client=local&tgt=%s&fun=%s" % (target, fun)) elif arg_num = = 1 : ch.setopt(ch.POSTFIELDS, "client=local&tgt=%s&fun=%s&arg=%s" % (target, fun, arg)) ch.setopt(ch.HEADER, False ) ch.perform() html = info.getvalue() info.close() ch.close() return html #测试时用的,做为模块使用时请注释下面两行 api_login() print api_exec( '主机key' , 'test.ping' , '', 0 ) |
先亮执行结果截图,哈哈:
关键的地方是提取经过认证后的 token,不要忘记除掉结尾的换行符”\n”,不然就悲剧了。
转载请注明出处http://www.xiaomastack.com/2014/06/27/python-salt-api/ 谢谢!
请问这个能分享和共同学习一下?
最近也在边学边写运维平台,刚好也是用django;方便给下代码吗?感谢!
我一哥们儿开源了一个,也是用的Django,你可以参考下:
https://github.com/binbin91/oms你好,我现在已经做好一部分自动化运维平台django+bootstrap实现,完成资产管理,部分配置管理,堡垒机全部功能,现在想接入zabbix告警报表,看你的做的不错,能共享下吗,可以QQ私聊,你需要我的也可以共享。代码写的烂 现在主要是思路 希望慢慢优化,完善 。谢谢 QQ:1873447820
已加,不过我的zabbix告警报表没有接到平台上。
方便发一下代码给我参考一下么,我也一直想开发这样一个平台
已发邮件
小马哥,搞的不错开源么?
小马哥?
今天刚上班,呵呵
每个公司的运维环境和需求不一样,还有就是代码不够好就不开源了,望见谅。