Puppet是一个配置自动化平台,可简化各种系统管理员任务。Puppet使用客户端/服务器模型,其中托管服务器(称为Puppet代理)与Puppet主服务器通信并下拉配置文件。
Puppet是用自己的自定义语言编写的,系统管理员可以访问它。位于Puppet主站上的模块描述了所需的系统。然后,Puppet软件将模块转换为代码,并且puppet agent
在代理节点上运行命令时根据需要更改代理服务器,或者按指定的时间间隔自动更改代理服务器。
Puppet可用于管理跨多种基础架构的多个服务器,从一组个人服务器到企业级操作。它旨在在Linux和其他类Unix操作系统上运行,但也已移植到Windows。但是,为了迎合本指南的目的,我们将使用Ubuntu 16.04 LTS作为主服务器,一个Ubuntu 16.04和一个CentOS 7作为两个代理节点。
注意 以
root
用户身份开始本指南。具有管理权限的受限用户将在后续步骤中配置。
您应该有三个可用的Linode,其中一个具有至少四个用于Puppet master的CPU核心。建议使用Linode 8GB计划。另外两个节点可以是任何计划大小,具体取决于您在安装和配置Puppet后打算如何使用它们。
按照入门指南进行操作,确保您的Linode配置为使用相同的时区。
注意为便于使用,请将Puppet主服务器的主机名设置为puppet
,并具有有效的完全限定域名(FQDN)。
要检查您的主机名,运行hostname
并检查您的FQDN,请运行hostname -f
。
将puppetlabs-release
存储库安装到Ubuntu 16.04并更新您的系统。此过程下载.deb
将为您配置存储库的文件:
wget https://apt.puppetlabs.com/puppetlabs-release-pc1-xenial.deb
dpkg -i puppetlabs-release-pc1-xenial.deb
apt update
注意 如果您希望将另一个Linux发行版作为主服务器运行,则.deb可以使用以下格式替换另一个发行版的初始文件:
基于Red Hat的系统:
wget https://yum.puppetlabs.com/puppetlabs-release-pc1-OS-VERSION.noarch.rpm
基于Debian的系统:
wget https://apt.puppetlabs.com/puppetlabs-release-pc1-VERSION.deb
然后必须修改任何特定于Ubuntu的命令以进行适当的分发。可以在Puppet的安装文档或我们的包管理指南中找到更多信息。
安装puppetmaster-passenger包:
apt install puppetmaster-passenger
默认的Puppet安装可以启动Apache并将其配置为在与Puppet相同的端口上侦听。停止Apache以避免这种冲突(如果使用CentOS7,请apache2在此示例中更改httpd):
systemctl stop apache2
通过运行确保您拥有最新版本的Puppet:
puppet resource package puppetmaster ensure=latest
更新/etc/puppet/puppet.conf
并添加dns_alt_names
到该部分的行[main]
,替换puppet.example.com
为您自己的FQDN:
/etc/puppet/puppet.conf
[main]
dns_alt_names=puppet,puppet.example.com
启动Puppet master:
systemctl start puppetmaster
默认情况下,Puppet主进程侦听端口8140上的客户端连接。如果puppetmaster
服务无法启动,请检查端口是否尚未使用:
netstat -anpl | grep 8140
在运行Ubuntu 16.04或其他基于Debian的发行版的代理节点上,使用此命令安装Puppet:
apt install puppet
在运行CentOS 7或其他Red Hat系统的代理节点上,请按照下列步骤操作:
仅限CentOS 7,添加Puppet Labs存储库:
rpm -ivh https://yum.puppetlabs.com/el/7/products/x86_64/puppetlabs-release-22.0-2.noarch.rpm
注意 如果您使用的是CentOS 7以外的Red Hat系统,请跳过此步骤。
安装Puppet代理:
yum install puppet
修改您的Puppet Agent的主机文件以解析Puppet主IP puppet
:
/etc/hosts
198.51.100.0 puppet
将server
值添加到[main]
节点puppet.conf
文件的部分,替换puppet.example.com
为Puppet master的FQDN:
/etc/puppet/puppet.conf
[main]
server=puppet.example.com
重启Puppet服务:
systemctl restart puppet
在每个代理上,为Puppet master生成一个证书以进行签名:
puppet agent -t
这将输出一个错误,指出没有找到证书。此错误是因为生成的证书需要由Puppet master批准。
登录您的Puppet master并列出需要批准的证书:
puppet cert list
它应该输出一个包含代理节点主机名的列表。
批准证书,替换hostname.example.com为每个代理节点的主机名:
puppet cert sign hostname.example.com
返回Puppet代理节点并再次运行Puppet代理:
puppet agent -t
上面配置的Puppet主节点和代理节点都是可用的,但不安全。根据 保护您的服务器指南中的概念,应配置受限用户和防火墙。这可以通过创建基本的Puppet模块在所有节点上完成,如下所示。
注意 这并不是为完全强化的服务器提供基础,而只是作为一个起点。根据您的特定需求,更改并添加防火墙规则和其他配置选项。
从Puppet master,导航到/etc/puppet/modules
目录并创建用于添加用户帐户的新模块,然后cd
进入该目录:
mkdir /etc/puppet/modules/accounts
cd /etc/puppet/modules/accounts
创建以下目录,这些目录是具有正常运行的模块所需的:
mkdir {examples,files,manifests,templates}
该examples
目录允许您在本地测试模块。files
包含可能需要编辑或添加的任何静态文件。manifests
包含模块的实际Puppet代码,并templates
包含可能需要的任何非静态文件。
移动到manifests目录并创建名为的第一个类init.pp。所有模块都需要一个init.pp文件作为模块的主定义文件。
cd manifests
在init.pp
文件中,定义要使用的受限用户,而不是用您选择的用户名root
替换所有实例username
:
/etc/puppet/modules/accounts/manifests/init.pp
class accounts {
user { 'username':
ensure => present,
home => '/home/username',
shell => '/bin/bash',
managehome => true,
gid => 'username',
}
}
该init.pp
文件最初定义了accounts
该类。然后它调用user
资源,其中username
定义了a 。ensure
设置该值以确保用户存在(存在)。该home
值应设置为用户的主目录路径。shell
定义shell类型,在本例中为bash shell。managehome
注意到应该创建主目录。最后,gid
为用户设置主要组。
虽然主要组设置为共享用户名,但尚未创建组本身。保存并退出init.pp
。然后,创建一个名为的新文件groups.pp
并添加以下内容。此文件将用于创建用户的组。再次,username
用您选择的用户名替换:
/etc/puppet/modules/accounts/manifests/groups.pp
class accounts::groups {
group { 'username':
ensure => present,
}
}
通过在类中添加include groups
到文件中来包含此文件:init.ppaccounts
/etc/puppet/modules/accounts/manifests/init.pp
class accounts {
include groups
...
}
此用户应具有权限,以便可以执行管理任务。因为我们在基于Debian和Red Hat的系统上都有代理节点,所以新用户需在Debian系统上的组sudo
中,以Red Hat系统上的组wheel
中。这个值可以通过使用selector和facter动态设置,这是Puppet中包含的程序,用于跟踪每个服务器的信息或事实。init.pp
在帐户类括号内的文件顶部添加一个选择器语句,定义两个选项:
/etc/puppet/modules/accounts/manifests/init.pp
class accounts {
$rootgroup = $osfamily ? {
'Debian' => 'sudo',
'RedHat' => 'wheel',
default => warning('This distribution is not supported by the Accounts module'),
}
user { 'username':
...
}
此命令序列告诉Puppet,在accounts模块中,变量$rootgroup
应使用facter评估操作系统family($osfamily
),如果返回的值是Debian
,则将$rootgroup
值设置为sudo
。如果返回的值是RedHat
,则应将此相同值设置为wheel
; 否则,该default
值将输出一个警告,表示此模块不支持所选的分发。
注意 该
user
定义将包括$rootgroup
,对日伪的配置语言执行代码从上到下。你必须定义$rootgroup
之前的user
,以便它可以访问。
将groups
值添加到用户资源,调用$rootgroup
上一步中定义的变量:
/etc/puppet/modules/accounts/manifests/init.pp
user { 'username':
ensure => present,
home => '/home/username',
shell => '/bin/bash',
managehome => true,
gid => 'username',
groups => "$rootgroup",
}
该值"$rootgroup"
用双引号(“)而不是单引号(')括起来,因为它是一个变量。单引号中包含的任何值都将在模块中键入; 用双引号括起来的任何东西都可以接受变量。
需要添加的最终值是password
。由于我们不想使用纯文本,因此应将其作为SHA1摘要提供给Puppet,默认情况下支持该摘要。从终端设置密码:
openssl passwd -1
系统将提示您输入密码并确认。将输出哈希密码。然后应将其复制并添加到user
资源中:
/etc/puppet/modules/accounts/manifests/init.pp
class accounts {
user { 'username':
ensure => present,
home => '/home/username',
shell => '/bin/bash',
managehome => true,
gid => 'username',
groups => "$rootgroup",
password => '$1$07JUIM1HJKDSWm8.NJOqsP.blweQ..3L0',
}
}
注意 哈希密码必须包含在单引号(')中。
保存更改后,使用puppet解析器确保代码正确:
puppet parser validate init.pp
需要解决的任何错误都将记录到标准输出中。如果没有返回任何内容,则代码有效。
在进一步测试模块之前,导航到examples
目录并创建另一个init.pp
文件,这次调用accounts
模块:
cd ../examples
/etc/puppet/modules/accounts/examples/init.pp1
include accounts
添加此行后,保存并退出该文件。
仍在examples
目录中时,测试模块而不进行更改:
puppet apply --noop init.pp
注意 该
--noop
参数可防止Puppet实际运行该模块。
它应该返回:
Notice: Compiled catalog for puppet.example.com in environment production in 0.26 seconds
Notice: /Stage[main]/Accounts::Groups/Group[username]/ensure: current_value absent, should be present (noop)
Notice: Class[Accounts::Groups]: Would have triggered 'refresh' from 1 events
Notice: /Stage[main]/Accounts/User[username]/ensure: current_value absent, should be present (noop)
Notice: Class[Accounts]: Would have triggered 'refresh' from 1 events
Notice: Stage[main]: Would have triggered 'refresh' from 2 events
Notice: Finished catalog run in 0.02 seconds
再次从examples
目录中运行puppet apply
以对Puppet主服务器进行以下更改:
puppet apply init.pp
登出root
以新用户身份登录Puppet master。本指南的其余部分将由该用户运行。
虽然新用户已成功添加到Puppet主服务器,但该帐户仍然不安全。在继续之前,应禁用服务器的根访问权限。
导航到files
该范围内account
的模块目录:
cd /etc/puppet/modules/accounts/files
将sshd_config
文件复制到此目录:
sudo cp /etc/ssh/sshd_config .
用sudo
,打开文件,并将PermitRootLogin
值设置为no
:
/etc/puppet/modules/aacounts/files/sshd_config
PermitRootLogin no
导航回manifests
目录,然后使用sudo
创建一个名为的文件ssh.pp
。使用file
资源将默认配置文件替换为Puppet管理的配置文件:
cd ../manifests
/etc/puppet/modules/accounts/manifests/ssh.pp
class accounts::ssh {
file { '/etc/ssh/sshd_config':
ensure => present,
source => 'puppet:///modules/accounts/sshd_config',
}
}
注意 该行中
file
省略了该目录,source
因为该files
文件夹是文件的默认位置。有关用于访问模块中资源的格式的更多信息,请参阅官方Puppet模块文档。
创建第二个资源以重新启动SSH服务,并将其设置为每当sshd_config
更改时运行。这也需要一个选择器语句,因为ssh
在Debian系统和sshd
Red Hat上调用SSH服务:
/etc/puppet/modules/accounts/manifests/ssh.pp
class accounts::ssh {
$sshname = $osfamily ? {
'Debian' => 'ssh',
'RedHat' => 'sshd',
default => warning('This distribution is not supported by the Accounts module'),
}
file { '/etc/ssh/sshd_config':
ensure => present,
source => 'puppet:///modules/accounts/sshd_config',
notify => Service["$sshname"],
}
service { "$sshname":
hasrestart => true,
}
}
将ssh
课程包括在内init.pp
:
/etc/puppet/modules/accounts/manifests/init.pp
class accounts {
include groups
include ssh
...
您的完整内容init.pp
将与此类似:
/etc/puppet/modules/accounts/manifests/init.pp
class accounts {
include groups
include ssh
$rootgroup = $osfamily ? {
'Debian' => 'sudo',
'RedHat' => 'wheel',
default => warning('This distro not supported by Accounts module'),
}
user { 'example':
ensure => present,
home => '/home/username',
shell => '/bin/bash',
managehome => true,
gid => 'username',
groups => "$rootgroup",
password => '$1$07JUIM1HJKDSWm8.NJOqsP.blweQ..3L0'
}
}
运行Puppet解析器,然后导航到examples
要测试和运行的目录puppet apply
:
sudo puppet parser validate ssh.pp
cd ../examples
sudo puppet apply --noop init.pp
sudo puppet apply init.pp
注意 验证时,您可能会在输出中看到以下行:
Error: Removing mount "files": /etc/puppet/files does not exist or is not a directory
这是指Puppet配置文件,而不是您尝试复制的模块资源。如果这是输出中唯一的错误,则操作仍应成功。
要确保ssh
该类正常工作,请注销然后尝试以as身份登录root
。你不应该这样做。
在本节中,我们将使用配置防火墙规则iptables
。但是,默认情况下,这些规则不会在重新启动后保留。要避免这种情况,请在继续之前在每个节点(主服务器和代理服务器)上安装相应的软件包:
Ubuntu / Debian:
sudo apt install iptables-persistent
CentOS 7:
CentOS 7默认使用firewalld作为iptables的控制器。在开始直接使用iptables之前,请确保firewalld已停止并已禁用:
sudo systemctl stop firewalld && sudo systemctl disable firewalld
sudo yum install iptables-services
在Puppet主节点上,从Puppet Forge安装Puppet Lab的防火墙模块:
sudo puppet module install puppetlabs-firewall
该模块将安装在您的/etc/puppet/modules
目录中。
导航到manifests
新firewall
模块下的目录:
cd /etc/puppet/modules/firewall/manifests/
创建一个标题为的文件pre.pp
,其中包含应首先运行的所有基本网络规则:
/etc/puppet/modules/firewall/manifests/pre.pp
class firewall::pre {
Firewall {
require => undef,
}
# Accept all loopback traffic
firewall { '000 lo traffic':
proto => 'all',
iniface => 'lo',
action => 'accept',
}->
#Drop non-loopback traffic
firewall { '001 reject non-lo':
proto => 'all',
iniface => '! lo',
destination => '127.0.0.0/8',
action => 'reject',
}->
#Accept established inbound connections
firewall { '002 accept established':
proto => 'all',
state => ['RELATED', 'ESTABLISHED'],
action => 'accept',
}->
#Allow all outbound traffic
firewall { '003 allow outbound':
chain => 'OUTPUT',
action => 'accept',
}->
#Allow ICMP/ping
firewall { '004 allow icmp':
proto => 'icmp',
action => 'accept',
}
#Allow SSH connections
firewall { '005 Allow SSH':
dport => '22',
proto => 'tcp',
action => 'accept',
}->
#Allow HTTP/HTTPS connections
firewall { '006 HTTP/HTTPS connections':
dport => ['80', '443'],
proto => 'tcp',
action => 'accept',
}
}
每条规则都通过评论文字进行解释。更多信息也可以在Puppet Forge防火墙页面上找到。
在同一目录create中post.pp
,它将运行需要最后输入的任何防火墙规则:
/etc/puppet/modules/firewall/manifests/post.pp
class firewall::post {
firewall { '999 drop all':
proto => 'all',
action => 'drop',
before => undef,
}
}
这些规则将指示系统删除防火墙中尚未允许的所有入站流量。
sudo puppet parser validate pre.pp
sudo puppet parser validate post.pp
上移目录,创建新examples
目录并导航到该目录:
cd ..
sudo mkdir examples
cd examples
在其中examples
,创建一个init.pp
文件来测试Puppet master上的防火墙:
/etc/puppet/modules/firewall/examples/init.pp
resources { 'firewall':
purge => true,
}
Firewall {
before => Class['firewall::post'],
require => Class['firewall::pre'],
}
class { ['firewall::pre', 'firewall::post']: }
firewall { '200 Allow Puppet Master':
dport => '8140',
proto => 'tcp',
action => 'accept',
}
此代码块保证pre.pp
和post.pp
正常运行,并增加了一个防火墙规则的木偶大师,让节点访问它。
通过Puppet解析器运行该init.pp
文件,然后测试它是否会运行:
sudo puppet parser validate init.pp
sudo puppet apply --noop init.pp
如果运行成功,请运行puppet apply
不带--noop
选项:
sudo puppet apply init.pp
一旦Puppet运行完毕,请检查iptables规则:
sudo iptables -L
它应该返回:
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere /* 000 lo traffic */
REJECT all -- anywhere 127.0.0.0/8 /* 001 reject non-lo */ reject-with icmp-port-unreachable
ACCEPT all -- anywhere anywhere /* 002 accept established */ state RELATED,ESTABLISHED
ACCEPT icmp -- anywhere anywhere /* 004 allow icmp */
ACCEPT tcp -- anywhere anywhere multiport ports ssh /* 005 Allow SSH */
ACCEPT tcp -- anywhere anywhere multiport ports http,https /* 006 HTTP/HTTPS connections */
ACCEPT tcp -- anywhere anywhere multiport ports 8140 /* 200 Allow Puppet Master */
DROP all -- anywhere anywhere /* 999 drop all */
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere /* 003 allow outbound */
现在已经在Puppet master上创建,测试和运行了accounts
和firewall
模块,现在是时候将它们添加到之前创建的Puppet代理节点中了。
从Puppet master,导航到/etc/puppet/manifests
。
cd /etc/puppet/manifests
列出所有可用的代理节点:
sudo puppet cert list -all
创建文件site.pp
以定义哪些节点将采用哪些模块。替换ubuntuagent.example.com
并centosagent.example.com
使用代理节点的FQDN:
/etc/puppet/manifests/site.pp
node 'ubuntuagent.example.com' {
include accounts
resources { 'firewall':
purge => true, }
Firewall {
before => Class['firewall::post'],
require => Class['firewall::pre'],
}
class { ['firewall::pre', 'firewall::post']: }
}
node 'centosagent.example.com' {
include accounts
resources { 'firewall':
purge => true,
}
Firewall {
before => Class['firewall::post'],
require => Class['firewall::pre'],
}
class { ['firewall::pre', 'firewall::post']: }
}
这包括accounts
模块并使用与上述相同的防火墙设置,以确保正确应用防火墙规则。
在每个Puppet代理节点上,启用以下puppet agent
命令:
puppet agent --enable
运行Puppet代理:
puppet agent -t
要确保Puppet代理工作,请以创建的受限用户身份登录并检查iptables:
sudo iptables -L
恭喜!您已在主服务器节点和两个代理节点上成功安装了Puppet。现在您已确认一切正常,您可以创建其他模块以自动化代理节点上的配置管理。有关更多信息,请参阅Puppet模块基础知识。您还可以安装和使用其他人在Puppet Forge上创建的模块。
有关此主题的其他信息,您可能需要参考以下资源。虽然提供这些是希望它们有用,但请注意,我们无法保证外部托管材料的准确性或及时性。