一、节点管理

1、什么是节点

   我们将Puppet的每个客户端都称为节点( node) 。 每个节点件定义主机名时可以是个、 组 ( 正则或继承) 。 所有的节点都需要在站点件( site.pp) 中进定义, 采import的式进引。 Puppet在进认证时都是以主机名( hostname) 进。 因此每台服务器在上线使时都需要规范主机名。 节点的配置有多种, 以下为采个或组主机名定义个节点的法。 

1) 以主机名命名节点配置件。 此节点配置只包含该主机, 配置件只定义该主机需要应的类 及变量。 代码如下: 

$ vim /etc/puppet/manifests/nodes/test.domain.com.pp
node 'test.domain.com' { #节点名, 即主机名
include nginx #加载ningx模块
$vhost = 'linuxtone.org' #定义虚拟主机变量vhost
}

同时需要在站点件( site.pp) 中进如下定义:

$ vim /etc/puppet/manifests/site.pp
import "nodes/test.domain.com.pp"

2) 定义组功能相似的主机名配置件。 例如有3台主机, 它们的配置都完全相同, 只是主机名 不同, 我们就可以通过代码清单8-1进指定。 

定义组主机名配置件 :

$ vim /etc/puppet/manifests/nodes/testgroups.pp
node 'test.domain.com' {
include nginx
$vhost ='linuxtone.org'
}
node 'test1.domain.com' {
include nginx
$vhost = 'linuxtone.org'
} 
node 'test2.domain.com' {
include nginx
$vhost = 'linuxtone.org'
}

在Puppet 0.25.0及以后的版本中, 也可以使正则表达式来指定这些节点:

node /^test\d+\.domain\.com$/{
include nginx
$vhost = 'linuxtone.org'
}

同时需要在站点件( site.pp) 中进如下定义:

如果nodes录下存在多个节点配置件时, 可以在站点件( site.pp) 中import所有节点件, 然 后采通配符匹配, 具体如下: 

$ vim /etc/puppet/manifests/site.pp
import "nodes/*.pp"

如果存在多个录, 只需要将节点件存放在import的不同录即可, 具体如下:

$ vim /etc/puppet/manifests/site.pp
import "nodes/cnc/*.pp"
import "nodes/ctc/*.pp"

同理, Puppet也持多级录正则, 以上cnc、 ctc录可以采“*”代替, 具体如下:

$ vim /etc/puppet/manifests/site.pp
import "nodes/*/*.pp"

2、主机名命名规范

Puppet限制主机名可以包含字母、 数字、 句点、 下划线、 破折号, 并且符合以下正则表达式:

/\A[a-z0-9._-]+\Z/

通常我们在对主机名命名时不会以“.”和“-”开头, 因此主机名正则表达式只允许在主机名中出现以 上字符。 在第5章时笔者就已经建议主机名命名遵循以下规范: 

role-isp-idc-ip.centos.domain.com

#名-运营商-机房名-机器IP.管理域名.com

例如:

web-cnc-bj-174.129.158.192.centos.linuxtone.org

   在规范好主机名后, 就可以根据服务器的部署进合理的归档管理。 例如要在全国10个IDC、 跨3个运营商上线100台服务器, 这些服务器拥有相同的, 因此可以按照规范进匹配命名。 在采节点组管理主机时可以利这特性的正则表达式进匹配, 从减少量节点管理件的编写作。 这对于维护节点管理件提供了极的便。 利这特性我们也可以充分利节点继承来处理组相同的主机。 

规范主机名的好处有如下个:

  • 管理便: 机器上线时通过MAC获取主机名。 

  • DNS管理便: 通过开源DNS管理主机名。 

  • 维护便: 主机的所有信息了然。

3、 节点继承

  • 节点继承关系 

   如前面模拟的场景: 上线的服务存在相同的络环境, 所有服务器都需要应同配置并定义同 变量, 类似于系统环境统初始化。 这种配置逻辑较简单, 可以采定义个basenode默认节点的法进配置, 其他主机节点采"inherits"继承basenode的配置信息, 具体如下: 

