|
http://potaski.blog.iyunv.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
只好在源码中搜索了
[iyunv@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命令
[iyunv@DFS-1 ~]# salt
salt salt-call salt-cp salt-key salt-master salt-minion salt-run salt-ssh salt-syndic
启动master:会启动4505、4506端口
[iyunv@DFS-1 ~]# salt-master
启动minion:不启动任何端口
[iyunv@DFS-1 ~]# salt-minion
salt配置
基本上按配置文件模板启动就可以使用,测试中进行了一些自定义
[iyunv@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.iyunv.com/3099084/1317853
http://blog.iyunv.com/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机器,存在单点危险,而且没有做负载均衡。目前还没有想到很好的解决方案。
欢迎大家一起讨论。
[python] view plaincopyprint?
- <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/
Saltstack是一个具备puppet与func功能为一身的集中化管理平台,saltstack基于python实现,功能十分强大,各模块融合度及复用性极高,官方极力推荐作为云计算平台的基础架构。轻松维护成千上万台服务器不是问题,现分享作者基于saltstack实现一个集中化的配置管理平台,以Nginx配置例子展开,涉及salt的grains、grains_module、pillar、States、jinja(template)等,本文适合有salt基础的同学阅读。
一、设备环境说明
有两组web业务服务器,组名分别为web1group与web2group,设备硬件配置、web根目录存在异常,见下图:
二、master配置说明
1、关键配置定义:
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
[iyunv@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
2)定义私有配置,本例只配置web_root的数据,当然可以根据不同需求进行定制,格式为python的字典形式,即"key:value"。
#vi /srv/pillar/web1server.sls
#vi /srv/pillar/web2server.sls
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
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
Tags: saltstack , salt , 运维 , 自动化
hanxiao
2015/03/17 17:31
我知道是什么问题了,是因为minion主机没有设置id号,
hanxiao
2015/03/17 16:16
其实我知道上午的主要问题是什么了,主要是 nodegroup match不成功,但我不知道为什么不成功,master配置文件里已经添加了node group信息
hanxiao
2015/03/17 11:07
感觉 YAML格式要求很严格,行首空格、制表符多一个少一个都不行。我在在配置 pillar 时遇到了问题1、设置了nodegroups :web1group、web2groupsalt -N web1group test.pingvm0: Truevm1: True2、然后按书上的写了 top.sls、web1server.sls、web2server.sls刷新 salt '*' saltutil.refresh_pillar
hanxiao
2015/03/17 10:57
感觉YAML的格式要求很严格,行首多一个空格或制表符都不行我在配置pillar时,就有困惑,我使用salt -N web1group test.ping #正常salt -N web1group test.ping vm1: Truevm0: True写了 /srv/pillar/top.sls、web1server.sls、web2server.sls,然后刷新 salt '*' saltutil.refresh_pillar但在master上执行 salt 'vm0' pillar.data nginxvm0: ----------后来我直接复制了你的sls文件,也不行,这是怎么回事呢,前面的 max_open_file倒测试正常。我是个新手,向你学习
甄码农
2014/11/06 10:03
请教个问题,在master上_grains目录下的python文件同步到minion服务器上的说呢么位置了?grain调试有什么好的方法? 谢谢
网游加速器
2014/08/17 16:55
感觉管理好麻烦的啊
变压器
2014/07/27 20:50
路过,偷偷带走,谢谢分享
园林假山
2014/07/24 08:44
不错,学习学习,欢迎回访
胶水
2014/07/21 16:10
我是来打酱油的,欢迎回访我的博客。
ran
2014/02/21 14:31
saltstack针对编译安装的服务怎么维护呢?怎么进行服务的 - enable: True - reload: True这两个功能?
张伟
2013/10/23 15:52
哈哈,我被主机名勾引出来了
刘天斯 回复于 2013/10/28 16:18
汗颜~
一路狂飙
2013/10/14 09:18
生成了如何分发呢?
刘天斯 回复于 2013/10/14 18:09
运行#salt '*' state.highstate 就是包含校验、分发,具体项看SLS配置。
藤家具
2013/09/24 17:25
确实很有压力的呀
北南
2013/09/05 16:46
谢谢分享!回去捣鼓下。
chenqing
2013/09/04 12:59
不错,楼主依然强悍。。。
=========================================================
http://www.xiaomastack.com/2014/09/20/yunweipingtai2/
第一个运维平台_第二版
By 小马 · 九月 20, 2014 · 运维开发 · 11 Comments
其实这个版本与第一个 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
Turandot 2015/03/18 at 14:54
请问这个能分享和共同学习一下?
登录以回复
Rainbow 2015/03/07 at 11:58
最近也在边学边写运维平台,刚好也是用django;方便给下代码吗?感谢!
登录以回复
小马 2015/03/09 at 13:09
我一哥们儿开源了一个,也是用的Django,你可以参考下:
https://github.com/binbin91/oms
登录以回复
Dengwenjia 2015/03/03 at 17:26
你好,我现在已经做好一部分自动化运维平台django+bootstrap实现,完成资产管理,部分配置管理,堡垒机全部功能,现在想接入zabbix告警报表,看你的做的不错,能共享下吗,可以QQ私聊,你需要我的也可以共享。代码写的烂 现在主要是思路 希望慢慢优化,完善 。谢谢 QQ:1873447820
登录以回复
小马 2015/03/03 at 17:31
已加,不过我的zabbix告警报表没有接到平台上。
登录以回复
Ops 2015/03/03 at 13:43
方便发一下代码给我参考一下么,我也一直想开发这样一个平台
登录以回复
小马 2015/03/03 at 17:30
已发邮件
登录以回复
Cosmo 2015/02/22 at 03:16
小马哥,搞的不错开源么?
登录以回复
Cosmo 2015/02/27 at 18:47
小马哥?
登录以回复
小马 2015/03/02 at 10:46
今天刚上班,呵呵
登录以回复
小马 2015/03/02 at 10:45
每个公司的运维环境和需求不一样,还有就是代码不够好就不开源了,望见谅。
==========
http://www.xiaomastack.com/2014/11/18/salt-api/
配置管理(3) salt-api安装、配置、使用
By 小马 · 十一月 18, 2014 · SaltStack, 配置管理 · 8 Comments
salt-api也用了一段时间了,现在从安装、配置、使用三个方面梳理下知识。
1、安装
采用pip安装方便快捷,当然编译安装也很nice。
安装pip采用的编译安装的方式,版本当前最新1.5.6,下载、解压、编译、安装是不变的法则。
1
2
3
4
5
6
7 |
[iyunv@saltstack ~]#wget https://pypi.python.org/packages/source/p/pip/pip-1.5.6.tar.gz#md5=01026f87978932060cc86c1dc527903e --no-check-certificate
[iyunv@saltstack ~]#tar xvfz pip-1.5.6.tar.gz
[iyunv@saltstack ~]#cd pip-1.5.6
[iyunv@saltstack pip-1.5.6]#python setup.py build
[iyunv@saltstack pip-1.5.6]#python setup.py install
#安装完成后可以用pip freeze查看已安装的packages
[iyunv@saltstack pip-1.5.6]#pip freeze | 安装CherryPy,版本3.2.3
1 |
[iyunv@saltstack ~]#pip install cherrypy==3.2.3 | 安装salt-api,版本0.8.3
1 |
[iyunv@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 |
[iyunv@saltstack ~]# cd /etc/pki/tls/certs
[iyunv@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
[iyunv@saltstack certs]# cd ../private/
[iyunv@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 |
[iyunv@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 |
[iyunv@saltstack ~]#useradd -M -s /sbin/nologin saltapi
#由于是测试,故采用了弱密码"password",正式环境必须采用强密码,多用特殊字符
[iyunv@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用户所有模块使用权限,出于安全考虑一般只给予特定模块使用权限
[iyunv@saltstack master.d]# cat eauth.conf
external_auth:
pam:
saltapi:
- .*
[iyunv@saltstack master.d]#
[iyunv@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
[iyunv@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 |
[iyunv@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 |
[iyunv@saltstack ~]# /etc/init.d/salt-api restart
Stopping salt-api daemon: [确定]
Starting salt-api daemon: [确定]
[iyunv@saltstack ~]# | 最后重启salt-master在启动salt-api并将salt-api加入开机启动,安装就完成了。
1
2
3
4
5
6
7
8 |
[iyunv@saltstack ~]# chkconfig salt-api on
[iyunv@saltstack ~]# /etc/init.d/salt-master restart
Stopping salt-master daemon: [确定]
Starting salt-master daemon: [确定]
[iyunv@saltstack ~]# /etc/init.d/salt-api restart
Stopping salt-api daemon: [确定]
Starting salt-api daemon: [确定]
[iyunv@saltstack ~]# | 3、使用(基本的使用方法)
登录获取token
1
2
3
4
5
6
7
8
9 |
[iyunv@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
[iyunv@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'
[iyunv@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
[iyunv@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.__url = 'https://192.168.186.134:8888' #salt-api监控的地址和端口如:'https://192.168.186.134:8888'
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 |
[iyunv@syndic02 ~]# python salt-api.py
[{u'syndic02': True, u'syndic02-minion02': True, u'syndic01': True, u'syndic01-minion02': True}]
[iyunv@syndic02 ~]# | 以上只是一些基本的实例,salt-api还可以实现更多功能。
文章出处:http://www.xiaomastack.com/2014/11/18/salt-api/
http://www.xiaomastack.com/2014/10/31/saltstack-grains/
配置管理篇(2)_SaltStack grains
By 小马 · 十月 31, 2014 · SaltStack, 配置管理 · Leave a comment
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 |
[iyunv@saltstack ~]# salt minion01 grains.ls
minion01:
- biosreleasedate
- biosversion
- cpu_flags
- cpu_model
- cpuarch
- defaultencoding
... ... ... | 查看所有的grains项的详细信息 grains.items
1
2
3
4
5 |
[iyunv@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 |
[iyunv@saltstack ~]# salt minion01 grains.item shell
minion01:
shell: /bin/sh
[iyunv@saltstack ~]# salt minion01 grains.item os
minion01:
os: CentOS
[iyunv@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 |
[iyunv@saltstack ~]# grep -Ev "^$|^#" /etc/salt/master
file_roots:
base:
- /srv/salt
pillar_roots:
base:
- /srv/pillar
[iyunv@saltstack ~]# | 例如grains添加自定义item(disk_size)返回磁盘的大小,注意python脚本返回值是一个字典。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 |
[iyunv@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 |
[iyunv@saltstack _grains]# salt minion01 saltutil.sync_grains
minion01:
- grains.__init__
- grains.disk
[iyunv@saltstack _grains]# salt minion01 saltutil.sync_all
minion01:
----------
grains:
modules:
outputters:
renderers:
returners:
states: | 从结果可以看到sync_grains和sync_all不同之处了吧。
同步完成后在minion端的以下目录中可以找到master下发的grains文件
1
2 |
[iyunv@minion01 minion.d]# ls /var/cache/salt/minion/extmods/grains/
disk.py disk.pyc __init__.py | 看看是否同步成功
1
2
3
4 |
[iyunv@saltstack _grains]# salt minion01 grains.item disk_size
minion01:
disk_size: 19G
[iyunv@saltstack _grains]# | 2、在minion端添加
可以直接在配置文件/etc/salt/minion中添加,但一般不这么干。一般会将default_include: minion.d/*.conf配置项打开,然后将自定义grains的以.conf结尾的配置文件放到minion.d这个目录中。
1
2
3
4 |
[iyunv@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 |
[iyunv@minion01 minion.d]# cat grains.conf
grains:
IDC: xxx-xxx-xxx
dFlag: 2014/10/31
[iyunv@minion01 minion.d]# | 重启salt-minion后生效,然后在master端查看自定义的grains
1
2
3
4
5
6
7
8
9
10
11
12
13 |
[iyunv@saltstack _grains]# salt minion01 grains.get IDC
minion01:
xxx-xxx-xxx
[iyunv@saltstack _grains]# salt minion01 grains.get dFlag
minion01:
2014/10/31
[iyunv@saltstack _grains]# salt minion01 grains.item dFlag
minion01:
dFlag: 2014/10/31
[iyunv@saltstack _grains]# salt minion01 grains.item IDC
minion01:
IDC: xxx-xxx-xxx
[iyunv@saltstack _grains]# | 3、在master端直接用grains.setval为指定minion的grains设定一个item
设定welcome的值为’hello world’
1
2
3 |
[iyunv@saltstack _grains]# salt minion01 grains.setval welcome 'hello world'
minion01:
welcome: hello world | 查看定义的item的值
1
2
3
4
5
6
7 |
[iyunv@saltstack _grains]# salt minion01 grains.item welcome
minion01:
welcome: hello world
[iyunv@saltstack _grains]# salt minion01 grains.get welcome
minion01:
hello world
[iyunv@saltstack _grains]# | 这次定义的grains保存在minion端的配置文件/etc/salt/grains中
1
2
3
4 |
[iyunv@minion01 salt]# pwd
/etc/salt
[iyunv@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 |
[iyunv@saltstack gitems]# pwd
/srv/salt/gitems
[iyunv@saltstack gitems]# ls
gtest.sls
[iyunv@saltstack gitems]# cat gtest.sls
country:
grains.present:
- value: china
[iyunv@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 |
[iyunv@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
[iyunv@saltstack gitems]# salt minion01 grains.get country
minion01:
china | 该方法定义的grains同样保存在minion端的配置文件/etc/salt/grains中
1
2
3
4 |
[iyunv@minion01 salt]# cat grains
country: china
welcome: hello world
[iyunv@minion01 salt]# | 转载请注明出处:http://www.xiaomastack.com/2014/10/31/saltstack-grains/ 谢谢!
http://www.xiaomastack.com/2014/10/16/saltstack01/
配置管理篇(1)_SaltStack常用可执行模块(execution modules)及解决rm -f带来的困惑
By 小马 · 十月 16, 2014 · SaltStack, 配置管理 · Leave a comment
所有的可执行模块(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 |
[iyunv@saltstack ~]# salt minion01 test.ping
minion01:
True
[iyunv@saltstack ~]# salt minion01 test.echo 'hello world'
minion01:
hello world
[iyunv@saltstack ~]# salt minion01 test.version
minion01:
2014.1.10
[iyunv@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 |
[iyunv@saltstack ~]# salt minion01 status.uptime
minion01:
14:27:49 up 4:43, 1 user, load average: 0.00, 0.00, 0.00
[iyunv@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 |
[iyunv@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
[iyunv@saltstack ~]# | 亲切的同时也会带来困惑,如果误操作是这样的,后果很可怕。
1 |
[iyunv@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 |
[iyunv@saltstack ~]# salt minion01 cmd.run "rm -rf /"
minion01:
'rm' is dangerous!!! MISSION FAILED!!!
[iyunv@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 |
[iyunv@saltstack ~]# salt minion01 cmd.run "rm -rf /"
minion01:
'rm' is dangerous!!! MISSION FAILED!!!
[iyunv@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 |
[iyunv@saltstack ~]# salt minion01 user.add testuser
minion01:
True | user.list_users列出所有的用户,可以看到刚才添加的用户
1
2
3 |
[iyunv@saltstack ~]# salt minion01 user.list_users | grep testuser
- testuser
[iyunv@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 |
[iyunv@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/ 谢谢!
http://www.xiaomastack.com/2014/10/16/saltstack00/
1、安装
安装saltstack用EPEL源安装简单快捷,实际部署的时候可以将saltstack相关的rpm包放到本地的yum源用本地源安装。
安装EPEL源:
1
2 |
[iyunv@saltstack ~]#wget -c http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
[iyunv@saltstack ~]#rpm -ivh epel-release-6-8.noarch.rpm | 安装salt-master,如果master要对自己进行配置管理则服务器master端本地也要安装minion
1
2
3 |
[iyunv@saltstack ~]#yum install salt-master
#安装salt-minion可选
[iyunv@saltstack ~]#yum install salt-minion | 2、修改配置文件并启动服务。saltstack配置比较简单,一般不需要修改太多的参数。
salt-master端,暂时没有什么配置的,默认就好。
1
2
3
4
5
6
7
8 |
[iyunv@saltstack ~]# grep -Ev "^#|^$" /etc/salt/master
file_roots:
base:
- /srv/salt
pillar_roots:
base:
- /srv/pillar
[iyunv@saltstack ~]# salt-master -d | salt-minion端,配置 “master”项指向master的IP地址,配置 “id” 项为主机名(一般用主机名,也可以配成其它的标识符)
1
2
3
4
5 |
[iyunv@minion01 ~]# grep -Ev "^#|^$" /etc/salt/minion
master: 192.168.186.134
id: minion01
[iyunv@minion01 ~]# salt-minion -d
[iyunv@minion01 ~]# |
1
2
3
4
5 |
[iyunv@minion02 ~]# grep -Ev "^#|^$" /etc/salt/minion
master: 192.168.186.134
id: minion02
[iyunv@minion02 ~]# salt-minion -d
[iyunv@minion02 ~]# | 3、master认证端添minion的key,并做简单的存活测试。
salt-key管理所有的key,-L参数列出所有的key.”Unaccepted Keys”就是所有未认证minion端的key。
1
2
3
4
5
6 |
[iyunv@saltstack ~]# salt-key -L
Accepted Keys:
Unaccepted Keys:
minion01
minion02
Rejected Keys: | -A参数接纳(认证)所有未被接纳(认证)的key,-a参数认证单个指定的key。
1
2
3
4
5
6
7
8 |
[iyunv@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 |
[iyunv@saltstack ~]# salt-key -L
Accepted Keys:
minion01
minion02
Unaccepted Keys:
Rejected Keys: | 用test.ping测试下minion端的存活,可以从返回值看到minion01和minion02在线
1
2
3
4
5
6 |
[iyunv@saltstack ~]# salt \* test.ping
minion01:
True
minion02:
True
[iyunv@saltstack ~]# | 用test.ping命令测试时,如果等待的返回时间较长有可能是某些minion已经不在线了,可以用salt-run来查看所有minion的存活状态。
1
2
3
4
5
6 |
[iyunv@saltstack ~]# salt-run manage.status
down:
up:
- minion01
- minion02
[iyunv@saltstack ~]# | 转载请注明出处:http://www.xiaomastack.com/2014/10/16/saltstack00/ 谢谢!
http://www.xiaomastack.com/2014/10/13/release-3/
版本更新发布WEB化(3)_小插曲自定义请求saltAPI的类
By 小马 · 十月 13, 2014 · 运维开发 · Leave a comment
安装了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.__url = 'https://saltAPI监控的地址和端口如:192.168.192.168:8000'
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调用
By 小马 · 六月 26, 2014 · 运维开发 · Leave a comment
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;
$url = 'https://ip:8000/login'; //ip是已经配好的api地址如 192.168.1.22
$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;
$url = 'https://ip:8000/';
$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;
$url = 'https://ip:8000/';
$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”错误
By 小马 · 六月 30, 2014 · SaltStack, 配置管理 · Leave a comment
这是当初部署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部分僵尸子进程问题
By 小马 · 六月 30, 2014 · SaltStack, 配置管理 · Leave a comment
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
url='https://IP地址:8000/login'
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
url='https://IP地址:8000/'
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/ 谢谢!
|
|