标签:数据中心 客户端软件 配置文件 管理工具 管理系统 puppet
使用puppet实现自动化运维
服务概述:
1、什么是puppet
puppet是一个为实现数据中心自动化管理而设计的配置管理软件。是一种Linux、Unix平台的集中配置管理系统,使用ruby语言,可管理配置文件、用户、cron任务、软件包、系统服务等。puppet把这些系统实体称之为资源,puppet的设计目标是简化对这些资源的管理以及妥善处理资源间的依赖关系。
2、Puppet的工作模式
Puppet是一个C/S架构的配置管理工具,在中央服务器上安装puppet-server软件包(被称作Puppetmaster)。在需要管理的目标主机上安装puppet客户端软件(被称作PuppetClient)。当客户端连接上Puppetmaster后,定义在Puppetmaster上的配置文件会被编译,然后在客户端上运行。每个客户端默认每半个小时和服务器进行一次通信,确认配置信息的更新情况。如果有新的配置信息或者配置信息已经改变,配置将会被重新编译并发布到各客户端执行。也可以在服务器上主动触发一个配置信息的更新,强制各客户端进行配置。如果客户端的配置信息被改变了,它可以从服务器获得原始配置进行校正。puppet的服务器端保存着所有的对客户端服务器的配置代码,在puppet里面叫做manifest(清单). manifest(清单)存放在puppetmaster 服务端。 puppet客户端下载manifest之后,可以根据manifest对服务器进行配置,例如软件包管理,用户管理和文件管理等等。
端口: 8140
3、运行原理
1)客户端puppetd调用facter,facter会探测出这台主机的一些变量如主机名、内存大小、IP地址等。然后puppetd把这些信息发送到服务器端。
2)服务器端的puppetmaster检测到客户端的主机名,然后会到manifest里面对应的node配置,然后对这段内容进行解析,facter送过来的信息可以作为变量进行处理的,node牵涉到的代码才解析,其它的代码不解析,解析分几个过程:语法检查、然后会生成一个中间的伪代码,然后再把伪代码发给客户机。
3)客户端接收到伪代码之后就会执行,客户端再把执行结果发送给服务器。
4-服务器再把客户端的执行结果写入日志。
4、注意:
1)为了保证安全: 安装openssl ,openssl-devel, client和server 通信基于ssl和证书通信。 只有经过puppetmaster server认证的puppet client 才可以puppetmaster server通信。 CA证书。
2)默认30分钟, client会向服务器同步一次配置文件。
3)基于ruby脚本写的。 安装ruby开发环境。
对应的软件: | |
软件名 | 作用 |
facter-1.6.7.tar.gz | 探测服务器上一些信息 |
puppet-2.7.13.tar.gz | puppet这个软件包,包括了puppetmaster服务器软件和puppetd客户端。 |
一:实验目标
实战:配置Puppet服务器
实战:Puppet自动化运维5个实战案例
二:实验环境
facter-1.6.7.tar.gz
puppet-2.7.13.tar.gz
服务端:xuegod63 IP:192.168.1.63
客户端:xuegod64 IP:192.168.1.64
三:实验代码
搭建puppet服务器和puppet客户端的准备工作:
Puppet 要求所有机器有完整的域名(FQDN)。
配好: 主机名 保持两台服务器时间同步,只有时间同步了,CA认证才可以通过,同时要关闭iptables和selinux。
以下操作在xueogd63和xuegod64上都操作: Puppet 要求所有机器有完整的域名(FQDN)。
1、配置xuegod63和xuegod64环境
1)主机名同步
[root@xuegod63 ~]# cat /etc/hosts
192.168.1.63 xuegod63.cn
192.168.1.64 xuegod64.cn
[root@xuegod63 ~]# scp /etc/hosts 192.168.1.64:/etc/ #hosts配置文件复制到xuegod64
2)保持两台服务器时间同步
[root@xuegod63 ~]# cat /etc/ntp.conf
server 0.rhel.pool.ntp.org
server 1.rhel.pool.ntp.org
server 2.rhel.pool.ntp.org
[root@xuegod63 ~]# ntpdate 0.rhel.pool.ntp.org #
15 Dec 20:36:57 ntpdate[3652]: step time server 202.112.31.197 offset 31.527473 sec
[root@xuegod63 ~]# date
Mon Dec 15 20:37:14 CST 2014
[root@xuegod63 64 ~]# crontab -e
*/5 * * * * /usr/sbin/ntpdate 0.rhel.pool.ntp.org &
3)保持域名一致
[root@xuegod63 ~]# cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=xuegod63.cn
[root@xuegod64 ~]# cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=xuegod64.cn
2、xuegod63安装puppet服务端
上传软件包:
facter-1.6.7.tar.gz #探测服务器上一些信息
puppet-2.7.13.tar.gz # puppet包括,puppetmaster服务器软件和puppetd客户端软件包
1)安装ruby openssl openssl-devel:
[root@xuegod63 ~]# yum install openssl openssl-devel
[root@xuegod63 ~]# yum install ruby -y
注:xuegod63和xuegod64上都安装facter-1.6.7.tar.gz和puppet-2.7.13.tar.gz。区别那一台主机是服务端和客户端,在于每台机器上生成服务器脚本不一样。
2)安装:facter-1.6.7.tar.gz
[root@xuegod63 ~]# tar zxvf facter-1.6.7.tar.gz
[root@xuegod63 ~]# cd facter-1.6.7
[root@xuegod63 facter-1.6.7]# ruby install.rb
3)安装:puppet-2.7.13.tar.gz
[root@xuegod63 ~]# tar zxvf puppet-2.7.13.tar.gz
[root@xuegod63 ~]# cd puppet-2.7.13
[root@xuegod63 puppet-2.7.13]# ruby install.rb
4)xuegod63复制配置文件:
[root@xuegod63 puppet-2.7.13]# cp conf/redhat/fileserver.conf /etc/puppet/
[root@xuegod63 puppet-2.7.13]# cp conf/redhat/puppet.conf /etc/puppet/
[root@xuegod63 puppet-2.7.13]# mkdir /etc/puppet/manifests
[root@xuegod63 puppet-2.7.13]# cd /etc/puppet/
[root@xuegod63 puppet]# ls
auth.conf fileserver.conf manifests puppet.conf
参数说明:
// auth.conf --> puppet server对client访问的ACL配置文件
// fileserver.conf --> puppet server 作为文件服务器的ACL配置文件
// manifests --> Puppet脚本主文件目录,至少需要包含site.pp文件,site.pppuppet主文件(入口文件)。所有要在服务器上执行的操作都写在这种.pp结尾的文件中。
// puppet.conf --> Puppet服务器配置文件
5)设置开机启动脚本:
[root@xuegod63 puppet-2.7.13]# cp conf/redhat/server.init /etc/init.d/puppetmaster
[root@xuegod63 puppet-2.7.13]# chmod +x !$
chmod +x /etc/init.d/puppetmaster
[root@xuegod63 puppet-2.7.13]# chkconfig puppetmaster on
[root@xuegod63 puppet-2.7.13]# chkconfig --list puppetmaster
puppetmaster 0:off 1:off 2:on 3:on 4:on 5:on 6:off
6)生成puppet用户:
[root@xuegod63 puppet-2.7.13]# grep puppet /etc/passwd #前期查,是没有puppet这个用户
[root@xuegod63 puppet-2.7.13]# chmod +x /etc/init.d/puppetmaster
[root@xuegod63 puppet-2.7.13]# puppetmasterd --mkusers #生成一下用户
[root@xuegod63 puppet-2.7.13]# grep puppet /etc/passwd #查看用户
puppet:x:500:500::/home/puppet:/bin/bash
7)启动服务
[root@xuegod63 puppet-2.7.13]# /etc/init.d/puppetmaster start
Starting puppetmaster:
[root@xuegod63 puppet-2.7.13]# netstat -antup | grep 8140
tcp 0 0 0.0.0.0:8140 0.0.0.0:* LISTEN 4750/ruby
[root@xuegod63 puppet-2.7.13]# lsof -i :8140
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
puppetmas 4750 puppet 7u IPv4 28000 0t0 TCP *:8140 (LISTEN)
3、安装客户端: xuegod64.cn
1)安装ruby openssl openssl-devel:
[root@xuegod63 ~]# scp facter-1.6.7.tar.gz puppet-2.7.13.tar.gz 192.168.1.64:/root
[root@xuegod64 ~]# yum install openssl openssl-devel
[root@xuegod64 ~]# yum install ruby -y
2)安装:facter-1.6.7.tar.gz
[root@xuegod64 ~]# tar zxvf facter-1.6.7.tar.gz
[root@xuegod64 ~]# cd facter-1.6.7
[root@xuegod64 facter-1.6.7]# ruby install.rb
3)安装:puppet
[root@xuegod64 ~]# tar zxvf puppet-2.7.13.tar.gz
[root@xuegod64 ~]# cd puppet-2.7.13
[root@xuegod64 puppet-2.7.13]# ruby install.rb
4)复制配置文件:
[root@xuegod64 puppet-2.7.13]# cp conf/namespaceauth.conf /etc/puppet/
[root@xuegod64 puppet-2.7.13]# cp conf/redhat/puppet.conf /etc/puppet/
5)设置开机启动脚本:
[root@xuegod64 puppet-2.7.13]# cp conf/redhat/client.init /etc/init.d/puppet
[root@xuegod64 puppet-2.7.13]# chmod +x /etc/init.d/puppet
[root@xuegod64 puppet-2.7.13]# chkconfig puppet on
6)配置xuegod64 puppet配置文件:指定puppetmaster 主机名 和 客户端证书名
[root@xuegod64 puppet-2.7.13]# vim /etc/puppet/puppet.conf # 插入以下红色内容
[main]
# The Puppet log directory.
# The default value is ‘$vardir/log‘.
logdir = /var/log/puppet
# Where Puppet PID files are kept.
# The default value is ‘$vardir/run‘.
rundir = /var/run/puppet
# Where SSL certificates are kept.
# The default value is ‘$confdir/ssl‘.
ssldir = $vardir/ssl
[agent]
# The file in which puppetd stores a list of the classes
# associated with the retrieved configuratiion. Can be loaded in
# the separate ``puppet`` executable using the ``--loadclasses``
# option.
# The default value is ‘$confdir/classes.txt‘.
classfile = $vardir/classes.txt
server = xuegod63.cn
certname = xuegod64.cn
# Where puppetd caches the local configuration. An
# extension indicating the cache format is added automatically.
# The default value is ‘$confdir/localconfig‘.
localconfig = $vardir/localconfig
注:
server = xuegod63.cn #指定puppetmaster 主机名
certname = xuegod64.cn #客户端证书名
7)启动服务
[root@xuegod64 puppet-2.7.13]# puppetmasterd --mkusers #生成一下用户
[root@xuegod64 puppet-2.7.13]# /etc/init.d/puppet start
[root@xuegod64 puppet-2.7.13]# netstat -antup | grep 8140
tcp 0 0 0.0.0.0:8140 0.0.0.0:* LISTEN 2829/ruby
注:发现服务器和客户端都启动8140端口
[root@xuegod63 ~]# netstat -antup | grep 8140
tcp 0 0 0.0.0.0:8140 0.0.0.0:* LISTEN 4750/ruby
4、签名证书: 客户端xuegod64找xuegod63签名
1)Xuegod64 发送请求: 生成证书请求文件
[root@xuegod64 puppet-2.7.13]# puppetd --test --server xuegod63.cn
err: Could not retrieve catalog from remote server: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed. This is often because the time is out of sync on the server or client
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
err: Could not send report: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed. This is often because the time is out of sync on the server or client
出了错,解决方法: 一些文件不是证书签名的文件
[root@xuegod64 puppet-2.7.13]# rm -rf /var/lib/puppet/ssl/*
[root@xuegod64 puppet-2.7.13]# puppetd --test --server xuegod63.cn
[root@xuegod64 puppet-2.7.13]# echo $? #返回为1,没有问题。
1
2)xuegod63查看有哪些服务器证书请求文件
[root@xuegod63 puppet-2.7.13]# puppetca --list #查看哪些服务器申请了证书签名。
xuegod64.cn (DB:28:A7:03:C1:B5:55:4E:68:9E:07:0E:91:4D:7C:CB)
3)对请求文件进行签名
[root@xuegod63 puppet-2.7.13]# puppetca -s xuegod64.cn #只签名某个客户端。服务器端对 -a表示对所有的请求文件进行签名,xuegod64签名
notice: Signed certificate request for xuegod64.cn
notice: Removing file Puppet::SSL::CertificateRequest xuegod64.cn at ‘/var/lib/puppet/ssl/ca/requests/xuegod64.cn.pem‘
[root@xuegod63 puppet-2.7.13]# puppetca -s -a # 对所有客户端全部签名
No waiting certificate requests to sign
[root@xuegod63 puppet-2.7.13]# ls /var/lib/puppet/ssl/ca/requests/ #空的,没有任何文件
[root@xuegod63 puppet-2.7.13]# ls /var/lib/puppet/ssl/ca/signed/
xuegod63.cn.pem xuegod63.pem xuegod64.cn.pem
4)查看证书签名, 前面有+号,表示已经签名成功
[root@xuegod63 puppet-2.7.13]# puppetca -a --list
+ xuegod63.cn (24:49:4F:DC:0B:55:CD:50:F9:A6:D0:F9:BA:56:A1:D6) (alt names: DNS:puppet, DNS:puppet.cn, DNS:xuegod63.cn)
+ xuegod64.cn (D1:2D:D4:95:38:46:F0:B4:A8:7E:58:5D:ED:89:35:84)
服务器签名过的证书存放位置
[root@xuegod63 puppet-2.7.13]# ls /var/lib/puppet/ssl/ca/signed/* #服务器签名过的证书存放位置
/var/lib/puppet/ssl/ca/signed/xuegod63.cn.pem
/var/lib/puppet/ssl/ca/signed/xuegod64.cn.pem
5)xuegod64重启服务器,获得可用的新CA证书,并使用新的CA证书和服务器端通信:
[root@xuegod64 puppet-2.7.13]# ls /var/lib/puppet/ssl/certs/
ca.pem
[root@xuegod64 puppet-2.7.13]# /etc/init.d/puppet restart
[root@xuegod64 puppet-2.7.13]# ls /var/lib/puppet/ssl/certs/
ca.pem xuegod64.cn.pem
#可看到证书,说明客户端和服务器端正常通信了。 ============================================================
5、自动运维实例:
实战1,通过puppet远程在xuegod64的/tmp目录下自动创建一个文件test.txt,并写入内容:Welconme
方法一:
1)xuegod63服务端配置:
[root@xuegod63 puppet-2.7.13]# vim /etc/puppet/manifests/site.pp
[root@xuegod63 puppet-2.7.13]# cat /etc/puppet/manifests/site.pp
node default{
file { "/tmp/test.txt":
content=> "this is a test file";
}
}
[root@xuegod63 puppet-2.7.13]# /etc/init.d/puppetmaster restart
2)测试客户端能否自动创建文件
方法1 通过重启puppet客户端服务,来执行脚本
[root@xuegod64 puppet-2.7.13]# /etc/init.d/puppet restart
[root@xuegod64 puppet-2.7.13]# cat /tmp/test.txt
this is a test file
方法2:
1)同步临时生效
[root@xuegod64 puppet-2.7.13]# puppetd --test --server xuegod63.cn
info: Caching catalog for xuegod64.cn
info: Applying configuration version ‘1429357828‘
notice: Finished catalog run in 0.10 seconds
[root@xuegod64 puppet-2.7.13]# cat /tmp/test.txt
this is a test file
方法3:等30分钟后自己同步。
实例2: 文件分发。
要把server服务器上/opt目录下的a.txt(apache-4.1.12.rpm)发布至client服务器的/opt目录下,文件名不变。 注意:分发文件时,不要用/root ,会有权限问题。
1)xuegod63配置:
[root@xuegod63 ~]# cp /etc/hosts /opt/a.txt
[root@xuegod63 ~]# vim /etc/puppet/fileserver.conf #在文件最后,追加以下内容
[files]
path /opt/
allow 192.168.1.0/24
注: [files] #名字,可以随便写
2)指定客户端要执行的操作:
[root@xuegod63 ~]# vim /etc/puppet/manifests/site.pp
[root@xuegod63 ~]# cat /etc/puppet/manifests/site.pp #添加红色内容
node default{
file { "/tmp/test.txt":
content=> "this is a test file";
}
file { "/opt/a.txt":
source => "puppet://$puppetserver/files/a.txt",
#//xuegod63.cn//opt/a.txt
}
}
注:
file { "/opt/a.txt": #指分发到客户端的路径
source => "puppet://$puppetserver/files/a.txt", 中的files要和/etc/puppet/fileserver.conf中定义的名字一样。
注:修改site.pp 文件后,服务端不需要重新启动服务。
3)同步临时生效
[root@xuegod64 puppet-2.7.13]# puppetd --test --server xuegod63.cn
info: Caching catalog for xuegod64.cn
info: Applying configuration version ‘1418651351‘
notice: /Stage[main]//Node[default]/File[/opt/a.txt]/ensure: defined content as ‘{md5}e7d6d91a44650a85573b0cd47f2c1647‘
notice: Finished catalog run in 0.46 seconds
[root@xuegod64 puppet-2.7.13]# ls /opt/ #查看
a.txt
[root@xuegod64 puppet-2.7.13]# cat /opt/a.txt
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.63 xuegod63.cn
192.168.1.64 xuegod64.cn
实战3: 自动修改文件属性
1)xuegod63编写脚本配置
[root@xuegod64 ~]# ll /opt/a.txt
-rw-r--r-- 1 root root 210 10月 22 16:31 /opt/a.txt
[root@xuegod63 ~]# cat /etc/puppet/manifests/site.pp
node default{
file { "/tmp/test":
content=> "this is a test file";
}
file { "/opt/a.txt":
source => "puppet://$puppetserver/files/a.txt",
owner => "puppet",
group => "puppet",
mode => 777,
}
}
注:需要将上一个实验的代码删掉
2)同步临时生效测试:
[root@xuegod64 puppet-2.7.13]# puppetd --test --server xuegod63.cn
info: Caching catalog for xuegod64.cn
info: Applying configuration version ‘1418651544‘
notice: /Stage[main]//Node[default]/File[/opt/a.txt]/owner: owner changed ‘root‘ to ‘puppet‘
notice: /Stage[main]//Node[default]/File[/opt/a.txt]/group: group changed ‘root‘ to ‘puppet‘
notice: /Stage[main]//Node[default]/File[/opt/a.txt]/mode: mode changed ‘0644‘ to ‘0777‘
notice: Finished catalog run in 0.30 seconds
[root@xuegod64 puppet-2.7.13]# ll /opt/a.txt
-rwxrwxrwx 1 puppet puppet 213 Dec 15 21:49 /opt/a.txt
例4: server端让client端自动执行shell脚本或命令
通过puppet分发执行shell脚本,然后在客户端的/opt目录下执行test.sh脚本,该脚本执行后,会在/tmp目录创建一个testfile文件。
1)编辑测试脚本
[root@xuegod63 ~]# vim /opt/test.sh
#!/bin/bash
/bin/touch /tmp/testfile
2)编辑脚本
[root@xuegod63 opt]#vim /etc/puppet/manifests/site.pp #写入以下红色标记内容
node default{
file { "/tmp/test":
content=> "this is a test file";
}
file { "/opt/a.txt":
source => "puppet://$puppetserver/files/a.txt",
owner => "puppet",
group => "puppet",
mode => 777,
}
file { "/opt/test.sh":
source => "puppet://$puppetserver/files/test.sh",
owner => "puppet",
group => "puppet",
mode => 755,
}
exec { "exec-mkdir":
cwd => "/opt",
command => "sh /opt/test.sh",
user => "puppet",
path => "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin",
}
}
注: 不用重启服务器的
3)同步测试:
[root@xuegod64 puppet-2.7.13]#puppetd --test --server xuegod63.cn
info: Caching catalog for xuegod64.cn
info: Applying configuration version ‘1418651975‘
notice: /Stage[main]//Node[default]/File[/opt/test.sh]/ensure: defined content as ‘{md5}d68e2194d349dcc3f1990a0ce37dcf1a‘
notice: /Stage[main]//Node[default]/Exec[exec-mkdir]/returns: executed successfully
notice: Finished catalog run in 1.85 seconds
[root@xuegod64 puppet-2.7.13]# ls /tmp/testfile
/tmp/testfile
[root@xuegod64 puppet-2.7.13]# ll /opt/
total 8
-rwxrwxrwx 1 puppet puppet 213 Dec 15 21:49 a.txt
-rwxr-xr-x 1 puppet puppet 37 Dec 15 21:59 test.sh
例5:客户端自动执行服务的启动及关闭:
可以通过puppet对一些服务进行重启,状态等操作。puppet是通过service命令操作的。所以,只能针对在/etc/init.d/目录下的服务 实例:把客户端xuegod64的vsftpd服务关闭,并把nfs服务启动
1)准备环境:
[root@xuegod64 ~]# rpm -ivh /mnt/Packages/vsftpd-2.2.2-6.el6_0.1.x86_64.rpm
[root@xuegod64 ~]# service vsftpd start #为了实现远程关闭服务,所以这里先开着
[root@xuegod64 ~]#service nfs stop
[root@xuegod64 ~]# service vsftpd status
[root@xuegod64 ~]#service nfs status
2)配图manifests菜单,配置客户端如何执行:
[root@xuegod63 opt]# cat /etc/puppet/manifests/site.pp #添加红色标记内容
node default{
file { "/tmp/test":
content=> "this is a test file";
}
file { "/opt/a.txt":
source => "puppet://$puppetserver/files/a.txt",
owner => "puppet",
group => "puppet",
mode => 777,
}
file { "/opt/test.sh":
source => "puppet://$puppetserver/files/test.sh",
owner => "puppet",
group => "puppet",
mode => 755,
}
exec { "exec-mkdir":
cwd => "/opt",
command => "sh /opt/test.sh",
user => "puppet",
path => "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin",
}
service { vsftpd":
ensure => stopped;
"nfs":
ensure => running;
}
}
3)xuegod64 测试:
[root@xuegod64 ~]#puppetd --test --server xuegod63.cn
[root@xuegod64 ~]# service vsftpd status
vsftpd is stopped
[root@xuegod64 ~]# service nfs status
rpc.svcgssd is stopped
rpc.mountd (pid 8896) is running...
nfsd (pid 8893 8892 8891 8890 8889 8888 8887 8886) is running...
rpc.rquotad (pid 8880) is running...
实战6:修改同步时间
修改puppet 客户端默认连接puppetmaster的时间 默认puppet 客户端每隔30分钟连接到puppetmaster, 同步一次配置文件 现在修改为1分钟.同步一次。
1)修改配置文件
[root@xuegod64 ~]# cat /etc/puppet/puppet.conf #添加以下红色标记内容
[main]
# The Puppet log directory.
# The default value is ‘$vardir/log‘.
logdir = /var/log/puppet
# Where Puppet PID files are kept.
# The default value is ‘$vardir/run‘.
rundir = /var/run/puppet
# Where SSL certificates are kept.
# The default value is ‘$confdir/ssl‘.
ssldir = $vardir/ssl
[agent]
# The file in which puppetd stores a list of the classes
# associated with the retrieved configuratiion. Can be loaded in
# the separate ``puppet`` executable using the ``--loadclasses``
# option.
# The default value is ‘$confdir/classes.txt‘.
classfile = $vardir/classes.txt
server = xuegod63.cn
certname = xuegod64.cn
runinterval = 60 #同步时间间隔默认为妙
# Where puppetd caches the local configuration. An
[root@xuegod64 ~]# /etc/init.d/puppet restart
[root@xuegod64 ~]# rm -rf /opt/*
[root@xuegod64 ~]# ls /opt/
2)测试:等待1分钟后再查看。
[root@xuegod64 ~]# ls /opt/ #发现执行了site.pp中内容
a.txt test.sh
本文出自 “末班车” 博客,请务必保留此出处http://blxueyuan.blog.51cto.com/9673381/1924072
标签:数据中心 客户端软件 配置文件 管理工具 管理系统 puppet
原文地址:http://blxueyuan.blog.51cto.com/9673381/1924072