node basenode {
$my_puppet_server = "10.42.0.10"
$my_local_network = "10.42.0.0/24"
$my_syslog_server = "10.42.0.11"
$my_ntp_server = "10.42.0.12"
} 
node 'www.domain.com' inherits basenode {
include general
include httpd::php
}

以上代码中定义了basenode默认节点, 包含4个变量, 每个变量都赋予个值。 其中节 点"www.domain.com"采inherits继承的式继承basenode默认节点的所有属性, 4个变量将直接应 该节点内, 同时www.domain.com节点包含( include) 两个类: general和httpd: : php。 

  • 继承变量覆盖 

   如果另个节点ntp.domain.com。 所继承的变量$my_ntp_server的值与默认basenode定义的值不 同, 可以直接在节点内进重新声明, 这时节点内定义的值将覆盖basenode定义的原值, 具体如下: 

node 'ntp.domain.com' inherits basenode {
$my_ntp_server = "0.pool.ntp.org"
include general
}

通过上代码, 变量$my_ntp_server的值将由“10.42.0.12”变为"0.pool.ntp.org"。

  • 默认类与默认节点 

   定义默认节点配置与定义默认类baseclass的的相同: 为所有节点应相同全局变量并进系统环 境初始化。 定义默认类general, 并将所有节点需要引的类通过include式添加到默认类general中。 我们也称默认类general为公共类。 general类的定义如下: 

class general {
include yum
include hosts
include puppet
include iptables
include sysctl
include nrpe
include ntp
include syslog
}

   除了可以定义basenode, 我们还可以定义个default, 如果没有明确定义个节点, 将默认按 default进操作。 default的定义存在Puppet每次都会编译Catalog的问题, 也就是说不管所定义的default 有没有在使, Puppet都会将它编译到Catalog, 如果default没有使就会导致Puppet性能下降。 如果没 有特殊需求, 笔者建议采basenode或baseclass( general) 公共类的法实现。 

定义个default节点, 包含两个变量, 并加载个类, 具体代码如下:

node default {
$my_puppet_server = "10.42.0.10"
$my_local_network = "10.42.0.0/24"
include ntp
}
  • 节点继承的判断 

   如果有了相同功能的各个节点, 却又想给这些节点添加不同的, 可以将相同部分的配置定义到 basenode, 节点都继承basenode的信息, 然后分别增加不同功能的类引。 这的概念并不在Puppet中体现, 是抽象成种汇总的形式来表现。 定义节点www.domain.com与节点lb.domain.com继承同个节点basenode, 并包含( include) 不同的模块, 具体如下: 

node basenode {
$my_puppet_server = "10.42.0.10"
$my_ntp_server = "10.42.0.12"
} 
node 'www.domain.com' inherits basenode {
include role_webserver
} 
node 'lb.domain.com' inherits basenode {
include role_loadbalancer
}

   通过以上代码可以看到两个节点继承了basenode的信息, 并且没有做变量修改操作, 只是向www 添加了role_webserver类, 向lb添加了role_loadbalancer类。 在进类的配置时, 可以针对role_webserver和role_loadbalancer这两个抽象出来的进声明。

   主机www.domain.com抽象的是webserver即include nginx。 主机lb.domain.com抽象的是 loadbalancer即include lvs。 其中$my_role分别代表两个主机的抽象名。 具体实现代码如下: 

class role_webserver {
$my_role = "webserver"
include nginx
} 
class role_loadbalancer {
$my_role = "loadbalancer"
include lvs
}

   在件引时, 可以针对这些抽象出来的应不同的配置件, 例如webserver和loadbalancer 应的防墙配置件不同, 可以在iptables录创建iptables-webserver和iptables-loadbalancer两个件。 使source属性定义件来源时可采$my_role进判断。 具体实现如下: 

