自动化运维工具-----puppet入门详解

一.三大运维工具的比较

  • 下表是各大自动化工具的使用下载情况

自动化运维工具-----puppet入门详解_第1张图片

  • 下表则是三大运维工具的简介以及优缺点
名称 简介 优点 缺点
Puppet 是一个开源的软件自动化配置和部署工具,它使用简单且功能强大,很多大型IT公司均在使用puppet对集群种的软件进行管理和部署 能够在web界面生成处理报表、资源清单、实时节点管理,push命令可即刻触发变更 相对于其他工具较为复杂,需要学习puppet的DSL或者Ruby,安装过程缺少错误校验和生成错误报表
SaltStack 是一种全新的基础设施管理方式,部署轻松,在几分钟内可以运行起来,扩展性能好,很容易管理上万台服务器,速度够快,服务器之间毫秒级通讯 可以使用简单的配置模块或者复杂的脚本,web界面可以看到运行和监控的工作状态、事件日志、扩展能力极强。 缺少生成深度报告的能力
Ansible 是新出现的运维工具,是基于Python开发的综合了众多老牌运维工具的优点实现了批量操作系统配置、批量程序的部署、批量运行命令等功能。 模块可以用任何语言开发、被管理节点不需要安装代理软件、有web管理界面、安装运行简单 对windows被管理节点需要加强、执行效率相对较低

二.puppet简介

  • puppet是一个IT基础设施自动化管理工具,它能够帮助系统管理员管理基础设施的整个生命周期,包括:供应(provisioning)、配置(configuration)、联动(orchestration)以及报告(reporting)。
  • 基于puppet,可以实现自动化重复任务、快速部署关键性的应用以及在本地或者云端完成主动管理变更和快速扩展架构规模等。
  • puppet遵循GPL协议(2.7.-),基于ruby语言开发。2.7.0以后使用(Apache 2.0 license)
  • 对于系统管理员是抽象的,只依赖于ruby与facter。
  • 能够管理多达40种资源,例如:file、user、group、host、package、service、cron、exec、yum repo等。
  • 如下为puppet官网:https://puppet.com/

三.puppet的工作机制

puppet的工作模型

  • puppet通过声明性、基于模型的方法进行IT自动化管理。
  • 定义:通过puppet的声明性配置语言定义基础设置配置的目标状态;
  • 模拟:强制应用改变的配置之前先进行的模拟性应用;
  • 强制:自动、强制部署达成目标状态,纠正任何偏离的配置;
  • 报告:报告当下状态以及目标状态的不同,以及达成目标状态所进行的任何强制性改变。
  • puppet的三层模型如下所示:

自动化运维工具-----puppet入门详解_第2张图片

puppet的工作流程

自动化运维工具-----puppet入门详解_第3张图片

puppet的使用模型

  • puppet的使用模型分为单击使用模型和master/agent使用模型,下面我们来看看这两个模型的原理

单机模型

  • 实现定义了多个manifests--》complier--》catalog--》apply

自动化运维工具-----puppet入门详解_第4张图片

master/Agent模型

  • master/Agent模型实现的是集中式管理,即agent端周期性向master端发起请求,请求自己需要的数据,然后在自己的机器上运行,并且将结果返回给master端
  • master/Agent模型的架构如下:

自动化运维工具-----puppet入门详解_第5张图片

  • master/Agent模型的工作原理

自动化运维工具-----puppet入门详解_第6张图片

puppet相关名词解释

  • 资源:是puppet的核心,通过资源申报,定义在资源清单之中。
  • 类:一组资源清单。
  • 模块:包含多个类
  • 站点清单:以主机为核心,应用哪些模块

四.puppet的资源详解

pupet的安装

  • puppet的安装可以使用源码安装,也可以使用rpm(官方提供)、epel源、官方提供的yum仓库来安装(通过下载官方提供的rpm包可以指定官方的yum仓库)
  • 以下使用yum安装puppet
[root@cloud ~]# yum install -y puppet
  • 安装完成之后,可以查看puppet下载后都有什么包,其中/etc/puppet/puppet.conf为主配置文件,使用的主程序为/usr/bin/puppet
