Puppet:声明式配置管理工具
puppet package { 'nginx': ensure => installed, }
service { 'nginx': ensure => running, enable => true, require => Package['nginx'], }
上面的代码声明了一个 `nginx` 包必须被安装,并且 `nginx` 服务必须处于运行状态且开机自启,同时服务资源依赖于包资源。
### 清单(Manifest)
清单是包含 Puppet 代码的文件,扩展名为 `.pp`。清单文件中可以放置类定义、资源声明、变量、条件判断等。一个典型的项目入口清单文件是 `site.pp`,它通常用于定义节点配置。
### 类(Class)与定义(Definition)
类是一组相关资源的集合,可以重复使用。定义则是一种可以接受参数并创建多个命名实例的代码块。例如:
```puppet
class nginx {
package { 'nginx': ensure => installed }
service { 'nginx':
ensure => running,
enable => true,
require => Package['nginx'],
}
}
define vhost ($docroot) {
file { "/etc/nginx/sites-available/${title}":
content => template('nginx/vhost.conf.erb'),
}
}
模块(Module)
模块是 Puppet 代码的组织单元,通常包含类、定义、文件模板、相关数据等。每个模块有固定的目录结构,例如:
nginx/
├── manifests/
│ └── init.pp
├── templates/
│ └── vhost.conf.erb
├── files/
└── metadata.json
Puppet 社区提供了大量预置模块(通过 Puppet Forge),可以直接安装使用。
节点分类(Node Classification)
节点的定义告诉 Puppet Master 应该把哪些配置(类、参数)分配给哪台机器。可以在 site.pp 中使用 node 块来定义:
node 'web01.example.com' {
include nginx
class { 'ntp': servers => ['pool.ntp.org'] }
}
更灵活的方式是通过外部节点分类器(ENC)或 Hiera 进行动态分配。
环境搭建:安装 Puppet
在生产环境中,需要至少两台机器:一台 Puppet Master 和一台或多台 Agent 节点。下面以 CentOS 7 / Rocky Linux 为例,演示快速安装过程。
安装 Puppet Master(服务器端)
-
添加 Puppet 官方仓库:
rpm -Uvh https://yum.puppet.com/puppet7-release-el-7.noarch.rpm -
安装 Puppet Server 软件包:
yum install -y puppetserver -
调整内存(可选):编辑
/etc/sysconfig/puppetserver,修改 JVM 堆内存大小以适应你的服务器。 -
启动并设置开机自启:
systemctl start puppetserver systemctl enable puppetserver -
防火墙配置(如果开启):
firewall-cmd --add-port=8140/tcp --permanent firewall-cmd --reload
安装 Puppet Agent(客户端)
在每台受管节点上执行:
-
添加仓库并安装 Puppet Agent:
rpm -Uvh https://yum.puppet.com/puppet7-release-el-7.noarch.rpm yum install -y puppet-agent -
配置 Master 地址:编辑
/etc/puppetlabs/puppet/puppet.conf,在[main]或[agent]段添加:[agent] server = puppet-master.example.com -
启动 Agent 服务并启用:
/opt/puppetlabs/bin/puppet resource service puppet ensure=running enable=true
证书签名
Agent 第一次连接 Master 时会发起证书签名请求,需要在 Master 上审核:
- 查看待签名证书:
/opt/puppetlabs/bin/puppetserver ca list - 签名所有请求:
/opt/puppetlabs/bin/puppetserver ca sign --all
签名完成后,Agent 即可定期从 Master 获取并执行配置。
我的第一个 Puppet 清单
在 Master 上创建最简单的清单,让 Agent 安装并启动 NTP 服务。
-
创建模块目录(可以在主配置环境路径下):
mkdir -p /etc/puppetlabs/code/environments/production/modules/ntp_module/manifests -
编写类文件
init.pp:# /etc/puppetlabs/code/environments/production/modules/ntp_module/manifests/init.pp class ntp_module { package { 'ntp': ensure => installed, } service { 'ntpd': ensure => running, enable => true, require => Package['ntp'], } } -
在
site.pp中添加节点定义:# /etc/puppetlabs/code/environments/production/manifests/site.pp node default { include ntp_module }这里的
default会匹配所有未明确定义的节点。 -
在 Agent 上手动触发运行(测试):
/opt/puppetlabs/bin/puppet agent --test如果一切正常,你会在输出中看到 NTP 软件包安装和服务启动的过程。此后 Agent 将按默认间隔(30分钟)自动运行。
使用模块与 Puppet Forge
Puppet Forge 是官方模块仓库,包含数千个预置模块。使用社区模块可以大幅减少编写代码的工作量。
安装模块
在 Master 上使用 puppet module install 命令:
/opt/puppetlabs/bin/puppet module install puppetlabs-ntp
该命令会将模块安装到 /etc/puppetlabs/code/environments/production/modules 下。之后可以在清单中直接使用:
include ntp
大多数模块支持参数传递,便于自定义:
class { 'ntp':
servers => [ '0.pool.ntp.org', '1.pool.ntp.org' ],
}
管理模块依赖
模块目录中的 Puppetfile 可以描述所有依赖,并借助工具(如 r10k、Code Manager)实现自动化部署。一个简单的 Puppetfile 示例:
forge 'https://forge.puppet.com'
mod 'puppetlabs/ntp', '9.0.0'
mod 'puppetlabs/firewall', '2.8.0'
数据分离:Hiera
随着环境规模增长,直接在清单中硬编码配置值会变得难以维护。Puppet 通过 Hiera 将配置数据与代码分离。
Hiera 使用层次化的 YAML 文件存储键值对,根据节点特定的事实(如操作系统、数据中心位置、角色等)返回对应的值。例如:
hiera.yaml 层次结构:
---
version: 5
defaults:
datadir: data
data_hash: yaml_data
hierarchy:
- name: "Per-node data"
path: "nodes/%{trusted.certname}.yaml"
- name: "Common data"
path: "common.yaml"
数据文件示例:
data/common.yaml:
ntp::servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
在类中使用 Hiera 数据自动查找参数:
如果 ntp 类的参数名与 Hiera 键一致,Puppet 会自动注入值。否则可以通过 lookup() 函数显式获取:
$servers = lookup('ntp::servers')
Facter:系统信息收集
Puppet 内建了 Facter 工具,它会提取目标节点的系统信息(如 IP 地址、操作系统版本、内核等),并转变为变量供 Puppet 代码使用。这些信息被称为“事实(facts)”。你可以在清单或模板中直接使用,例如:
if $facts['os']['family'] == 'RedHat' {
$package_name = 'httpd'
} elsif $facts['os']['family'] == 'Debian' {
$package_name = 'apache2'
}
你也可以编写自定义事实(custom facts)来提取业务相关的节点属性,放置于模块的 facts.d 目录下。
节点管理最佳实践
使用 Roles 和 Profiles 模式
当基础设施变得复杂时,建议采用 Roles & Profiles 设计:
- Profile:一个小的功能组合,例如 “Web 服务器基础配置”、“MySQL 客户端”。
- Role:由多个 Profile 组成,定义一个完整的节点角色,例如 “Web 应用服务器”。
这样每个节点只需分配一个 Role 类,清晰的层级便于维护。
class profile::base {
include ntp
include ssh
}
class role::web_server {
include profile::base
include profile::apache
}
版本控制与 CI/CD
所有 Puppet 代码(清单、模块、Hiera 数据)都应纳入版本控制系统(如 Git)。通过集成 Puppet Code Manager(配合 Git 分支),可以实现环境的自动部署。每次代码提交后,自动运行 Puppet 语法检查与单元测试,然后推送到 Master。
环境隔离
利用 Puppet 的目录环境(Directory Environments),可以为开发、测试、生产创建独立的代码路径,避免未测试的变更影响生产节点。
故障排查与常用命令
- 在 Agent 上测试运行并查看详细输出:
/opt/puppetlabs/bin/puppet agent --test --verbose - 查看 Master 端详细日志:
tail -f /var/log/puppetlabs/puppetserver/puppetserver.log - 检查证书状态:
/opt/puppetlabs/bin/puppetserver ca list --all - 验证清单语法:
/opt/puppetlabs/bin/puppet parser validate <manifest.pp> - 在 Master 上模拟节点目录编译:
/opt/puppetlabs/bin/puppet master --compile <nodename>