Puppet配置管理实战:让1000台服务器听话的秘密武器
今天就来分享一下我这几个月使用Puppet管理多服务器配置的实战经验,包括一些踩过的坑和解决方案。
Puppet基础概念快速入门
在开始实战之前,先简单说说Puppet的核心概念,这些理解了后面的操作就很容易了。
Puppet采用的是Master-Agent架构,Master节点存储配置清单(manifest),Agent节点定期向Master请求配置并应用。整个过程是声明式的,你只需要描述想要的最终状态,Puppet会自动计算如何达到这个状态。
几个重要概念:
- Manifest:用Puppet DSL语言编写的配置文件,描述系统应该是什么样子
- Module:可复用的配置单元,包含manifest、文件、模板等
- Node:被管理的服务器节点
- Catalog:Master为每个节点编译生成的具体配置指令
环境搭建实战
我的测试环境是3台CentOS 7服务器,1台Master,2台Agent。生产环境类似,只是Agent数量更多。
Master节点安装配置
# 安装Puppet Server
rpm -Uvh https://yum.puppet.com/puppet-release-el-7.noarch.rpm
yum install -y puppetserver
# 修改内存配置,默认2G太大了
vim /etc/sysconfig/puppetserver
JAVA_ARGS="-Xms512m -Xmx512m"
# 启动服务
systemctl enable puppetserver
systemctl start puppetserver这里有个坑,Puppet Server默认内存配置是2G,小环境根本用不了这么多,而且会导致启动失败。我把它调到512M,测试环境够用了。
Agent节点配置
# 安装Puppet Agent
rpm -Uvh https://yum.puppet.com/puppet-release-el-7.noarch.rpm
yum install -y puppet-agent
# 配置Master地址
vim /etc/puppetlabs/puppet/puppet.conf
[main]
server = puppet-master.example.com
# 启动服务
systemctl enable puppet
systemctl start puppetAgent第一次连接Master时需要证书认证,在Master上执行:
/opt/puppetlabs/bin/puppetserver ca list
/opt/puppetlabs/bin/puppetserver ca sign --all编写第一个配置管理模块
我们从一个简单的nginx模块开始。在生产环境中,nginx的配置管理是个头疼的问题,不同环境的配置文件经常不一致。
创建nginx模块结构
cd /etc/puppetlabs/code/environments/production/modules
mkdir -p nginx/{manifests,files,templates,tests}编写主配置文件
# nginx/manifests/init.pp
class nginx {
package { 'nginx':
ensure => installed,
}
service { 'nginx':
ensure => running,
enable => true,
require => Package['nginx'],
}
file { '/etc/nginx/nginx.conf':
ensure => present,
source => 'puppet:///modules/nginx/nginx.conf',
owner => 'root',
group => 'root',
mode => '0644',
notify => Service['nginx'],
require => Package['nginx'],
}
}这个配置很简单,确保nginx包安装、服务运行、配置文件正确。notify参数很重要,当配置文件变化时会自动重启服务。
准备配置文件模板
# 将标准的nginx配置放到files目录
cp /etc/nginx/nginx.conf nginx/files/应用到节点
# site.pp
node 'web-server-01.example.com' {
include nginx
}
node 'web-server-02.example.com' {
include nginx
}这样两台web服务器就会自动安装和配置nginx了。每次Agent运行时(默认30分钟),都会检查配置是否符合要求,不符合就自动修复。
高级配置管理技巧
使用变量和条件判断
实际环境中,不同服务器的配置往往有差异。比如内存大小不同,nginx worker进程数就应该不同:
class nginx {
$worker_processes = $facts['processors']['count']
package { 'nginx':
ensure => installed,
}
file { '/etc/nginx/nginx.conf':
ensure => present,
content => template('nginx/nginx.conf.erb'),
owner => 'root',
group => 'root',
mode => '0644',
notify => Service['nginx'],
require => Package['nginx'],
}
service { 'nginx':
ensure => running,
enable => true,
require => [Package['nginx'], File['/etc/nginx/nginx.conf']],
}
}对应的ERB模板文件:
# nginx/templates/nginx.conf.erb
worker_processes <%= @worker_processes %>;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
<% if @facts['memorysize_mb'].to_i > 4096 %>
# 大内存服务器使用更多连接
worker_connections 2048;
<% end %>
}参数化模块
为了让模块更灵活,可以使用参数:
class nginx (
String $version = 'installed',
Integer $worker_processes = $facts['processors']['count'],
Boolean $enable_ssl = false,
) {
package { 'nginx':
ensure => $version,
}
if $enable_ssl {
package { 'nginx-mod-ssl':
ensure => installed,
}
}
# 其他配置...
}在site.pp中这样使用:
node 'web-server-01.example.com' {
class { 'nginx':
worker_processes => 8,
enable_ssl => true,
}
}使用Hiera进行数据分离
Hiera是Puppet的数据查找系统,可以把配置数据从代码中分离出来。这在管理多环境时特别有用。
# /etc/puppetlabs/code/environments/production/data/common.yaml
nginx::worker_processes: 4
nginx::enable_ssl: false
# /etc/puppetlabs/code/environments/production/data/nodes/web-server-01.yaml
nginx::worker_processes: 8
nginx::enable_ssl: true模块中使用lookup函数获取数据:
class nginx {
$worker_processes = lookup('nginx::worker_processes', Integer, 'first', $facts['processors']['count'])
$enable_ssl = lookup('nginx::enable_ssl', Boolean, 'first', false)
# 配置逻辑...
}管理复杂应用配置
单个服务的配置相对简单,但实际生产环境往往需要管理整个应用栈。我们来看一个更复杂的例子:LAMP环境的配置。
创建profile模块
# profiles/manifests/lamp.pp
class profiles::lamp {
include apache
include mysql
include php
# 确保安装顺序
Class['mysql'] -> Class['apache'] -> Class['php']
}Apache模块
class apache (
String $document_root = '/var/www/html',
Array[String] $modules = ['rewrite', 'ssl'],
) {
package { 'httpd':
ensure => installed,
}
service { 'httpd':
ensure => running,
enable => true,
}
file { '/etc/httpd/conf/httpd.conf':
ensure => present,
content => template('apache/httpd.conf.erb'),
notify => Service['httpd'],
require => Package['httpd'],
}
$modules.each |$module| {
exec { "enable-${module}-module":
command => "/usr/bin/a2enmod ${module}",
unless => "/usr/bin/apache2ctl -M | grep ${module}",
notify => Service['httpd'],
require => Package['httpd'],
}
}
}使用角色分离
在大型环境中,不同服务器承担不同角色。可以创建role模块:
# roles/manifests/webserver.pp
class roles::webserver {
include profiles::lamp
include profiles::monitoring
include profiles::backup
}
# roles/manifests/database.pp
class roles::database {
include profiles::mysql
include profiles::monitoring
include profiles::backup
}然后在site.pp中按角色分配:
node /^web-\d+\.example\.com$/ {
include roles::webserver
}
node /^db-\d+\.example\.com$/ {
include roles::database
}配置文件管理最佳实践
使用文件片段拼接
有时候配置文件需要从多个模块贡献内容,比如nginx的虚拟主机配置:
# 主配置
concat { '/etc/nginx/nginx.conf':
owner => 'root',
group => 'root',
mode => '0644',
notify => Service['nginx'],
}
concat::fragment { 'nginx-main':
target => '/etc/nginx/nginx.conf',
content => template('nginx/nginx-main.conf.erb'),
order => '01',
}
# 虚拟主机配置
define nginx::vhost (
String $document_root,
String $server_name = $title,
) {
concat::fragment { "nginx-vhost-${title}":
target => '/etc/nginx/nginx.conf',
content => template('nginx/vhost.conf.erb'),
order => '10',
}
}敏感数据处理
生产环境中经常需要处理密码等敏感信息。Puppet支持加密的eyaml:
# 安装hiera-eyaml
/opt/puppetlabs/puppet/bin/gem install hiera-eyaml创建加密的配置:
eyaml encrypt -s 'mysecretpassword'在Hiera中使用:
mysql::root_password: >
ENC[PKCS7,MIIBiQYJKoZIhvcNAQcDoIIBejCCAXYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAE...]大规模部署策略
管理几百台服务器时,需要考虑部署策略,避免同时更新所有服务器导致服务中断。
使用环境分离
# 创建不同环境
mkdir -p /etc/puppetlabs/code/environments/{development,staging,production}Agent可以指定环境:
# puppet.conf
[agent]
environment = staging分批次部署
可以使用Puppet的runinterval和splay参数控制Agent运行时间:
[agent]
runinterval = 1800 # 30分钟运行一次
splay = true # 随机延迟,避免同时运行也可以手动控制部署:
# 禁用自动运行
puppet agent --disable "maintenance window"
# 手动触发特定节点
mco puppet runonce -I web-server-01配置验证
部署前最好验证配置语法:
# 验证语法
puppet parser validate manifests/init.pp
# 模拟运行
puppet agent --test --noop监控和故障排除
生产环境中,监控Puppet运行状态很重要。我们可以从多个维度监控:
日志分析
Puppet的日志很详细,但需要重点关注几个方面:
# Agent日志
tail -f /var/log/puppetlabs/puppet/puppet.log
# Master日志
tail -f /var/log/puppetlabs/puppetserver/puppetserver.log关键指标包括:
- 配置编译时间
- 资源应用成功率
- 证书问题
- 依赖关系错误
使用PuppetDB
PuppetDB可以存储所有节点的状态信息,方便查询和监控:
# 安装PuppetDB
yum install -y puppetdb puppetdb-termini
# 配置Master连接PuppetDB
vim /etc/puppetlabs/puppet/puppetdb.conf
[main]
server_urls = https://puppetdb.example.com:8081查询节点状态:
# 查看失败的节点
curl -X GET http://puppetdb:8080/pdb/query/v4/reports \
--data-urlencode 'query=["=", "status", "failed"]'常见问题排查
我在使用过程中遇到过几个典型问题:
证书过期:Puppet证书默认5年有效期,过期后Agent无法连接Master。需要重新签发证书。
依赖关系循环:资源之间的依赖关系形成循环,导致配置无法应用。可以通过puppet agent --graph生成依赖图分析。
文件权限问题:特别是SELinux环境下,需要注意文件的安全上下文。
内存不足:Master编译大量配置时可能内存不足,需要调整JVM参数。
与其他工具集成
Puppet可以和很多运维工具集成,形成完整的自动化体系。
与Git集成
使用r10k或Code Manager可以实现Git驱动的部署:
# Puppetfile
mod 'puppetlabs-stdlib'
mod 'puppetlabs-concat'
mod 'nginx',
:git => 'https://github.com/company/puppet-nginx.git',
:branch => 'production'与监控系统集成
可以在Puppet配置中自动部署监控:
class profiles::monitoring {
package { 'zabbix-agent':
ensure => installed,
}
file { '/etc/zabbix/zabbix_agentd.conf':
ensure => present,
content => template('monitoring/zabbix_agentd.conf.erb'),
notify => Service['zabbix-agent'],
}
service { 'zabbix-agent':
ensure => running,
enable => true,
}
}性能优化经验
管理大量服务器时,性能优化很重要。我总结了几个优化点:
Master端优化
# /etc/puppetlabs/puppetserver/conf.d/puppetserver.conf
jruby-puppet: {
max-active-instances: 4
max-requests-per-instance: 100000
}Agent端优化
[agent]
usecacheonfailure = false
report = false
pluginsync = false对于只读节点,可以禁用一些不必要的功能。
网络优化
使用本地Package仓库可以大幅提升安装速度:
yumrepo { 'local-repo':
baseurl => 'http://repo.internal.com/centos/7/',
enabled => 1,
gpgcheck => 0,
}经过几个月的实践,我们的服务器配置管理效率提升了至少10倍,配置漂移问题基本消失。虽然初期学习成本比较高,但是长期收益非常明显。
特别是在云环境下,服务器经常弹性伸缩,Puppet的自动化配置管理能力显得更加重要。新服务器启动后几分钟就能自动完成所有配置,大大提升了运维效率。
当然Puppet也不是万能的,对于一些复杂的业务逻辑,还是需要结合其他工具。但作为基础设施配置管理,Puppet确实是个不错的选择。
如果你也在管理大量服务器,强烈建议试试Puppet。虽然学习曲线比较陡峭,但掌握后真的会让你的运维工作轻松很多。记住,好的工具能让运维工作事半功倍,而不是增加复杂度。
希望这篇文章对正在做配置管理的朋友有所帮助。如果你在使用Puppet过程中遇到问题,欢迎留言讨论。觉得有用的话,别忘了点赞转发哦~
关注@运维躬行录,获取更多实战干货!
公众号:耕云躬行录
个人博客:躬行笔记