[root@cloud ~]# rpm -ql puppet | grep etc
/etc/NetworkManager
/etc/NetworkManager/dispatcher.d
/etc/NetworkManager/dispatcher.d/98-puppet
/etc/logrotate.d/puppet
/etc/puppet
/etc/puppet/auth.conf
/etc/puppet/modules
/etc/puppet/puppet.conf
/usr/share/doc/puppet-3.6.2/examples/hiera/etc
/usr/share/doc/puppet-3.6.2/examples/hiera/etc/hiera.yaml
/usr/share/doc/puppet-3.6.2/examples/hiera/etc/hieradb
/usr/share/doc/puppet-3.6.2/examples/hiera/etc/hieradb/common.yaml
/usr/share/doc/puppet-3.6.2/examples/hiera/etc/hieradb/dc1.yaml
/usr/share/doc/puppet-3.6.2/examples/hiera/etc/hieradb/development.yaml
/usr/share/doc/puppet-3.6.2/examples/hiera/etc/puppet.conf
[root@cloud ~]# 

pupet资源简介

资源抽象

  • puppet可以从以下三个维度来对资源完成抽象:

1.相似的资源被抽象成同一种资源“类型”,如程序包资源、用户资源以及服务资源等;

2.将资源属性或者状态的描述与其实现方式剥离开来,如仅仅说明安装一个程序包而不用关心其具体是通过yum、pkgadd、ports或是其他方式实现;

3.仅仅描述资源的目标状态,也即期望其实现的结果,而不是具体过程,如确定nginx运行起来而不是具体描述为“运行nginx命令将其启动起来”;

  • 这三个也被称为puppet的资源抽象层(RAL)
  • RAL由type(类型)和provider(提供者,即不同OS上的特定实现)组成

资源定义

  • 资源定义通过向资源的属性复制来实现,可以称为资源类型实例化;
  • 定义了资源实例的文件即清单,manifest;
  • 定义资源的语法如下:
type {'title':
        attribute1   => value1,
        attribute2   => value2,
        ...

}

注意:type必须使用小写字母;title是一个字符串,在同一类型中必须唯一,每一个属性之间要用逗号隔开,最后一个逗号可以省略。

例如,可以同时有名为nginx的“service资源”和“package”资源,但是在“package“类型的资源中只能有一个名为”nginx“的资源。

资源属性

  • Namevar:可以简称为name;
  • ensure:资源的目标状态
  • Provider:指明资源的管理接口

puppet常用资源

  • 我们可以使用puppet describe来打印有关的puppet资源类型,提供者和元参数的帮助,使用的语法如下:
puppet decribe [-h|--help] [-s|--short] [-p|--providers] [-l | --list] [-m | --meta] [type]

-s:显示指定类型的简要帮助信息;
-m:显示指定类型的元参数,一般与-s一起使用
-l:列出所有资源的类型

group:管理系统上的用户组

  • 查看group的帮助信息
[root@cloud ~]# puppet describe group -s -m

group
=====
Manage groups. On most platforms this can only create groups.
Group membership must be managed on individual users.
On some platforms such as OS X, group membership is managed as an
attribute of the group, not the user record. Providers must have
the feature 'manages_members' to manage the 'members' property of
a group record.


Parameters
----------
    allowdupe, attribute_membership, attributes, auth_membership, ensure,
    forcelocal, gid, ia_load_module, members, name, system

Meta Parameters
---------------
    alias, audit, before, loglevel, noop, notify, require, schedule, stage,
    subscribe, tag

Providers
---------
    aix, directoryservice, groupadd, ldap, pw, windows_adsi
[root@cloud ~]# 

##相关属性
name:组名,可以省略。如果省略,将继承title的值;
gid:组ID;
system:是否为系统组,true OR false
ensure:目标状态,present/absent;
members:成员用户;


##简单举例如下
vi group.pp
    group{'mygroup':
    name => 'mygroup',
    ensure => present,
    gid => 2000,

    }
  • 试运行group.php
[root@cloud demo]# ls
group.pp
[root@cloud demo]# cat group.pp 
 group{'mygroup':
    name => 'mygroup',
    ensure => present,
    gid => 2000,

    }
