Puppet核心概念

本书的重点是讲解PuppetOpenstack项目,并假定读者对于Puppet有一定的了解,因此将不会包含对于Puppet基础知识的讲解。

然而,在Puppet中有一些非常重要的概念,对于这些核心概念的准确理解,将有助于读者快速掌握Puppet Modules的开发,因此,本节将花费一些篇幅来帮助读者深入理解这些核心概念。

0.Resource Type

在Linux中,一切皆文件(file)。而在Puppet中,一切皆资源(resource)。

比如,package对应着软件包资源类型(resource type)。

在服务器上安装vim软件包,相应地声明一个package资源:

  1. package {'vim':
  2. ensure => present
  3. }

在服务器上管理ntp服务,相应地声明一个service资源:

  1. service {'ntpd':
  2. ensure => running
  3. }

在Puppet中,常用的资源类型有以下8类:

  • file
  • package
  • service
  • modify
  • exec
  • cron
  • user
  • group

0.1 资源声明

资源声明(Resource declaration)则是一个表达式,用于描述资源的期望状态并将其添加到Catalog。

可以理解为类似于编程语言中的函数调用。

1.Class

与面向对象语言不同,类(Class)在Puppet中只是表示了一个代码块:通常将一些相关的功能组合到一起,并存储到module中,以便后期使用。

1.1 类的定义

定义一个Class的语法格式如下:

  • class关键字开头
  • 指定一个类的名称
  • 参数列表(可选)
  • 一对花括号
  • 至少含有一个资源声明的代码块

例如,以下是一个关于apache的Class:

  1. class apache (String $version = 'latest') {
  2. package {'httpd':
  3. ensure => $version, # Using the class parameter from above
  4. before => File['/etc/httpd.conf'],
  5. }
  6. file {'/etc/httpd.conf':
  7. ensure => file,
  8. owner => 'httpd',
  9. content => template('apache/httpd.conf.erb'), # Template from a module
  10. }
  11. service {'httpd':
  12. ensure => running,
  13. enable => true,
  14. subscribe => File['/etc/httpd.conf'],
  15. }
  16. }

1.2 Class文件的存放位置

Class定义文件应存放在modules的manifests目录下,Puppet将自动地加载该路径下的所有类。

1.3 类的声明

在Puppet manifest文件中声明一个Class时,则会将其添加到catalog文件。通常在节点定义文件中或者其他class文件中去声明一个Class。

在Puppet中,有两种方式来声明一个Class:

  • 类Include方式
  • 类Resource声明方式

1.3.1 Include方式

Include方式是指使用includerequirecontainhiera_include函数来声明Class,使用这种方式Class可以安全地被多次声明。

例如:

  1. class compute(){
  2. include ::nova
  3. include ::nova::api
  4. }
  5. node 'compute_node' {
  6. include compute
  7. # nova类被声明了2次
  8. include ::nova
  9. }

何谓安全地多次声明?

任何一个Class在一个指定节点的定义中,只能被声明一次,否则Puppet在运行时会抛出资源重复声明的错误。这也是初学者容易犯错的地方。

而通过类include的方式可以实现尽管Class被多次声明,但最终只向catalog添加一次的效果。

但使用这种方式,则Class中的参数传值只能通过Hiera进行。

1.3.2 Class方式

Class的方式则要求每个被声明的Class只被声明一次。通过这种方式,在声明某个特定Class的时候,可以对指定参数进行重新赋值。

例如:

  1. class compute($ip='127.0.0.1'){
  2. class {'nova':
  3. ipaddress => $ip
  4. }
  5. class {'nova::api':}
  6. }
  7. node 'compute_node' {
  8. class{'compute':
  9. ip => '192.168.1.1'
  10. }
  11. }

2.Defines

Defines也称为是Defined resource type,是一段可以被多次赋值的代码块,可以理解为是一种轻量级的自定义的资源类型。

例如,以下是nova::manage:network define,用于管理nova network的创建。在实际使用中,可以通过传递不同的参数给nova::manage::network来创建不同的nova network。

  1. define nova::manage::network (
  2. $network,
  3. $label = 'novanetwork',
  4. $num_networks = 1,
  5. $network_size = 255,
  6. $vlan_start = undef,
  7. $project = undef,
  8. $allowed_start = undef,
  9. $allowed_end = undef,
  10. $dns1 = undef,
  11. $dns2 = undef
  12. ) {
  13. include ::nova::deps
  14. nova_network { $name:
  15. ensure => present,
  16. network => $network,
  17. label => $label,
  18. num_networks => $num_networks,
  19. network_size => $network_size,
  20. project => $project,
  21. vlan_start => $vlan_start,
  22. allowed_start => $allowed_start,
  23. allowed_end => $allowed_end,
  24. dns1 => $dns1,
  25. dns2 => $dns2,
  26. }
  27. }

初学者在选择如何define和class时,常常犹豫不决。

首先,来看这两种类型的最大区别:

  • Define:在一个catalog中可以被重复声明
  • Class: 在一个catatlog中只能被声明一次

再谈使用场景:

  • Class通常用于管理具有唯一性的资源
  • Define通常用于管理具有多样性的资源

    以Apache为例,会使用Class来管理Apache软件包,主配置文件,以及服务状态的管理;而Apache vhost则会使用Define来管理。我们会在后面puppet-apache章节中详细讲解。

3. Nodes

假设你已经下载了puppet-apache和puppet-mysql模块,接下来要为指定服务器赋予指定的角色,那么这个过程称为是节点分类(Node Classification)。
在Puppet中,这些数据通常存储在节点定义文件中。

节点定义文件的存放路径通常位于<ENVIRONMENTS DIRECTORY>/<ENVIRONMENT>/manifests/site.pp

现在我们要配置2种类型的节点:Web服务器www.example.com和DB服务器db1.example.com,在site.pp中加入以下代码:

  1. node 'www.example.com' {
  2. include apache
  3. }
  4. node 'db.example.com' {
  5. include mysql
  6. }

最佳实践

尽管在节点定义文件里可以添加任何的Puppet代码,但请保持只在节点定义文件中做两件事情:声明类和设置变量。