source => [ "puppet://$server/iptables/iptables-$hostname" , "puppet://$server/iptables/iptables-$my_role" , "puppet://$server/iptables/iptables" ],

或者在ERB模块件中进判断, 具体实现如下:

# Role specific settings
<% if my_role=="webserver" %>
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
<% end %>

4、节点管理法

   当节点越来越多时, 就需要采取定既有效又适合的节点管理法。 通过前的介绍我们了解 到Puppet节点管理持多种配置法。 Puppet节点管理的法可以是单主机、 正则、 继承等。 下将讲解每个节点管理的配置法及其优劣性。 

  • 每个主机名独 

   每个独的主机名可以是个节点配置件。 例如, 若主机名是test.domain.com, 那么节点配置 件可以是test.domain.com.pp。 在站点管理( site.pp) 中采通配符匹配录下的所有节点件, 不考虑 节点的、 加载的类等其他相关信息。 配置法如下: 

$ vim /etc/puppet/manifests/nodes/test.domain.com.pp
node 'test.domain.com' {
$vhost = 'linuxtone.org'
include nginx
} 
$vim /etc/puppet/manifests/nodes/test2.domain.com.pp
node 'test2.domain.com' {
$vhost = 'linuxtone.org'
include apache
} …

上述代码实现了: 所有节点配置件以主机名命名, 并存放在nodes录。

   对单录下的件数并没有明确的限制, 但是当个录下件数达到定数量级( 1000以 内, 通过"ls"命令查看录下的件时系统响应就会变得缓慢) 后会影响服务器性能, 何况涉及节点管理呢? 或通过程序来维护个录下的超过定规模的件也不是明智的选择。 笔者建议采级录的式来实现。 在节点的录下建需要管理的的级录, 具体如下: 

$ cd /etc/puppet/manifests/nodes
$ mkdir {web,db,lvs,cache,mq,custom}

   此法适于通过程序成节点管理件, 根据应的不同来固定所包含( include) 模块与 变量。 此法不适合编写节点管理件, 节点件过多时容易引发变更故障。 

  • 采正则匹配 

   代码清单8-1定义了组主机配置件, 通过观察可以发现所有主机都包含( include) 相同的模 块, 并定义了相同的变量。 这个时候我们可以通过正则表达式来减少代码。 代码清单8-1的主机组定义可以简写为: 

node /^test\d+\.domain\.com/ { #正则匹配多个主机名
include nginx #加载ningx模块
$vhost = 'linuxtone.org' #定义虚拟主机变量vhost
}

   此法适合系统管理员完全了解服务器所有的及定义, 并且不会发变化的情况。 缺点就 是当正则匹配内的服务器发改变时操作烦琐。 

   Puppet节点配置也持正则匹配的覆盖, 例如前正则匹配中所有test开头的主机。 如果test2想要单独加载不同的类, 可以将此主机单独声明, Puppet将单独声明节点覆盖之前的正则匹配, 实现代码如下: 

node 'test2.domain.com' {
include mysql
}
  • 使外部节点分类器 

   当Puppet运在个节点时, Master会根据节点名查找该节点都声明了哪些类。 将类映射到节点中 的最简单法就是在配置清单中声明。 例如, 定义个节点web.domain.com声明nginx类: 

node 'web.domain.com' {
include nginx
}

   除这种法外, 还可以ENC( External Node Classifiers, 外部节点分类器) 来完成这个任务。  个外部节点分类器是任何可执程序, 它可以接受个节点的名称, 并返回该节点的类列表。 例如, 这 可能是个简单的Shell脚本, 也可能是对个可以决定如何映射类到节点的更复杂的程序或API的封装。 

   外部分类器的主要途是使Puppet可以连接LDAP录服务。 许多型组织都有LDAP基础设施, 可以于设置Puppet, 使它可以从LDAP录服务中获取信息, 并且其他LDAP客户也可以通过Puppet获得由其管理的节点的信息。