##试运行
[root@cloud demo]# puppet apply -v  --noop group.pp 
Error: NetworkManager is not running.
Notice: Compiled catalog for cloud in environment production in 0.08 seconds
Info: Applying configuration version '1588746101'
Notice: /Stage[main]/Main/Group[mygroup]/ensure: current_value absent, should be present (noop)
Notice: Class[Main]: Would have triggered 'refresh' from 1 events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Info: Creating state file /var/lib/puppet/state/state.yaml
Notice: Finished catalog run in 0.02 seconds
##正式运行
puppet apply -v group.pp

user:管理系统上的用户

  • 查看使用帮助信息
[root@cloud demo]# puppet describe user -s -m

user
====
Manage users.  This type is mostly built to manage system
users, so it is lacking some features useful for managing normal
users.
This resource type uses the prescribed native tools for creating
groups and generally uses POSIX APIs for retrieving information
about them.  It does not directly modify `/etc/passwd` or anything.
**Autorequires:** If Puppet is managing the user's primary group (as
provided in the `gid` attribute), the user resource will autorequire
that group. If Puppet is managing any role accounts corresponding to the
user's roles, the user resource will autorequire those role accounts.


Parameters
----------
    allowdupe, attribute_membership, attributes, auth_membership, auths,
    comment, ensure, expiry, forcelocal, gid, groups, home, ia_load_module,
    iterations, key_membership, keys, managehome, membership, name,
    password, password_max_age, password_min_age, profile_membership,
    profiles, project, purge_ssh_keys, role_membership, roles, salt, shell,
    system, uid

Meta Parameters
---------------
    alias, audit, before, loglevel, noop, notify, require, schedule, stage,
    subscribe, tag

Providers
---------
    aix, directoryservice, hpuxuseradd, ldap, pw, user_role_add, useradd,
    windows_adsi
[root@cloud demo]# 

##相关属性的解析
name:用户名,可以省略,如果省略,将继承title的值;
uid:UID;
gid:基本组ID;
groups:附加组,不能包含基本组;
comment:注释;
expiry:过期时间;
home:用户的家目录;
shell:默认shell类型
system:是否为系统用户;
ensure:present/absent;
password:加密后的密码串;
  • 简单举例如下:
vi user1.pp
    user{'keerr':
    ensure => present,
    system => false,
    comment => 'Test User',
    shell => '/bin/tcsh',
    home => '/data/keerr',
    managehome => true,
    groups => 'mygrp',
    uid => 3000,

    }

package:puppet的管理软件包

  • 查看使用帮助信息:
[root@cloud demo]# puppet describe package -s -m

package
=======
Manage packages.  There is a basic dichotomy in package
support right now:  Some package types (e.g., yum and apt) can
retrieve their own package files, while others (e.g., rpm and sun)
cannot.  For those package formats that cannot retrieve their own files,
you can use the `source` parameter to point to the correct file.
Puppet will automatically guess the packaging format that you are
using based on the platform you are on, but you can override it
using the `provider` parameter; each provider defines what it
requires in order to function, and you must meet those requirements
to use a given provider.
**Autorequires:** If Puppet is managing the files specified as a
package's `adminfile`, `responsefile`, or `source`, the package
resource will autorequire those files.


Parameters
----------
    adminfile, allow_virtual, allowcdrom, category, configfiles,
    description, ensure, flavor, install_options, instance, name,
    package_settings, platform, responsefile, root, source, status,
    uninstall_options, vendor

Meta Parameters
---------------
    alias, audit, before, loglevel, noop, notify, require, schedule, stage,
    subscribe, tag

Providers
---------
    aix, appdmg, apple, apt, aptitude, aptrpm, blastwave, dpkg, fink,
    freebsd, gem, hpux, macports, msi, nim, openbsd, opkg, pacman, pip, pkg,
    pkgdmg, pkgin, pkgutil, portage, ports, portupgrade, rpm, rug, sun,
    sunfreeware, up2date, urpmi, windows, yum, zypper
[root@cloud demo]# 


