...html
http://www.vpsee.com/2013/08/a-system-configuration-management-and-orchestration-tool-saltstack/java
2013年08月22日 | 标签: devops, puppet, salt, saltstack | 做者:vpseenode
咱们的服务器由 Puppet 配置管理工具来管理,服务器上线后由 puppet 完成初始化和配置等一系列工做(好比,静态 IP 配置,DNS 设置,NFS/SAN 挂载,LDAP/Kerberos 登陆,安全加固配置,内核参数优化,防火墙规则配置等等),等初始化完成后开始运行,运行一段时间后有一些须要自动和手动操做的任务(好比升级、重启、备份等),这时候咱们使用 Fabric 来批量执行这些临时任务。python
因此从这里能够看到 Puppet 和 Fabric 实际上是两个不一样性质的工具,看下面的归类可能会更清楚一些。Puppet 和 Fabric 两个的工做其实能够由一个工具 SaltStack(或 AnsibleWorks)完成,减小一个工具的使用会减轻一点负担(学习工具的人力成本、安装和配置工具的时间成本等等)。react
操做系统和软件的安装、配置、初始化等;
(Puppet, Chef, CFEngine, AnsibleWorks, SaltStack, …)linux自动执行任务,好比按期备份、清除日志等;
(Fabric, AnsibleWorks, SaltStack, …)git手动执行任务,好比部署应用、升级、重启、检查和校验文件系统、增长用户等。
(Fabric, Rake, Func, Rundeck, AnsibleWorks, SaltStack, …)github
SaltStack 采用 zeromq 消息队列进行通讯,和 Puppet/Chef 比起来,SaltStack 速度快得多。还有一点咱们喜欢 SaltStack 的地方是它是 Python 写的,比 Puppet/Chef 这些 Ruby 工具更接近咱们的能力圈。web
和大多数相似工具同样,SaltStack 须要在一台机器(主控)上安装服务器端软件(SaltStack 称之为 salt master),在多台机器(受控)上安装客户端软件(SaltStack 称之为 salt minion)。在主控机器上给下属(受控)发命令,在受控机器上接受和执行上级(主控)的命令。redis
在 Ubuntu 上安装 salt master:
$ sudo add-apt-repository ppa:saltstack/salt $ sudo apt-get update $ sudo apt-get install salt-master
在 CentOS 6.x 上安装 salt master:
# rpm -Uvh http://ftp.linux.ncsu.edu/pub/epel/6/i386/epel-release-6-8.noarch.rpm # rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6 # yum update # yum install salt-master
在 Ubuntu 上安装 salt minion:
$ sudo add-apt-repository ppa:saltstack/salt $ sudo apt-get update $ sudo apt-get install salt-minion
在 CentOS 6.x 上安装 salt minion:
# rpm -Uvh http://ftp.linux.ncsu.edu/pub/epel/6/i386/epel-release-6-8.noarch.rpm # yum update # yum install salt-minion
安装完 salt minion 后记得修改配置文件,让 salt minion 指向 salt master 服务器地址:
$ sudo vi /etc/salt/minion ... # Set the location of the salt master server, if the master server cannot be # resolved, then the minion will fail to start. master: saltmaster.vpsee.com ... $ sudo restart salt-minion
在 master 上执行 salt-key list 就会看到有个 minion1.vpsee.com 请求加入受控,执行 -a 接受请求后,主控和受控之间的信任关系就创建起来了,主控就能够任意 “摆布” 受控了:
# salt-key list Accepted Keys: Unaccepted Keys: minion1.vpsee.com Rejected Keys: # salt-key -a minion1.vpsee.com The following keys are going to be accepted: Unaccepted Keys: minion1.vpsee.com Proceed? [n/Y]
在主控机器上执行一个命令,让全部受控机器执行 hostname 命令:
# salt '*' cmd.run "hostname" minion1.vpsee.com: minion1.vpsee.com
在主控机器上执行一个命令,让全部受控机器上执行内建 test.ping 命令:
# salt '*' test.ping minion1.vpsee.com: True
还有一些内建命令能够尝试:
# salt '*' disk.usage # salt '*' network.interfaces
开头的时候咱们说了 SaltStack = Fabric + Puppet,上面 “执行命令的例子” 演示了 Fabric 相似的功能,这里要演示的是 Puppet 相似的功能,在主控上定义好系统配置应该有的状态,而后受控自动完成相应的操做和配置。
首先肯定状态定义的文件应该放在什么地方,如下操做都在主控(salt master)上执行。检查 /etc/salt/master 文件的 file_roots 条目,默认是在 /srv/salt 下,若是没有这个目录还须要手动建立一个:
# vi /etc/salt/master ... #file_roots: # base: # - /srv/salt ... # mkdir /srv/salt
好比咱们想在全部受控机器上安装 vim 软件包,并使用本身定义的 vimrc 文件:
# vi /srv/salt/vim.sls vim: pkg.installed /etc/vimrc: file.managed: - source: salt://vimrc - mode: 644 - user: root - group: root # vi /srv/salt/vimrc syntax enable set textwidth=79 set shiftwidth=4 set tabstop=4 set expandtab set softtabstop=4 set shiftround set fileencodings=utf-8 set encoding=utf8 set tenc=utf8
强制执行这个状态:
# salt '*' state.sls vim
再来一个例子,参考 “安装和使用系统监控工具 Glances” 一文,咱们想在全部受控机器上安装 Glances,如何实现呢?
# vi /srv/salt/glances.sls python-pip: pkg.installed build-essential: pkg.installed python-dev: pkg.installed glances: pip.installed: - require: - pkg: python-pip
强制执行这个状态:
# salt '*' state.sls glances ... minion1.vpsee.com: ---------- State: - pip Name: glances Function: installed Result: True Comment: Package was successfully installed Changes: Glances==1.7.1: Installed ...
YC - August 24th, 2013 3:11 pm
前一段时间调研过saltstack,ansible,chef-solo三个自动化部署工具,最后决定用ansible。看来有空要试试saltOwnLinux - August 28th, 2013 1:34 pm有个地方须要更正一下。
默认是在 /srv/salt 下,若是没有这个目录还须要手动建立一个:
# vi /etc/salt/master
...
#file_roots:
# base:
# - /srv/salt
...
# mkdir /srt/salt
应该是 mkdir /srv/salt,后还有几个笔误的地方。
#########################################################################################################
http://blog.halfss.com/blog/2013/09/06/ge-ren-dui-yun-wei-ji-yun-wei-zi-dong-hua-de-li-jie/
如下内容为我的理解,若有不对,请及时指出,谢谢
对于运维来讲,基于状态的配置管理已经向自动化迈进了一大步,以状态为核心的运维,让状态自己有了可管理性;在运维过程当中咱们会发现,一样的一个配置,咱们会在不一样的时间,不一样的地点一次在一次的配置,这个时候,配置管理就有了重复性;有的甚至是原封不动的重复,而另一些则是按照必定的规律在发展,这些按照必定规律发展的配置,就是可预测的.综上我认识的,咱们运维工做的自己是可管理,可重复,可预测的.基于这样的理念,咱们就能够更进一步的推动咱们的运维自动化,甚至到智能化. 看到这里,我理想中的运维自动化的配置管理平台应该有以下功能:
1:对状态的配置及管理(最基本的) 2:能够及时的对系统状态进行调整并能看到结果(实时性和反馈性) 3:能够对其自己作方便的第三方管理(方便的将运维与其余管理作整合)
加分项:
1:开发语言单一 2:架构简单,灵活 3:有不错的安全性 4:没有商业版(我的偏见)
下面是现有比较有表明性的自动化配置管理工具:
附:如下仅基于开源版本进行介绍
基本属性(每项5分) 加分项目(每项1分) 总分 状态管理 实时管理 架构简单,灵活 开发语言单一 有API 有反馈系统 puppet 5 3.5 1 1 0 0 10.5 chef 5 1 -1 -1 1 0 5 salt 4 5 1 1 1 1 13
附:
到这里,若是你如今正要选择一个运维自动化的工具的时候,毋庸置疑,就是salt了
最近也出来一个比较新的运维自动化的工具:ansible(http://www.ansibleworks.com/),对于ansible我研究的很少,简单说下ansible与salt的状况:
1:2者仅仅从大的功能上来讲,区别不大 2:ansible:基于ssh(如今也能够基于消息),免安装(部分功能仍是须要安装的,不过跟salt比安装,配置方面就方便不少了),快捷方便,但也就限制在里linix/unix平台上;自带完善是Web管理,API,数据存在基于数据库; 总体看起来比较完整; 算是一个商业产品级 3:salt在产品这块的总体布局目前看起来不是很成熟(我感受salt在产品这块的切入点很不错),是一帮纯粹工程师搞出来的东西;虽然简单,灵活,强大,可是真实在实际使用过程当中,本身还会遇到很多的问题; 算是一个社区项目;不够salt的迭代很是快,我相信很快就汇成熟 ansible是从商业目的出发,而后作开源 salt是从技术与应用目的出发,如今也算是在作部分商业产品 因此我跟趋向于salt
这里有一个对比salt和ansible的文章:http://missingm.co/2013/06/ansible-and-salt-a-detailed-comparison/
我简单的说下文章的内容: 在速度上通常状况下salt比ansible快 在安全性上ansible略好于salt 安装&部署&维护上ansible好于salt 在对状态的管理的时候ansible也比salt优雅 最后做者更倾向于ansible;同时也说:也会使用salt;salt和ansible是都是很是优秀的工具.
Sep 6th, 2013 ops
http://blog.halfss.com/blog/2013/05/22/yun-wei-zi-dong-hua-zhi-saltxue-xi-bi-ji/
1:服务端 1:安装 2:配置文件 3:运行 4:注意事项 2:客户端 1:安装 2:配置文件 3:运行 4:注意事项
1:基础知识 1:targeting 2:nodegroup 3:grains 4:pillar 2:状态管理 1:state 1:state语法 2:state的逻辑关系 2:highstate 3:salt schedule 3:实时管理 1:cmd.run 2:module 4:其余 1:无master 2:peer 3:runner 4:reactor
1:saltclient管理salt 2:salt api
运维的工做主要在2方面: 1:状态的管理 2:系统性能调优 这里主要简介下运维状态的管理: 对于运维来讲,基于状态的配置管理已经向自动化迈进了一大步,以状态为核心的运维,让状态自己有了可管理性;在运维过程当中咱们会发现,一样的一个配置,咱们会在不一样的时间,不一样的地点一次在一次的配置,这个时候,配置管理就有了重复性;有的甚至是原封不动的重复,而另一些则是按照必定的规律在发展,这些按照必定规律发展的配置,就是可预测的.综上我认识的,咱们运维工做的自己是可管理,可重复,可预测的.基于这样的理念,咱们就能够更进一步的推动咱们的运维自动化,甚至到智能化. 看到这里,我理想中的运维自动化的配置管理平台应该有以下功能: 1:对状态的配置及管理(最基本的) 2:能够及时的对系统状态进行调整并能看到结果(实时性和反馈性) 3:能够对其自己作方便的第三方管理(方便的将运维与其余管理作整合) 加分项: 1:开发语言单一 2:架构简单,灵活 3:有不错的安全性 4:没有商业版(我的偏见) 下面是现有比较有表明性的自动化配置管理工具: 附:如下仅基于开源版本进行介绍 理念 优缺点 puppet 从运维的角度去作配置管理(运维人员作给运维用的) 架构简单,系统比较成熟/不便于第三方管理 chef 从研发的角度去作配置管理(研发人员作给运维用的) 较便于第三方管理,对自身(节点,变量,cookbook)的管理较方便,有本身的dashboard,cookbook支持版本管理,自从cookbook的版本管理/架构复杂,开发语言较多,(安全问题) 以上2者都比较侧重于状态的管理,对单个或者多个状态的临时调整或者管理较差 2个都有商业版,让我这个用开源版的很自卑 这里咱们也能看到,2个配置功能都没能达到我理想中的状态,那就暂用chef吧,直到有一天,了解到了saltstack看到了这句话:“ 系统配置的自动化不只可预测,可重复, 还具备可管理性”(http://wiki.saltstack.cn/reproduction/dive-into-saltstack),这尼玛才是运维自动化的将来啊,因而毫无节操的开始学习salt,并且发现越学越喜欢;在我使用puppet及chef的时候都没有使用salt的感受,太爽了。因此我这里仅仅介绍基本的语法不涉及实际用例,salt的安装很是方便,因此你在看本文档的时候但愿你能真正的动手去作一下,而后你就会爱上salt了 附::若是你会python,salt基本是不须要怎么学的,而我正好了解一点py,不过这最多占我选择salt的20%。 最近也出来一个比较新的运维自动化的工具:ansible(http://www.ansibleworks.com/),对于ansible我研究的很少,简单说下ansible与salt的状况: 1:2者仅仅从大的功能上来讲,区别不大 2:ansible:基于ssh(如今也能够基于消息),免安装(部分功能仍是须要安装的,不过跟salt比安装,配置方面就方便不少了),快捷方便,但也就限制在里linix/unix平台上;自带完善是Web管理,API,数据存在基于数据库; 总体看起来比较完整; 算是一个商业产品级 3:salt在产品这块的总体布局目前看起来不是很成熟(我感受salt在产品这块的切入点很不错),是一帮纯粹工程师搞出来的东西;虽然简单,灵活,强大,可是真实在实际使用过程当中,本身还会遇到很多的问题; 算是一个社区项目;不够salt的迭代很是快,我相信很快就汇成熟 ansible是从商业目的出发,而后作开源 salt是从技术与应用目的出发,如今也算是在作部分商业产品 因此我跟趋向于salt 这里有一个对比salt和ansible的文章:http://missingm.co/2013/06/ansible-and-salt-a-detailed-comparison/ 我简单的说下文章的内容: 在速度上通常状况下salt比ansible快 在安全性上ansible略好于salt 安装&部署&维护上ansible好于salt 在对状态的管理的时候ansible也比salt优雅 最后做者更倾向于ansible;同时也说:也会使用salt;salt和ansible是都是很是优秀的工具.
salt是一个新的基础平台管理工具。很短的时间便可运行并使用起来, 扩展性足以支撑管理上万台服务器,数秒钟便可完成数据传递. 常常被描述为 Func增强版+Puppet精简版。 salt的整个架构都是基于消息来实现.因此可以提供很强的拓展性,灵活性,实时性; 不过salt仍是一个很年轻的东西,还有不少地方不够完善,作的不够好,不过我相信这些都只是时间问题。 注:如下文档仅仅为基本内容,相关知识点的深刻学习,请看相应文档链接
安装有不少途径,做为一个CentOS的用户,我选择rpm 首先添加RPM源: rpm -ivh http://mirrors.sohu.com/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm 附:实际生产中我是自建源 epel中关于salt的包: salt-api.noarch : A web api for to access salt the parallel remote execution system salt-master.noarch : Management component for salt, a parallel remote execution system salt-minion.noarch : Client component for salt, a parallel remote execution system salt.noarch : A parallel remote execution system salt-cloud.noarch : Generic cloud provisioning tool 1:服务端 1:安装 yum install salt-master -y 2:配置文件 /etc/salt/master 配置文件选项介绍: http://docs.saltstack.com/ref/configuration/master.html 最基本字段: interface: 服务端监听IP 3:运行 调试模式: salt-master -l debug 后台运行: salt-master -d 做为CentOS管理员,我选择: /etc/init.d/salt-master start 4:注意事项: 1:监听端口 4505(publish_port):salt的消息发布系统 4506(ret_port):salt客户端与服务端通讯的端口,主要用来接受消息 因此确保客户端能跟服务端的这2个端口通讯 2:客户端 1:安装 yum install salt-minion -y 2:配置文件 /etc/salt/minion 配置文件选项介绍: http://docs.saltstack.com/ref/configuration/minion.html 最基本字段: master: 服务端主机名 id: 客户端主机名(在服务端看到的客户端的名字) 3:运行 调试模式: salt-minion -l debug 后台运行: salt-minion -d 做为CentOS管理员,我选择: /etc/init.d/salt-minion start 4:注意事项: 1:minion默认和主机名为salt的主机通讯 2:关于配置文件 salt的配置文件均为yaml风格 $key: $value #注意冒号后有一个空格 3:基础知识 1:salt minion和master的认证过程: (1) minion在第一次启动时,会在/etc/salt/pki/minion/下自动生成minion.pem(private key), minion.pub(public key),而后将minion.pub发送给master (2) master在接收到minion的public key后,经过salt-key命令accept minion public key,这样在master的/etc/salt/pki/master/minions下的将会存放以minion id命名的public key, 而后master就能对minion发送指令了 以下: 启动服务端: /etc/init.d/salt-minion restart 启动客户端: /etc/init.d/salt-minion restart 服务端查看key: salt-key Accepted Keys: Unaccepted Keys: minion1 Rejected Keys: 服务端接受key salt-key -a minion1 测试: salt 'minion1' test.ping minion1: True 附:salt更多命令及手册 salt '*' sys.doc
1:基础知识 1:targeting salt '*' test.ping 引号中以实现很强大的minion的过滤与匹配技术 文档:http://docs.saltstack.com/topics/targeting/compound.html 经常使用命令: salt 'shell正则' 命令 salt -E 'prel 正则' salt -N $group 命令 salt -L 'server_id1,server_id2,server_id3' 命令 示例: salt -C 'webserv* and G@os:Debian or E@web-dc1-srv.*' test.ping 2:nodegroup 对minion进行分组 文档: http://docs.saltstack.com/topics/targeting/nodegroups.html 在master的配置文件中按以下格式定义: nodegroups: group1: 'L@foo.domain.com,bar.domain.com,baz.domain.com or bl*.domain.com' group2: 'G@os:Debian and foo.domain.com' 在state或者pillar中引用的时候以下: base: group1: - match: nodegroup - webserver 3:grains minion基本信息的管理 文档:http://docs.saltstack.com/topics/targeting/grains.html 基本使用: salt '*' grains.ls 查看grains分类 salt '*' grains.items 查看grains全部信息 salt '*' grains.item osrelease 查看grains某个信息 示例: salt '*' grains.item osrelease minoin1: osrelease: 6.2 在用salt进行管理客户端的时候或者写state的时候均可以引用grains的变量 4:pillar salt对敏感信息的管理,只有匹配到的节点才能获取和使用 文档:http://docs.saltstack.com/topics/tutorials/pillar.html 默认:pillar数据定义文件存储路径:/srv/pillar 入口文件:/srv/pillar/top.sls 格式: base: "targeting": - $pillar #名字为pillar.sls的文件来存放对匹配到的minion的变量 $pillar.sls 基本: $key: $value state引用方式: 复杂: users: thatch: 1000 shouse: 1001 utahdave: 1002 redbeard: 1003 state引用方式: 查看节点的pillar数据: salt 'client2' pillar.data 同步pillar: salt '*' saltutil.refresh_pillar 附:这里咱们能够看到,pallar中也可使用jinja(后面会提到)作一些处理 5:minion 即为salt的客户端 2:状态管理 1:state salt基于minion进行状态的管理 1:state语法 文档:http://docs.saltstack.com/ref/states/all/index.html 结构: $ID: #state的名字 $state: #要管理的模块类型 - $State states #该模块的状态 示例: vim: pkg: - installed 若是是redhard系列的就安装 vim-enhanced,若是系统是Debian或者Ubuntu就安装vim-nox 附:state默认使用jinja(http://jinja.pocoo.org/)的模板语法, 文档地址: http://jinja.pocoo.org/docs/templates/ 2:state的逻辑关系: 文档:http://docs.saltstack.com/ref/states/ordering.html require:依赖某个state,在运行此state前,先运行依赖的state,依赖能够有多个 httpd: pkg: - installed file.managed: - name: /etc/httpd/conf/httpd.conf - source: salt://httpd/httpd.conf - require: - pkg: httpd watch:在某个state变化时运行此模块 redis: pkg: - latest file.managed: - source: salt://redis/redis.conf - name: /etc/redis.conf - require: - pkg: redis service.running: - enable: True - watch: - file: /etc/redis.conf - pkg: redis 附:watch除具有require功能外,还增了关注状态的功能 还有与watch 和 require相反的watch_in,require_in order: 优先级比require和watch低 有order指定的state比没有order指定的优先级高 vim: pkg.installed: - order: 1 #让当前状态第一个运行,若是该状态依赖其余状态,依赖的状态会在这个状态运行前运行 想让某个state最后一个运行,能够用last 3:state与minion 临时给minoin部署个state salt 'minion1' state.sls 'vim' #给minion1加一个vim的state 执行该命令后能够当即看到输出结果 2:highstate 给minion永久下添加状态 文档: http://docs.saltstack.com/ref/states/highstate.html 默认配置文件:/srv/salt/top.sls 语法: '*': - core - wsproxy /srv/salt/目录结构: . ├── core.sls ├── top.sls └── wsproxy ├── init.sls ├── websocket.py └── websockify 应用: salt "minion1" state.highstate 测试模式: salt "minion1" state.highstate -v test=True 3:salt schedule 默认的state只有在服务端调用的时候才执行,不少时候咱们但愿minon自觉的去保持在某个状态 文档:http://docs.saltstack.com/topics/jobs/schedule.html cat /srv/pillar/top.sls base: "*": - schedule cat /srv/pillar/schedule.sls schedule: highstate: function: state.highstate minutes: 30 如上配置: minion会每30分钟从master拉去一次配置,进行自我配置 3:实时管理 有时候咱们须要临时的查看一台或多台机器上的某个文件,或者执行某个命令 1:cmd.run 用法 salt '$targeting' cmd.run '$cmd' 示例:salt '*' cmd.run 'hostname' 执行下这样的命令,立刻就感觉到效果了,速度还贼快 2:module 同时,salt也将一些经常使用的命令作了集成 文档:http://docs.saltstack.com/ref/modules/all/index.html 这里几乎涵盖了咱们全部的经常使用命令 好比: 查看全部节点磁盘使用状况 salt '*' disk.usage 4:其余 1:无master 文档:http://docs.saltstack.com/topics/tutorials/quickstart.html 主要应该在测试和salt单机管理的时候 2:peer 文档:http://docs.saltstack.com/ref/peer.html 提供了一种让某个或者某些minion经过master管理其余minoin的方法 既然minion均可以管理其余minion了,确定要涉及到权限的问题,不然就乱了;peer的权限设置在master配置文件的peer块 风格以下: peer: .*: #有管理权限的minion节点 - .* #可使用的module 例子: peer: .*example.com: #ID以example.com结尾的节点 - test.* #可使用test模块 - ps.* #可使用ps模块 - pkg.* #可使用pkg模块 3:runner 官方的想法是提供了一种灵活的,快捷的调用salt的方式,经过salt-run就能够直接在minion上运行本身的代码,可是我感受有点多余;我直接在master写也能够啊 定义runner代码目录: master配置文件: runner_dirs: ['/srv/salt/_runner',] 测试: cat /srv/salt/_runner/foo.py def test(): print "True" salt-run foo.test True 固然这里应该写的是关于salt的调用 官方自带的几个runner:https://github.com/saltstack/salt/tree/develop/salt/runners 4:reactor 官方文档: http://docs.saltstack.com/topics/reactor/index.html 这个模块将消息中的部分标签与部分sls绑定起来(绑定经过master的配置文件),sls定义了动做(作什么操做) 1:定义tag与sls的关系 vim /etc/salt/master reactor: - 'test': - /srv/reactor/test.sls 2:定义reactor的sls vim /srv/reactor/test.sls clean_tmp: cmd.cmd.run: - tgt: '*' - arg: - rm -rf /tmp/* 3: 发送消息 salt-call event.fire_master '' 'test' 这个时候就能够看到 上面的哪一个reactor是执行了的,也就是说全部节点的tmp目录都是空的了 这里咱们注意到,第三步中执行的命令第一个参数是空的;这2个参数分布是一个data和tag;这个data能够在sls中作处理,tag就是用来触发sls的哪一个标志,和master中定义的哪一个须要同样 好比这个命令: salt-call event.fire_master '{"overstate": "refresh"}' 'foo' 首先:foo表明了触发那个tag,而后执行相应的sls;而后在你的sls中能够引用这个data,上面的哪一个overstate,在sls中引用的时候就须要这样:data['data']['overstate']; 这个功能就提供了无限的可能性啊,好比一个服务器出现某种问题的时候让另外一个服务器作某种操做等,反正我认识这事一个很是NB,实在的功能
1:saltclient管理salt 只有master才能够 salt所有用python,这里也用python 文档:http://docs.saltstack.com/ref/python-api.html 示例: import salt.client client = salt.client.LocalClient() ret = client.cmd('*', 'cmd.run', ['ls -l']) print ret 2:salt api salt api我如今还没用,不过我也没搞定,若是你搞定了,我会很是感谢你能分享下的。
1:salt中文wiki:http://wiki.saltstack.cn/ 很不错的文章:http://wiki.saltstack.cn/reproduction/dive-into-saltstack 2:salt官网http://saltstack.com/ 官网文档:http://docs.saltstack.com/