ENC外部节点分类器也可以使Puppet DashBoard或Foreman通过Web界管理节点和类之间的关 系? 。 

接下来演如何使ENC创建节点。

1) 使ENC需要配置Puppet Master的主配置件puppet.conf, 增加如下参数:

[master]
external_nodes = /tmp/test_enc.py
node_terminus = exec

2) "/tmp/test_enc.py"为可执的脚本, Puppet在调它时传递节点的名称作为命令参数。 脚本 的内容如下: 

#!/usr/bin/env python
import sys
import yaml
node_name = sys.argv[1]
classes = ["basenode"]
# Output must be a YAML document
print(yaml.dump({
"classes": classes,
}))

注意 :如果没有yaml模块, 可以通过yum install PyYAML命令进安装。 

3) 为该脚本添加可执权限, 代码如下:

$ sudo chmod 755 /tmp/test_enc.py
$sudo chmod 755/tmp/test_enc.py

4) 在站点件( site.pp) 中配置basenode类信息, 代码如下:

$ sudo vim /etc/puppet/manifests/site.pp
class basenode {
notify {"I am a basenode!":}
}

5) 在客户端运Puppet, 代码如下:

# puppet agent --server puppet.domain.com --test
Info: Retrieving plugin
Info: Caching catalog for agent.domain.com
Info: Applying configuration version '1358346582'
Notice: I am a basenode!
Notice: /Stage[main]/Basenode/Notify[I am a basenode!]/message: defined 'message' as 'I am a basenode!'
Notice: Finished catalog run in 0.12 seconds

作原理: Puppet调在puppet.conf中由参数external_nodes指定的脚本, 并传递节点的名称作为 命令参数。 

要使ENC创建节点管理, 需要学习external_nodes脚本的写法。 笔者总结了个常的节点管理 配置与ENC配置的写法异同。 

( 1) 加载模块

加载模块的异同见下。

nodes.pp:
node default {
include puppet
include ntp
}
ENC:
classes:
puppet:
ntp:

( 2) 参数定义

参数定义的异同见下。

nodes.pp:
class { 'ntp':
ntpserver => ['0.pool.ntp.org','1.pool.ntp.org']
}
ENC:
classes:
ntp:
ntpserver:
- 0.pool.ntp.org
- 1.pool.ntp.org

( 3) 变量与数组

变量与数组的异同见下。

nodes.pp:
$var1 = 1
$var2 = "test"
$var3 = ["a", 1]
$var4 = { 'ma_ref1' => { 'cle1' => 'valeur1', 'cle2' => 'valeur2' }
}
ENC:
parameters:
var1: 1
var2: test
var3:
- a
- 1
var4:
ma_ref1:
cle1: valeur1
cle2: valeur2


二、应用举例

1、个节点间要相互解析地址

[root@www.example.com ~]# cat /etc/hosts
192.168.1.8 www.example.com
192.168.1.9 node1.example.com
192.168.1.10 node2.example.com
[root@node1.example.com ~]# cat /etc/hosts
192.168.1.8 www.example.com
192.168.1.9 node1.example.com
192.168.1.10 node2.example.com
[root@node2.example.com ~]# cat /etc/hosts
192.168.1.8 www.example.com
192.168.1.9 node1.example.com
192.168.1.10 node2.example.com

2、环境介绍

wKioL1YSjmfhJwXdAAEpbVj10vI672.jpg

3、服务端初始化

生成ssl证书:

[root@www.example.com ~]# puppet master --no-daemonize -d -v
[root@www.example.com ~]# ls /var/lib/puppet/ssl/
ca                    certs    private       public_keys
certificate_requests  crl.pem  private_keys

Master配置文件设置:

[root@www.example.com ~]# puppet master --genconfig >> /etc/puppet/puppet.conf

启动服务查看监听的端口:

[root@www.example.com ~]# service puppetmaster start
启动 puppetmaster:                                        [确定]
[root@www.example.com ~]# ss -tnlp |grep puppet
LISTEN     0      5                         *:8140                     *:*      users:(("puppetmasterd",3856,5))

4、agent端安装puppet

[root@node1.example.com ~]# yum install -y facter-1.7.6-1.el6.x86_64.rpm puppet-2.7.26-1.el6.noarch.rpm 
[root@node2.example.com ~]# yum install -y facter-1.7.6-1.el6.x86_64.rpm puppet-2.7.26-1.el6.noarch.rpm

5、配置agent端

在puppet配置文件添加master端地址:

[root@node1.example.com ~]# vim /etc/puppet/puppet.conf 
server = www.example.com
生成证书:
[root@node1.example.com ~]# puppet agent --server www.example.com -d -v --noop --test
info: Creating a new SSL key for node1.example.com
info: Caching certificate for ca
info: Creating a new SSL certificate request for node1.example.com
info: Certificate Request fingerprint (md5): 57:62:E0:23:B9:02:BC:29:27:B2:6B:CF:B5:30:3B:0E

Master端签署证书:

[root@www.example.com ~]# puppet cert list
  "node1.example.com" (57:62:E0:23:B9:02:BC:29:27:B2:6B:CF:B5:30:3B:0E)
[root@www.example.com ~]# puppet cert sign node1.example.com
notice: Signed certificate request for node1.example.com
notice: Removing file Puppet::SSL::CertificateRequest node1.example.com at '/var/lib/puppet/ssl/ca/requests/node1.example.com.pem'

Master端为node1主机添加模版:

[root@www.example.com ~]# vim /etc/puppet/manifests/node1.example.com.pp
node 'node1.example.com'{
        include nginx::web
}
[root@www.example.com ~]# vim /etc/puppet/manifests/site.pp
import "*.example.com.pp"
[root@www.example.com ~]# service puppetmaster reload

6、agent端测试

[root@node1.example.com ~]# puppet agent --server www.example.com -d -v --test
[root@node1.example.com ~]# rpm -q nginx
nginx-1.0.15-12.el6.x86_64
[root@node1.example.com ~]# service nginx status
nginx (pid  2412) 正在运行...

7、为agent端添加puppet服务

[root@node1.example.com ~]# service puppet start
启动 puppet:                                              [确定]
[root@node1.example.com ~]# chkconfig puppet on

8、按相同方法添加node2节点为agent

[root@www.example.com ~]# vim /etc/puppet/manifests/node2.example.com.pp
node 'node2.example.com' {
        include nginx::web
}
[root@node2.example.com ~]# vim /etc/puppet/puppet.conf 
server = www.example.com
[root@node2.example.com ~]# service puppet start
启动 puppet:                                              [确定]

Master端添加node2节点的证书:

[root@www.example.com ~]# puppet cert list
  "node2.example.com" (AD:5D:18:5F:6F:D6:24:36:5A:97:E4:21:57:5E:8B:10)
[root@www.example.com ~]# puppet cert sign node2.example.com
notice: Signed certificate request for node2.example.com
notice: Removing file Puppet::SSL::CertificateRequest node2.example.com at '/var/lib/puppet/ssl/ca/requests/node2.example.com.pem'

可以手动请求服务端:

[root@node2.example.com ~]#  puppet agent --server www.example.com -d -v --test

9、步骤总结

puppet master:

  • 安装puppet-master 

  • # puppet master --genconfig >> /etc/puppet/puppet.conf 

  • 启动puppetmaster服务 

puppet agent:

  • 安装puppet 

  • 编辑配置文件/etc/puppet/puppet.conf,在[agent]添加  server=puppetmaster.magedu.com 

  • 启动puppet服务 

master签署证书:

  • # puppet cert list 

  • # puppet cert sign NODE_NAME 

  • # puppet cert sign --all    //签署所有证书

注意:master端的任何修改,都要重新装载puppetmaster服务;