##属性
ensure:installd,present,latest,absent,any version string(implies present)
name:包名,可以省略,如果省略,将继承title的值;
source:程序包来源,仅仅对不会自动下载相关程序包的provider有用,例如rpm或dpkg
provider:指明安装方式


##简单举例如下:
vi package1.pp
    package {'nginx':
        ensure => installed,
        provider => yum
}

service:定义服务的状态

  • 查看使用帮助信息:
[root@cloud demo]# puppet describe service -s -m

service
=======
Manage running services.  Service support unfortunately varies
widely by platform --- some platforms have very little if any concept of a
running service, and some have a very codified and powerful concept.
Puppet's service support is usually capable of doing the right thing, but
the more information you can provide, the better behaviour you will get.
Puppet 2.7 and newer expect init scripts to have a working status command.
If this isn't the case for any of your services' init scripts, you will
need to set `hasstatus` to false and possibly specify a custom status
command in the `status` attribute. As a last resort, Puppet will attempt to
search the process table by calling whatever command is listed in the `ps`
fact. The default search pattern is the name of the service, but you can
specify it with the `pattern` attribute.
**Refresh:** `service` resources can respond to refresh events (via
`notify`, `subscribe`, or the `~>` arrow). If a `service` receives an
event from another resource, Puppet will restart the service it manages.
The actual command used to restart the service depends on the platform and
can be configured:
* If you set `hasrestart` to true, Puppet will use the init script's restart
command.
* You can provide an explicit command for restarting with the `restart`
attribute.
* If you do neither, the service's stop and start commands will be used.


Parameters
----------
    binary, control, enable, ensure, flags, hasrestart, hasstatus, manifest,
    name, path, pattern, restart, start, status, stop

Meta Parameters
---------------
    alias, audit, before, loglevel, noop, notify, require, schedule, stage,
    subscribe, tag

Providers
---------
    base, bsd, daemontools, debian, freebsd, gentoo, init, launchd, openbsd,
    openrc, openwrt, redhat, runit, service, smf, src, systemd, upstart,
    windows
[root@cloud demo]# 
  • service的相关属性
ensure:服务的目标状态,只有true(running)和false(stopped)
enable:是否可以开机自动启动,值有true和false
name:服务名称,可以省略,如果省略,将继承title的值
path:服务脚本路径默认为/etc/init.d下
start:定制启动命令
stop:定制关闭命令
restart:定制重启命令
status:定制状态
  • service的举例文件如下:
vi service1.pp
    service{'nginx':
    ensure => true,
    enable => false
    }

 

file:管理文件、目录、软连接

  • 查看使用帮助信息
[root@cloud ~]# puppet describe file -s -m

file
====
Manages files, including their content, ownership, and permissions.
The `file` type can manage normal files, directories, and symlinks; the
type should be specified in the `ensure` attribute. Note that symlinks
cannot
be managed on Windows systems.
File contents can be managed directly with the `content` attribute, or
downloaded from a remote source using the `source` attribute; the latter
can also be used to recursively serve directories (when the `recurse`
attribute is set to `true` or `local`). On Windows, note that file
contents are managed in binary mode; Puppet never automatically translates
line endings.
**Autorequires:** If Puppet is managing the user or group that owns a
file, the file resource will autorequire them. If Puppet is managing any
parent directories of a file, the file resource will autorequire them.


Parameters
----------
    backup, checksum, content, ctime, ensure, force, group, ignore, links,
    mode, mtime, owner, path, purge, recurse, recurselimit, replace,
    selinux_ignore_defaults, selrange, selrole, seltype, seluser, show_diff,
    source, source_permissions, sourceselect, target, type, validate_cmd,
    validate_replacement

Meta Parameters
---------------
    alias, audit, before, loglevel, noop, notify, require, schedule, stage,
    subscribe, tag

Providers
---------
    posix, windows
[root@cloud ~]# 
  • 相关属性含义
#ensure:目标状态,值有absent,present,file,directory和link
		file:类型为普通文件,其内容由content属性生成或复制由source属性指向的文件路径来创建;
		link:类型为符号链接文件,必须由target属性指明其链接的目标文件;
		directory:类型为目录,可通过source指向的路径复制生成,recurse属性指明是否递归复制;
#path:文件路径;
#source:源文件;
#content:文件内容;
#target:符号链接的目标文件; 
#owner:定义文件的属主;
#group:定义文件的属组;
#mode:定义文件的权限;
#atime/ctime/mtime:时间戳;
  • 简单举例如下所示:
vi file1.pp
    file{'aaa':
        path => '/data/aaa',
        source => '/etc/aaa',
        owner => 'keerr',
        mode => '611',
    }

exec:执行命令,慎用。通常用来执行外部命令

  • 查看使用帮助信息
[root@cloud ~]# puppet describe exec -s -m

exec
====
Executes external commands.
...

Parameters
----------
    command, creates, cwd, environment, group, logoutput, onlyif, path,
    refresh, refreshonly, returns, timeout, tries, try_sleep, umask, unless,
    user

Meta Parameters
---------------
    alias, audit, before, loglevel, noop, notify, require, schedule, stage,
    subscribe, tag

Providers
---------
    posix, shell, windows
[root@cloud ~]# 
  • exec的属性详解
command(namevar):要运行的命令;
cwd:指定运行该命令的目录;
creates:文件路径,仅此路径表示的文件不存在时,command方才执行;
user/group:运行命令的用户身份;
path:指定命令执行的搜索路径;
onlyif:此属性指定一个命令,此命令正常(退出码为0)运行时,当前command才会运行;
unless:此属性指定一个命令,此命令非正常(退出码为非0)运行时,当前command才会运行;
refreshonly:仅接收到订阅的资源的通知时方才运行;
refresh:重新执行当前command的替代命令;
  • 简历举例如下:
vi exec1.pp
    exec{'cmd':
        command => 'mkdir /data/testdir',
    path => ['/bin', '/sbin','/usr/bin','/usr/sbin'],
    #path => '/bin:/sbin:/usr/bin:/usr/sbin',
}

 

cron:定义周期性任务

  • 查看使用帮助信息:
[root@cloud ~]# puppet describe cron -s -m

cron
====
...


Parameters
----------
    command, ensure, environment, hour, minute, month, monthday, name,
    special, target, user, weekday

Meta Parameters
---------------
    alias, audit, before, loglevel, noop, notify, require, schedule, stage,
    subscribe, tag

Providers
---------
    crontab
[root@cloud ~]# 

##相关属性信息
    command:要执行的任务(命令或脚本);
	ensure:目标状态,present/absent;
	hour:时;
	minute:分;
	monthday:日;
	month:月;
	weekday:周;
	user:以哪个用户的身份运行命令(默认为root);
	target:添加为哪个用户的任务;
	name:cron job的名称;


##简单举例如下:
vim cron1.pp
	cron{'timesync':
    	command => '/usr/sbin/ntpdata 172.16.0.1',
    	ensure  => present,
    	minute  => '*/3',
    	user    => 'root',
	}

notify:调式输出

  • 查看使用帮助信息
[root@cloud ~]# 
[root@cloud ~]# puppet describe notify -s -m

notify
======
Sends an arbitrary message to the agent run-time log.


Parameters
----------
    message, name, withpath

Meta Parameters
---------------
    alias, audit, before, loglevel, noop, notify, require, schedule, stage,
    subscribe, tag
[root@cloud ~]# 


##属性信息
message:记录的信息
name:信息名称
  • 该选项一般用于master/agent模式,来记录一些操作时间,比如重新安装一个程序,或者重启应用等。会直接输出到代理机的运行日志中。

资源的特殊属性

  • puppet中提供了before、require、notify和subscribe四个参数来定义资源之间的依赖关系和通知关系

before:表示需要依赖于某个资源

require:表示应该先执行本资源,再执行别的资源

notify:A notify B,表示B依赖于A,而且A发生改变之后会通知B

subscribe:B subscribe A,表示B依赖于A,而且B监控A资源的变化产生的事件;

  • 此外,依赖关系还可以使用->和~>来表示

->表示后资源需要依赖于前资源

~>表示前资源变动通知后资源调用

  • 具体实例如下:

vim file.pp
	file{'test.txt':					#定义一个文件
		path   => '/data/test.txt',
		ensure  => file,
		source  => '/etc/fstab',
	}

	file{'test.symlink':				#依赖文件建立超链接
		path   => '/data/test.symlink',
		ensure  => link,
		target  => '/data/test.txt',
		require => File['test.txt'],
	}

	file{'test.dir':					#定义一个目录
		path   => '/data/test.dir',
		ensure  => directory,
		source  => '/etc/yum.repo.d/',
		recurse => true,
	}

##或者在最下面统一写依赖关系的方式来定义:
vim redis.pp
	package{'reids':
		ensure  => installed,
	}

	file{'/etc/redis.conf':
		source  => '/root/manifets/files/redis.conf',
		ensure  => file,
		owner   => redis,
		group   => root,
		mode    => '0640',
	}

	service{'redis':
		ensure  => running,
		enable  => true,
		hasrestart => true,
	}

	Package['redis'] -> File['/etc/redis.conf'] -> Service['redis']	#定义依赖关系
  • tag标签:puppet可以定义标签--》tag,打了标签之后,我们在运行资源的时候,就可以只运行某个打过标签的部分,而非全部,这就更加方便我们操作。

  • 一个资源中,可以有多个tag也可以有多个。具体用法如下:

type{'title1':
    ...
    tag => 'TAG1',    
}

type{'title2':
    ...
       tag => ['TAG1','TAG2',...],
}


##调用时的语法为:
puppet apply --tags TAG1,TAG2,... FILE.pp
  • 实例如下:

#首先我们去修改一下redis.pp文件,添加一个标签进去
vi redis.pp
    package{'redis':
        ensure => installed,
    }
    file{'/etc/redis.conf':

        source => '/root/manifest/file/redis.conf',
        ensure => file,
        owner => redis,
        group => root,
        mode => '0640',
        tag => 'instconf'        ##定义标签
}

    service{'redis':
        ensure => running,
        enable => true,
        hasrestart => true,
}
    Package['redis'] -> File['/etc/redis.conf'] -> Service['redis']

puppet变量

  • puppet变量以”$“ 开头,赋值操作符为”=“,语法为$variable_name=value

数据类型

  • 字符型:引号可有可无,但是单引号为强引用,双引号为弱引用;支持转义符;
  • 数值型:默认均识别字符串,仅仅在数值上下文才以数值对待;
  • 数组:[]中以逗号分隔元素列表;
  • 布尔型值:true,false;不能加引号;
  • hash:{}中以逗号分隔k/v数据列表;键为字符型,值为任意puppet支持的类型;{‘mon’ => 'Monday','true' => 'Tuesday',};
  • undef:从未被声明的变量的值里类型;
  • 正则表达式
(?:)
(?:)
OPTIONS:
    i:忽略字符大小写;
    m:把.当换行符;
    x:忽略中的空白字符;
(?i-mx;PATTERN)
注意:不能赋值给变量,仅能用在接受=`或者!`操作符的位置

puppet的变量

  • facts:由facter提供;top scope;
  • 内建变量
mater端变量
    $severname,$serverip,$serverversion
agent端变量
    $client,$clientversion,$environment
parser变量
    $module_name
  • 用户自定义变量

变量的作用域:不同的变量也有其不同的作用域。我们称之为Scope。

作用域有三种:top scope,node scope,class scope。

其生效范围排序为:top scope > node scope > class scope

其优先级排序为:top scope < node scope < class scope

puppet流程控制语句

  • puppet支持if语句,case语句和selector语句

if语句

  • if语句分为单分支,双分支和多分支,具体语法如下:
单分支:

if CONDITION {
    statement
    ...
}

双分支:

if CONDITION {
    statement
    ...
}
else {
    statement
    ...
}

多分支:
if CONDITION {
    statement
    ...
}
elsif CONDITION {
    statement
    ...
}
else {
    statement
    ...
}


##CONdITION的给定方式有如下三种:
1.变量
2.比较表达式
3.有返回值的函数


vi if.pp
    if $operatingsystemmajrelease == '7' {
        $db_pkg='mariadb-server'
}else{
        $db_pkg='mysql-server'
}
package{"$db_pkg":
        ensure => installed,
}

