文章目录
一、简介
Puppet是开源的基于Ruby的系统配置管理工具,依赖于C/S的部署架构。主要开发者是Luke Kanies,遵循GPLv2版权协议。从1997年开始Kanies参与UNIX的系统管理工作,Puppet的开发源于这些经验。因为对已有的配置工具不甚满意,从2001年到2005年间,Kanies开始在Reductive实验室从事工具的开发。很快,Reductive实验室发布了他们的旗舰产品——Puppet
二、目录结构
![1648170965047](https://s2.loli.net/2022/04/02/ixfzDGMAgSuFw1y.png)
puppet遵循定义-模拟-执行-报告的工作流程
![http://s4.51cto.com/wyfs02/M01/7E/0D/wKioL1b2G0_DjchOAAEi-eJInp4054.jpg](https://s2.loli.net/2022/04/02/WQT56Dj9qYyCfgb.jpg)
(a) agent把节点名与facts信息发送给master
(b) master通过site.pp中包含的node名称匹配agent相关的资源路径,将所需要的class类信息编译后存入catalog并发送给agent
© agent对catalog进行代码验证(检测语法及错误)并执行,执行信息、结果写入日志
(d) agent完成执行,系统达到预期状态,把结果及执行数据返回给master
客户端与服务器端的安全认证
- Puppet通信都采用SSL安全加密协议,以保障所有数据传输的安全性
- Puppet Master 在启动后会向自己签发证书和key。可以在/var/puppet/ssl或/var/lib/puppet/ssl目录下看到它们
- Puppet Agent 在运行puppet apply–test 时添加参数–verbose 可以在客户端终端看到申请证书的详细过程
- Puppet Master 同样可以使用puppetcert list查看申请证书的客户端列表。使用命令puppetcert sign agent_name来签发证书
- 如果Master一直不签发证书,客户端会每2分钟请求一次
三、一个helloworld
3.1 创建module
module的目录结构是固定的,目录的结构一般如下所示:
├── files
├── manifests
└── templates
- files: 属于模块的文件
- manifests: 脚本文件
- templates:模板文件
mkdir -p /etc/puppet/modules/helloworld/{files,templates,manifests}
新建模块的init.pp文件
vi /etc/puppet/modules/helloworld/manifests/init.pp
class helloworld{
file { '/tmp/hello.txt':
owner => 'root',
group => 'root',
mode => '0440',
source => 'puppet:///modules/helloworld/hello_old.txt'
}
}
- 配置file
在 /etc/puppet/modules/helloworld/files 预先新建hello_old文件
echo 'helloworld' > /etc/puppet/modules/helloworld/files/hello_old.txt
3.2 配置入口
编辑入口文件 vi /etc/puppet/manifests/site.pp ,无则新建
node 'Hostname(agent端的主机名)' {
include helloworld
}
3.3 验证
客户端执行 puppet agent -t --summarize
![1648174920191](https://s2.loli.net/2022/04/02/OkZQKUzRwg9dbmA.png)
测试查看
四、常用资源列表
资源依赖四大元参数:
资源依赖:
require:配置当前资源中,指向被引用的资源, 且被引用的资源的资源类型需要首字母大写
before:配置在被引用的资源中,指向当前资源
资源通知:
subscribe:订阅,配置在被引用资源,文件发生变化即可执行
notify:通知,配置在当前资源,文件发生变化通知执行
4.1 user
定义:管理系统上的用户
#title:用户名
user{'testuser':
#present/absent,删除用户使用absent
ensure => present,
#是否为系统用户
system => false,
#注释
comment => 'Test User',
#默认是shell类型
shell => '/bin/bash',
#用户的home目录
home => '/home/testuser',
#是否创建家目录,默认为false
managehome => true,
#附加组,不包含基本组
groups => 'testuser',
#用户的UID
uid => 3000,
#用户组gid
gid => 3000,
#用户加密的密码
password => '$1$2xm5sJf2$IaidZnkoU5gY23sccEimT0',
}
4.2 group
定义: 管理系统上的用户组
#组名
group{'testgroup':
#组名
name => 'testgroup',
#用户组的gid,不指定将自动设置大于500的随机值
gid => 1212,
#默认为false,允许使用同一个gid
allowdupe => false,
#默认为false,系统平台默认创建uid为0-500的系统用户
system => false,
#默认属性,创建present,删除absent
ensure => present,
#组成员管理
menbers => ['zhangsan','lisi']
}
4.3 package
定义: puppet的管理软件包
安装软件包
package{'redis':
#包名,可以省略,如果省略,将继承title的值
name => 'redis',
#ensure:installed, present, latest, absent, any version string (implies present)
ensure => installed,
#程序包来源,仅对不会自动下载相关程序包的provider有用,例如rpm或dpkg
#source => '/tmp/redis.rpm'
#指明安装方式
provider => yum
}
4.4 file
定义: 管理文件、目录、软链接
同步服务器文件至客户端
file{'test':
#目的路径
path => '/tmp/test',
#源路径
source => 'puppet:///modules/testfile/test',
#定义文件属主
owner => 'zhangsan',
#定义文件属组
group => 'zhangsan',
#定义文件的权限
mode => '755',
}
创建目录,文件,符号链接
file {'/tmp/test'
#ensure可设置为file,directory,link
#分别表示文件、目录和软链接
ensure => link,
#软链接需要指定目标文件
target => /opt/test
}
4.5 service
定义: 定义服务的状态
#监听nginx.conf文件的变化,若发生改变则重启nginx
service{'nginx':
#服务的状态,运行为true,停止为false
ensure => true,
#开机启动设置
enable => true,
#是否支持restart属性值
hasrestart => true,
#是否支持status属性值
hasstatus => true,
#监听文件改动
subscribe => File["/usr/local/nginx/conf/nginx.conf"],
restart => "nginx -s reload",
}
file {"/usr/local/nginx/conf/nginx.conf":
notify => Service["nginx"]
}
4.6 exec
定义:**执行外部命令,慎用 **
exec{'cmd':
command => 'mkdir /data/testdir',
path => ['/bin','/sbin','/usr/bin','/usr/sbin'],
}
当命令返回0才执行exec
exec{'nginx -s reload'
#命令的搜索路径
path => '/usr/bin:/usr/sbin:/bin',
#true表示命令仅刷新触发
refreshonly => false,
#命令返回0才会执行
onlyif => '/usr/local/nginx/sbin/nginx -t',
#尝试执行次数
tries => 3,
#重试期间的等待时间
try_sleep => 5,
}
4.7 cron
定义: 定义周期性任务
cron{'timesync':
command => 'ntpdate 10.27.126.249',
ensure => present,
minute => '*/3',
user => 'root',
}
4.8 notify
定义: 调试输出
notify{
"I am running!"
}
五、变量与作用域
PUPPET变量:由字母[a-z]、[A-Z]、[0-9]和下划线(_)组成,且大小写敏感,puppet中变量必须以"$“为前缀后接”="进行赋值,变量可以保存字符串、数值、布尔型、数组、哈希和特殊的undef值
5.1 数据类型
- 字符串类型
字符串类型需要以双引号或单引号进行声明。puppet默认的数据类型就是字符串类型,不能使用Puppet关键字。这里有几个特殊的符号作为变量值时,需要进行转义:
\$ : $符号
\”: 双引号
\' : 单引号
\\ : 反斜杠
\n : 回车换行符
\r : 回车换行
\t : tab键,一个tab键默认是7个空格
\s : 空格
- 数值类型(很少用)
数值类型是指定义成的数值形式的数据,这种数据可以直接进行加、减、乘、除等数学运算。
#下面是puppet运算符的优先级从高到底排序:
! : 取反
In : 范围
\* 和 / : 乘和除
\- 和 + : 减和加
<<和>> : 左移和右移
== 和 != :等于和不同于
\>= <=和>< :大于等于、小于等于和大于、小于
And : 与
Or : 或
- 正则表达式
在前面我们也简单用了下正则表达式,正则表达式我们在node哪里正则定义多主机的时候是很有用的,因为随着主机的众多不可能一个个的node定义下去。
[] : 用于描述范围(如[A-Z],表示范围在A~Z之间的大写字母)
(): 用于包含正则表达式
\w:用于描述字母或数字,相当于[0-9a-zA-Z]
\W : 非字母或数字。
\s: 匹配[\t\n\r\f],其中(\t)为制表符、(\r)为回车符、(\n)为换行符、(\f)为换页符、(\s)表示匹配这些符号的简写方式。
\S : 匹配非空字符。
\d:匹配[0-9]数字。
\D : 匹配非数字。
\b : 匹配退格符
\B : 非字边界
*:前面元素出现0次或多次
+:前面元素出现1次或多次
{m,n}:前面匀速最少出现m此,最多出现n次
?: 前面元素最多出现1次,等价于{0,1}
|:与前面或后面表达式匹配
i :表示忽略大小写
5.2 变量赋值
class apache ($sta = "present") {
package {"httpd":
ensure=> $sta,
}
}
注意:PUPPET不支持重复赋值,也就是一个变量只可以被赋值一次
特殊的变量:Facter变量
定义:Facter是一款扩展性强且功能强大的跨平台的系统性能分析收集工具,它可以收集Agent的信息,并将收集到的Agent信息作为变量传给master使用
5.3 作用域
根据大括号范围区分:
#$content变量分别定义于top域、node域和local域.
#示例:
$content="top"
node base {
include admin
$content="node"
}
#继承了base节点
node /sh-(proxy|web)\d+/ inherits base {
case $::hostname {
/sh-proxy\d+/: {
include apache
user {"test1":
ensure => present,
}
}
"sh-web1": {
include nginx::nginxconf
$content="sh-web1"
notify {"this value is $content":}
}
}
}
本示例会输出sh-web1,因为局部变量的优先级最高,{}包裹的区间之间作用域不共享,仅全局变量可被子括号区间读取
六、条件语句与函数
6.1 条件语句
-
if语句
if $operatingsystem == "CentOS"{ notify{ "This is CentOS!" } } elsif $operatingsystem in ["RedHat", "Fedora"]{ notify{ "This is RedHat, Fedora!" } }else{ notify{ "This is other linux release!" } }
-
case语句
case $operatingsystem{ 'Solaris': { include role::solaris } 'RedHat','CentOS': { include role::redhat } /^(Debian|Ubuntu)$/: { include role::debian } default: { include role::default } }
-
selector
$rootgroup = $osfamily ? { 'Solaris' => 'whell', /(Darwin|FreeBSD)/ => 'whell', default => 'root', } file { '/etc/passwd' ensure => file, owner => 'root', group => $rootgroup, }
6.2 表达式
定义:由两个操作数和一个运算符组成,! 操作除外,表示非操作
运算符:
比较操作符:==,!= ,< , >, <= ,=> , !~ 不能被模式匹配, =~能被模式匹配, in
逻辑操作符: and ,or ,|
算数操作符: +, - ,*,/, %, << , >>
布尔运算符:and or !
6.3 函数
puppet函数是在编译过程中运行的预定义Ruby代码块,puppet中包含了大量可调用的内置函数
注:函数只会在编译中运行,过程变量只能是master节点中的内容
-
create_resources(资源类型,一组资源的哈希描述):创建资源
$myuser = { 'nick' => { uid => '1300', group => allstaff, groups => ['root', 'nick'] } } create_resources(user, $myuser)
-
require:添加依赖关系
-
tag:表示标签
-
tagged:表示标记,是一个boolean类型的函数
-
template:表示模板
七、模块、类、模板
7.1 模块
模块清单:
创建模块:
mkdir -p /etc/puppet/modules/{模块名称}/{files,templates,manifests}
创建模块配置文件:
vi /etc/puppet/modules/{模块名称}/manifests/init.pp
编写templates的ERB模板
vi /etc/puppet/modules/{模块名称}/templates/tmp.erb
创建说明文件
vi /etc/puppet/modules/{模块名称}/Modulefile
vi /etc/puppet/modules/{模块名称}/README
7.2 类
定义:由一个关键字与一个代码块实现
class class_name {...}
若存在多个类,采取双冒号定义
class class_name {...}
class class_name::newclass1 {...}
class class_name::newclass2 {...}
类的继承
#定义父类
class nginx {
service { 'nginx':
name => nginx,
ensure => running,
enable => true,
requireb => File['nginx.conf']
}
}
#定义继承的类
class nginx::foo inherits nginx {
service{ 'nginx':
ensure => running,
enable => false
}
}
7.3 模板
ERB模板:全称是Embedded RuBy,意思是嵌入式的Ruby,是一种文本模板技术,用过JSP的话,会发现两者语法很像。我们项目中一般用ERB来产生各模块的配置文件。ERB模板也可以用来产生Web页面(之前搞过一段时间ROR开发,模板用的haml),也可以用来产生其他文件。
<% %>与<%= %>区别:
<%Ruby脚本%>,一般是Ruby的逻辑脚本,但是不会写入到目标文件中。
<%= Ruby脚本%> ,脚本的执行结果会写入到目标文件中。
define testingsite($cgidir, $tracdir) {
file { "testing-$name":
path => "/etc/tomcat/testing/$name.conf",
owner => superuser,
group => superuser,
mode => 644,
require => File[tomcatconf],
content => template("testsite.erb"),
notify => Service[tomcat]
}
symlink { "testsym-$name":
path => "$cgidir/$name.cgi",
ensure => "/usr/share/test/cgi-bin/test.cgi"
}
}
<Location "/cgi-bin/ <%= name %>.cgi">
SetEnv TEST_ENV "/export/svn/test/<%= name %>"
</Location>
# You need something like this to authenticate users
<Location "/cgi-bin/<%= name %>.cgi/login">
AuthType Basic
AuthName "Test"
AuthUserFile /etc/tomcat/auth/svn
Require valid-user
</Location>
组合模板
template('/path/to/template1', '/path/to/template2')
迭代模板
$values = [val1,val2,otherval]
<% values.each do |val| -%>
Some stuff with <%= val %>
<% end -%>
模板条件
<% if broadcast != "NONE" %> broadcast <%= broadcast %> <% end %>
模板变量:
#编写模板变量
testvariable = template('/var/puppet/template/testvar')
#未定义变量,检测变量生效情况
<% if has_variable?("myvar") then %>
myvar has <%= myvar %> value
<% end %>
#超范围变量
<%= scope.lookupvar('apache::user') %>
八、节点管理
定义:puppet的每个客户端被称为节点,所有节点定义在site.pp文件中,可使用import()进行引用,因此服务器上线前需规范主机名的书写格式,在puppet0.25之后的版本可用正则匹配主机名
# 1.定义通用目的节点
node 'base' {
include ntp
include iptables
include zabbix_agent
}
node 'node1.magedu.com' inherits base { # 节点node1继承基础节点的类
include nginx
}
# 2.节点名称支持使用正则表达式
node /^node[1234]\.lamp\.com$/ {
}
# 3.定义节点的配置文件规划:
/etc/puppet/manifests/
site.pp
import "nginx/*.pp" # 导入各类应用的节点定义文件
import "tomcat/*.pp"
import "varnish/*.pp"
base.pp
nginx/
node1.magedu.com.pp # 内部类继承于base
tomcat/
varnish/
# 4.使用外部的节点分类器ENC
使用yaml语法,PyYAML
ldap: