参考:
https://puppet.com/docs/puppet/5.3/index.html (语法参考官网)
https://www.gitbook.com/download/pdf/book/kisspuppet/puppet(实例推荐参考这个)
《puppet实战》刘宇著 (原理参考这本书,版本比较旧)
简介:
作为一名苦逼的运维工程师,我们会遇到类似这种情况:有某款xxx软件需要我们批量部署在不同系统的平台上,这就要求我们懂得对每个平台的xxx软件的部署,类似的结果却要求不同的操作,足以让人郁闷。 要是能够描述下需求,每台自动部署就好了。而puppet就是为了满足这种需求的一款软件
puppet本质其实就是对catalog的配置进行编译和应用。
那么什么是catalog呢?
我们前面说过,我们希望可以描述下需求,然后节点自动进行部署,catalog就是我们描述需求的文档,我们的对象是主机,所以可以想象catalog里面其实是对主机各种状态的描述,而puppet负责解读这个文件,并把主机配置为catalog描述的状态。
至于为什么需要编译过程,其实也很好理解,类似于低级语言和高级语言的关系,低级语言高效,但是不好理解,于是封装各种功能,弄成高级语言。高级语言无法被底层识别,所以最终还是要转化为低级语言执行,高级语言-->低级语言的过程就是编译。catalog前面还有一个更为高级的描述语言,在puppet中是在一堆.pp结尾的文件进行描述,编译的过程在puppet中的体现就是(.pp文件的内容 转化为catalog的过程)但是catalog本身最终也还是要转化为机器能执行的低级语言(即二进制代码)。
明白了这点后,就比较容易理解puppet的两种架构:
agent/master架构:
所谓的agent/master,其实就是弄一台主机专门负责配置和编译.pp结尾文件生成catalog的,并把编译好的catalog分发给对应的主机执行。这种架构的优点显而易见,集中管理编译分发,各个节点不需要浪费资源在编译上,所以执行效率高,管理方便。缺点是master容易成为整个架构的瓶颈,所以一般会结合负载均衡和高可用这类软件进行更复杂的架构。
stand-alone架构:
这种架构其实就是把编译的过程放到了各个节点上,优点是一个节点挂不会影响到其他节点,缺点就是浪费大量资源在编译上,效率低下,不便于管理,因为缺点比优点多,所以一般建议使用第一种架构。这篇文档也基于agent/master架构。
1.安装
master:
sudo rpm -Uvh https://yum.puppet.com/puppet5/puppet5-release-el-6.noarch.rpm (配置puppet yum源)
yum install puppetserver -y
agent:
sudo rpm -Uvh https://yum.puppet.com/puppet5/puppet5-release-el-6.noarch.rpm #centos 6系列
(sudo rpm -Uvh https://yum.puppet.com/puppet5/puppet5-release-el-7.noarch.rpm)#centos 7系列
yum install puppet-agent -y
(puppetserver 依赖于puppet-agent,所以装puppetserver也会自动装上puppet-agent)
puppet 5.3的版本目录对比之前的版本位置有了些变化,几个核心的目录如下:(linux下的目录,其他系统参考官网)
/etc/puppetlabs/code:存放puppet代码和数据的目录,我们大部分的操作(对节点进行描述)就在这个目录
/etc/puppetlabs/puppet: puppet的配置路径,(设置puppet的工作环境,这也是核心的功能)
/etc/puppetlabs/puppetserver: puppetserver 的配置目录(puppetserver可以简单看成是对puppet进行任务分配的工具)
/etc/puppetlabs/mcollective: mcollective是一个运行框架,方便puppet的管理
现在,再来看看maste/agent架构下的几个问题:
1.master如何知道节点的基本信息?
你可能会说,这些当然是自己写到puppet的配置文件上去的。没错,有些信息是自己写的,但是有些信息手动写不仅繁琐而且没必要,比如节点的系统版本,内存大小,时区等等信息,事实上,puppet的客户端利用一个叫facter的软件收集了这些信息并传递给puppet master。
2.如果有多节点,master如何知道该把写好的配置分配给哪些节点?
一种方法是master把写好的配置群发,让客户端进行判断,另一种方法是master先判断该发给谁,并只发送该节点对应的配置。 puppet采用第二种方法,它是根据主机名进行节点分类,然后发送相关配置。
3.master根据主机名进行分配配置,那么如果有人冒充客户端的主机名,master不就可能把一些重要的配置发送出去了?而且客户端收到配置的时候,如何知道这是靠谱的master发来的,而不是别的主机恶意行为?
这里就用到了非对称密钥的原理,事实上,master和agent在开始建立链接前有个认证过程,为了高效地管理,master自建了个CA(5.3的CA配置目录在/etc/puppetlabs/puppet/ssl/),然后对agent的主机进行签发证书认证,利用ssl加密传输数据,这样就保证了两台主机之间靠谱通信。
所以,master/agent架构下,puppet的工作流程大概是这样的:
<1>puppet 客户端和服务端通过证书原理建立安全连接
<2>agent将facts信息发送给master
<3>master利用facts信息和自身的配置进行编译生成catalog,并发送给agent
<4>agent对catalog进行代码验证(语法检查等)并执行,将执行结果写入日志
<5>agent 最终达到最开始所定义的状态,并且将结果及任何执行数据通过开放api的形式发送给master
了解了这些,就可以开始做实验了,这个文档只简单介绍构建一个安装包的过程
2.master和agent建立联系
master:
[root@cqhdtest httpd]# hostname cqhdtest.com #自己要修改自己的主机名
[root@cqhdtest httpd]# cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=cqhdtest.com
[root@cqhdtest httpd]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.124.127 cqhdtest.com
192.168.124.138 node1.com
192.168.124.221 vhos-ftp.com
192.168.124.111 centos7.com
#puppet 根据主机名来识别身份,这里做实验,简单用host绑定域名,效率高,如果架构大的话,建议自建个dns服务专门解析节点域名
vi /etc/sysconfig/puppetserver``
#JAVA_ARGS="-Xms2g -Xmx2g -Djruby.logger.class=com.puppetlabs.jruby_utils.jruby.Slf4jLogger"
JAVA_ARGS="-Xms512m -Xmx512m -Djruby.logger.class=com.puppetlabs.jruby_utils.jruby.Slf4jLogger"
#修改这个是因为我是虚拟机做的,puppetserver默认需要2G的内存才能启动,这里我改为512m,想做实验又发现一直提示内存不够的,修改这个即可
[root@cqhdtest ~]# cat /etc/puppetlabs/code/environments/production/manifests/site.pp
node 'default'{ #node是标记节点的资源,default代表默认,类似于httpd的默认主机
notify { "i am running on node $fqdn":} #notify在节点上打印{}里面的内容,这里的$fqdn就是节点上的facter传递给master的参数
}
#类似于c语言的main函数,puppetserver读取配置文件是从一个叫site.pp的文件开始的,从这个文件用include之类的指令加入其它文件,生成最终的catalog,这里,我们简单地用一个notify资源作为本实验的开头
/etc/init.d/puppetserver start
netstat -tnlp|grep 8140 #查看是否服务有起来,默认监听 8140
agent:
[root@centos7 ~]#hostname centos7.com
[root@centos7 ~]# cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=centos7.com
[root@centos7 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.124.127 cqhdtest.com
192.168.124.138 node1.com
192.168.124.221 vhos-ftp.com
192.168.124.111 centos7.com
#一样的,客户端需要知道主机在哪
[root@centos7 ~]# cat /etc/puppetlabs/puppet/puppet.conf
[main]
certname = centos7.com #填写客户端的主机名
server = cqhdtest.com #填写master的主机名
environment = production #这个是环境的版本,puppet可以支持多环境切换,比如测试环境测试成功后再转到生产环境
runinterval = 1h #这个是客户端主动向服务端读取更新配置时间,也可以在master端配置puppet kick主动推送
[root@centos7 ~]# puppet agent --test
Info: Creating a new SSL key for centos7.com
Info: Caching certificate for ca
Info: csr_attributes file loading from /etc/puppetlabs/puppet/csr_attributes.yaml
Info: Creating a new SSL certificate request for centos7.com
Info: Certificate Request fingerprint (SHA256): 49:B7:9D:E6:1F:DF:08:EF:68:0E:F0:67:87:02:31:96:BD:B0:C7:C2:60:E6:E4:6E:99:C6:C9:4F:7B:5C:50:2A
Info: Caching certificate for ca
Exiting; no certificate found and waitforcert is disabled
#这个时候puppet 会生成csr文件,像master请求签署,也就是相当于请求master的认可
master:
[root@cqhdtest httpd]# puppet cert list
"centos7.com" (SHA256) 49:B7:9D:E6:1F:DF:08:EF:68:0E:F0:67:87:02:31:96:BD:B0:C7:C2:60:E6:E4:6E:99:C6:C9:4F:7B:5C:50:2A
#接收到centos7的签署请求
[root@cqhdtest httpd]# puppet cert sign centos7.com
Signing Certificate Request for:
"centos7.com" (SHA256) 49:B7:9D:E6:1F:DF:08:EF:68:0E:F0:67:87:02:31:96:BD:B0:C7:C2:60:E6:E4:6E:99:C6:C9:4F:7B:5C:50:2A
Notice: Signed certificate request for centos7.com
Notice: Removing file Puppet::SSL::CertificateRequest centos7.com at '/etc/puppetlabs/puppet/ssl/ca/requests/centos7.com.pem'
#签署请求,想取消可以puppet cert clean centos7.com,此时客户端就必须重新生成证书再请求
[root@cqhdtest httpd]# tree /etc/puppetlabs/puppet/ssl/ca/
/etc/puppetlabs/puppet/ssl/ca/
├── ca_crl.pem
├── ca_crt.pem
├── ca_key.pem
├── ca_pub.pem
├── inventory.txt
├── private
├── requests
├── serial
└── signed
├── centos7.com.pem
├── cqhdtest.com.pem
├── node1.com.pem
└── vhos-ftp.com.pem
#这是puppet 5存放证书的目录,关于证书的问题,可以通过这个目录获取到一些有用的信息
agent:
[root@centos7 ~]# puppet agent --test
Info: Caching certificate for centos7.com
...
...
Info: Caching catalog for centos7.com
Info: Applying configuration version '1514273497'
Notice: i am running on node centos7.com
Notice: /Stage[main]/Main/Node[default]/Notify[i am running on node centos7.com]/message: defined 'message' as 'i am running on node centos7.com' #执行成功
Notice: Applied catalog in 0.08 seconds
3.puppet上构建一个简单的httpd安装模块
master:
[root@cqhdtest manifests]# cat site.pp
node 'centos7.com'{
include httpd #给centos7这个节点加载httpd模块
}
node 'default'{
notify { "i am running on node $fqdn":}
}
[root@cqhdtest manifests]# cd /etc/puppetlabs/code/environments/production/modules/
[root@cqhdtest modules]# mkdir httpd
#创建模块目录,这个目录名字必须和site.pp里面的include后面的参数一样,puppet根据这个名称加载模块里面的.pp文件
[root@cqhdtest modules]# cd httpd/
[root@cqhdtest httpd]# mkdir manifests templates files
#这三个目录都不是随意起名字的
manifests:存放的是.pp文件,当puppet加载模块的时候,先从这个路径下的init.pp文件加载
templates:存放模板文件,里面一般是利用facter传递过来的参数生成的配置文件的模板
files:存放一般的文件,一些写好的,各节点通用的文件可以放在这个目录
[root@cqhdtest httpd]# cd manifests/
[root@cqhdtest manifests]# cat init.pp
class httpd{
include httpd::install,httpd::config
}
#这个是第一个加载的.pp文件,对类的全局变量的初始化一般放在这里,这里我并没做更多的操作,只是定义了两个子类,用来对httpd的安装和配置
[root@cqhdtest manifests]# cat install.pp
class httpd::install{
yumrepo { "repo163":
descr =>"repo test",
baseurl => "http://mirrors.163.com/centos/6/os/x86_64/",
gpgcheck =>"0",
enabled =>"1";
}
package {
"httpd": #安装包的名字,不同系统对应不同名字,可以利用case $os.name 进行判断,这里简单实验,不做判断
ensure => installed, #状态
require => Yumrepo["repo163"]; #require指令会要求repo163这个yum源存在的时候才执行安装操作,指定依赖的时候就用这个
}
}
#这里的install.pp也不是随便取名的,它是根据init.pp里面的子类名 httpd::install 里的install+.pp命名的,puppet的找名字就是根据这种规律来的,同理,我们还需要建个config.pp
[root@cqhdtest manifests]# cat config.pp
class httpd::config{
file{ '/etc/httpd/conf.d/vhost.conf': #file指令可以对文件进行操作
ensure => present,
mode => '0644',
content=>template('httpd/vhost.conf.erb'), #这个代表file的内容根据模板来
require=>Class['httpd::install'], #这个代表要先装httpd才生成配置文件
}
}
#需要注意的是这里template的路径是比较诡异的,路径中的httpd代表的是httpd这个模块,vhost.conf.erb这个文件的真正路径却是在httpd模块的templates下,也就是
/etc/puppetlabs/code/environments/production/modules/httpd/templates/vhost.conf.erb
[root@cqhdtest manifests]# cat /etc/puppetlabs/code/environments/production/modules/httpd/templates/vhost.conf.erb
<VirtualHost *:80>
DocumentRoot /var/www/html
ServerName <%= @hostname %>.com
ErrorLog logs/localhost.com-error_log
CustomLog logs/localhost.com-access_log common
</VirtualHost>
#这里唯一需要注意的是hostname这个facter传递过来的参数需要用<%= @hostname %>引用(里面有个@,没有@是自定义的变量)
agent:
[root@centos7 ~]# rpm -qa|grep httpd
[root@centos7 ~]# puppet agent --test
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Caching catalog for centos7.com
Info: Applying configuration version '1514280511'
Notice: /Stage[main]/Httpd::Install/Yumrepo[repo163]/ensure: created
Info: Yumrepo[repo163](provider=inifile): changing mode of /etc/yum.repos.d/repo163.repo from 600 to 644
Notice: /Stage[main]/Httpd::Install/Package[httpd]/ensure: created
Notice: /Stage[main]/Httpd::Config/File[/etc/httpd/conf.d/vhost.conf]/ensure: defined content as '{md5}8ad25542b2a4bb9f6d6037d8f7d04a8e'
Notice: Applied catalog in 24.99 seconds
[root@centos7 ~]# rpm -qa|grep httpd
httpd-2.4.6-67.el7.centos.6.x86_64
httpd-tools-2.4.6-67.el7.centos.6.x86_64
[root@centos7 ~]# cat /etc/httpd/conf.d/vhost.conf
<VirtualHost *:80>
DocumentRoot /var/www/html
ServerName centos7.com
ErrorLog logs/localhost.com-error_log
CustomLog logs/localhost.com-access_log common
</VirtualHost>
测试成功,这里简化了很多步骤,想要详细的,推荐看https://www.gitbook.com/download/pdf/book/kisspuppet/puppet 基础篇7
debug:
- Error: /File[/opt/puppetlabs/puppet/cache/facts.d]: Failed to generate additional resources using 'eval_generate': SSL_connect returned=1 errno=0 state=unknown state: sslv3 alert certificate unknown
这个是客户端和服务端直接的认证没认证好,客户端已有证书却不能重新认证(原因待查明),解决方法:重新生成客户端的证书,服务端重新签署
假设:客户端的certname为a.com
服务端: puppet cert clean a.com
客户端: rm -rf /etc/puppetlabs/puppet/ssl (/etc/puppetlabs/puppet/ssl 为客户端存放证书的路径)
puppet agent --test
服务端: puppet cert sign a.com
2.Error: Could not request certificate: SSL_connect returned=1 errno=0 state=error:r /CN=Puppet CA: cqhdtest.com]
这个错误是客户端和服务端的时间没同步,分别ntpdate同步下时间即可
本文转自biao007h51CTO博客,原文链接: http://blog.51cto.com/linzb/2054934,如需转载请自行联系原作者