case语句

  •  类似if语句,case语句会从多个代码块中选择一个分支执行,这跟其他编程语言中的case语句功能一致。
  • case语句会接受一个控制表达式和一组case代码块,并且执行第一个匹配到控制表达式的块。
  • 使用语法如下:
case CONTROL_EXPRESSION {
    case1:{...}
    case2: {...}
    ....
    default: {...}
}
  • 其中,CONTROL_EXPRESSION的给定方式有如下三种

变量

表达式

有返回值的函数

  • 各个case的给定方式有如下五种:

直接字符串

变量

有返回值的函数

正则表达式模式

default

selector语句

  • selector只能用于期望出现直接值(plain value)的地方,这包括变量赋值、资源属性、函数参数、资源标题、其他selector。
  • selector不能用于一个已经嵌套于selector的case中,也不能用于一个已经嵌套于case的case语句中。
CONTROL_VARIABLE ? {
    case1 => value1,
    case2 => value2,
    ...
    default => valueN,
}
  • 其中,CONTROL_EXPRESSION的给定方式有如下三种:

变量

表达式

有返回值的函数

  • 各个case的给定方式有如下五种

直接子串

变量

有返回值的函数

正则表达式模式

default

五.Class类

类的定义

  • 类是puppet中命名的代码模块,常用于定义一组通用目标的资源,可以在puppet全局调用
  • 类可以被继承,也可以包含子类
  • 具体定义的语法如下:
class NAME {
    ...puppet code ...
}
  • 类的名称只能以小写字母,可以包含小写字母、数字和下划线。

  • 每个类都会引入一个新的变量scope,这意味着在任何时候访问类中的变量,都得使用其完全限定的名称。不过,在本地scope可以重新为top scope中变量赋予一个新值。

  • 如下是一个简单的例子:

vi class1.pp
    class redis {    #定义一个类
        packeage {'redis':
            ensure => installed,
    }    ->
        file{'/etc/redis.conf':
            ensure => file
            source => '/root/manifests/file/redis.conf',
            owner => 'redis',
            group => 'root',
            mode => '0604',
            tag => 'redisconf'
    } ~>
        service{'redis':
            ensure => running,
            enable => true,
            hasrestart => true,
            hasstatus => true
    }
}
include redis    #调用类

#类只有被调用才会被执行。include后可以跟多个类,直接用","隔开即可。

带有参数的类

  • 定义的类也可以进行参数设置,可以进行参数的传递
  • 具体的语法如下:
class NAME(parameter1,parameter2) {   #大括号前有空格
    ...pupet code...
}
  • 具体的实例如下:

vi class2.pp
    class instpkg($pkg) {
        package {"$pkg":
            ensure => installed,
    }
}
    class {"instpkg":            #给参数传入值
        pkg => 'memcached',    
}

#单个主机不能被直接声明两次
  • 如果对应的参数为未传值的话,执行会报错。但是我们可以在定义形参的时候,设定一个默认值,这样的话,我们不传入值的话,就会自动调用默认值

vi class3.pp
    class instpkg($pkg='wget') {
        package{"$pkg":
            ensure => installed,
        }
    }
    include instpkg
#这样的话,我们直接使用include调用即可,就不需要给参数传入值了。
  • 由上,我们可以得知,调用类的方式有两种:

1.include CLASS_NAME1,CLASS_NAME2,...
2.class{'CLASS_NAME':
    attribute => value,
}
  • 下面举一个比较全面的例子:首先我们判断系统的版本是6还是7,由此来确定,是安装mysql还是mariadb,同时,使用调用参数的方式来实现如上需求。

vi dbserver.pp
class dbserver($dbpkg='mariadb-server',$svc='mariadb') {	#定义类并给参数赋值
		package{"$dbpkg":
			ensure  => installed,
		}

		service{"$svc":
			ensure  => running,
			enable  => true,
			hasrestart  => true,
			hasstatus   => true,
		}
	}

	if $operatingsystem == 'CentOS' {
		if $operatingsystemmajrelease == '7' {
			include dbserver		#直接调用类
		} else {
			class{"dbserver":		#调用类并对参数重新赋值
				dbpkg   => 'mysql-server',
				svc     => 'mysqld'
			}
		}
	}

类的继承

  • 类似其他编程语言中的类的功能,pupet的class可以被继承,也可以包含子类。
  • 其定义的语法如下:
class SUB_CLASS_NAME inherits PARENT_CLASS_NAME {
	...puppet code...
}
  • 实例如下:

vim class4.pp
	class redis {		#定义class类
		package{'redis':
			ensure  => installed,
		}

		service{'redis':
			ensure  => running,
			enable  => true,
		}
	}

	class redis::master inherits redis {		#调用父类
		file {'/etc/redis.conf':
			ensure  => file,
			source  => '/root/manifests/file/redis-master.conf',
			owner   => 'redis',
			group   => 'root',
		} 

		Service['redis'] {						#定义依赖关系
			subscribe   => File['/etc/redis.conf']
		}
	}

	class redis::slave inherits redis {			#调用父类
		file {'/etc/redis.conf':
			ensure  => file,
			source  => '/root/manifests/file/redis-slave.conf',
			owner   => 'redis',
			group   => 'root',
		} 

		Service['redis'] {						#定义依赖关系
			subscribe   => File['/etc/redis.conf']
		}
	}

我们在类的调用的时候,可以实现修改原有值和额外新增属性的功能。

1.新增属性:继承父类的时候,可以定义一些父类原本没有的属性;

2.新增原有值:继承的类中,我们可以在属性的原有值的基础上,使用+>进行新增修改;

3.在继承的类中,我们可以直接把原有的值进行覆盖修改,使用=>进行覆盖即可;

4.整体调用父类,并且重写部分值:在继承的类中,我们可以在整体调用的基础上,根据不同的需求,把父类中的部分值进行修改;

六.模板与模块

模板

  • 模板通常以erb结尾。模板均使用erb语法
  • 如右是puppet的erb语法,https://docs.puppet.com/puppet/latest/reference/lang_template_erb.html
  • 实例:puppet模板实现修改redis的端口地址
#首先,我们先来定义一个file.pp文件,在该文件中调用我们的模板
vim file.pp
	file{'/tmp/redis.conf':		#仅用于测试模板是否生效,所以放在tmp目录下
		ensure  => file,
		content => template('/root/manifests/file/redis.conf.erb'),		#调用模板文件
		owner   => 'redis',
		group   => 'root',
		mode    => '0640',
	}

#接着,修改配置文件的源,也就是我们的模板文件
vim file/redis.conf.erb
	bind 127.0.0.1 <%= @ipaddress_eth0 %>	#修改监听端口

#修改完成以后,我们就可以执行查看结果
puppet apply -v file.pp

模块

  • 实践中,一般需要把manifest 文件分解成易于理解的结构,例如将类文件、配置文件甚至包括后面将提到的模块文件等分类存放,并且通过某种机制在必要时将它们整合起来。
  • 这种机制即模块,它有助于以结构化、层次化的方式使用puppet,而puppet 则基于“模块自动装载器”。
  • 从另一个角度来说,模块实际上就是一个按约定的、预定义的结构存放了多个文件或子目录的目录,目录里的这些文件或子目录必须遵循其命名规范

模块的命名规范

  模块的目录格式如下:

自动化运维工具-----puppet入门详解_第7张图片

  • 目录格式

其中,每个文件夹中存放的内容及其要求如下:

MODULE NAME:模块名称,模块名只能以小写字母开头,可以包含小写字母、数字和下划线;但不能使用"main"和"settings";

manifests/:必须要有

  • init.pp:必须一个类定义,类名称必须与模块名称相同;

files/:静态文件;

  • 其中,每个文件的访问路径遵循:puppet:///modules/MODULE_NAME/FILE_NAME

templates/

  • 其中,每个文件的访问路径遵循:tempate('MOD_NAME/TEMPLATE_FILE_NAME')

lib/:插件目录,常用于存储自定义的facts以及自定义类型;

spec/:类似于tests目录,存储lib/目录下插件的使用帮助和范例;

tests/:当前模块的使用帮助或使用范例文件;

 

你可能感兴趣的:(自动化运维工具)