Puppet自动化集群管理进阶篇

 武伟 360云计算 

女主宣言

puppet自动化集群管理基础篇,我们了解了puppet系统的基本架构、配置方法、资源以及简单的应用。对于大厂来说,puppet简单应用很难有效解决集群管理中的问题,急需开发模块化、可复用的puppet代码结构。接下来作者将带领大家对puppet中的environments、hiera、module、facter、模板进行介绍,从而轻松实现大厂中对大量软件包、配置文件、服务等的管理。

PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”,点关注哦!

Puppet自动化集群管理进阶篇


上次我们谈了puppet系统的架构、配置以及简单的应用。这次我们将进一步介绍如何编写模块化的puppet代码。其中,我们将涉及到puppet系统中的几个重要概念,包括environments、hiera、module、facter、模板等,通过这几个概念的结合,可以轻松的实现可复用的puppet代码。

首先,在我们的工作中,一般分为开发环境、测试环境、和生产环境。所有的代码在上线之前,都需要在测试环境中进行多次、多项指标的测试。没问题之后,才可以将代码放入生产环境进行上线。那么puppet是怎么对各种环境进行管理的呢?下来我们开始讲解puppet。


1

Environments

为了隔离开发环境、线上环境和测试环境,我们充分引入了puppet的environment模块。Puppet主配置文件puppet.conf中的environmentpath变量指明了puppet将要查询的environments文件夹的路径。如果有多个值,需要以冒号分隔。如果路径中有相同的environment名称,则以第一个路径下的environment为准。Puppet默认会先从environment目录下的modules目录中加载模块,如果为空,会从puppet.conf文件夹的basemodulepath所指的目录下查找模块。

Configuring environments


在全局的puppet.conf配置文件中设置basemodulebath/modulepath的值。

basemodulepath= $confdir/modules:

$confdir/environments/$environment/modules


Creating environments


在$confdir目录下建立environments文件夹,目录结构如下。

Puppet自动化集群管理进阶篇

其中,每个environment.conf都是这个环境模块的主配置文件。可以覆盖全局配置文件puppet.conf中所设置的变量的值。变量Environment_timeout设置了puppet master刷新环境信息的频率。不设置时,值为0,会影响master的性能,但是给代码部署带来了方便。所以一旦熟悉了代码部署,就应该设置该值为无限大,即environment_timeout = unlimited。

测试模块路径是否配置正确。

Puppet自动化集群管理进阶篇

Synchronizing environments

Agent在执行不同环境的同步命令时,只需要给environment参数赋予不同的值即可。当然你也可以在agent的puppet.conf配置文件中设置environment的值。

同步线上环境:

Puppet agent -t --environment=production

同步测试环境:

Puppet agent -t --environment=staging


2

模块

由environments的组织结构知道,每种环境都是由模块和该环境的配置文件组成。那么什么是模块呢?

写模块前需要注意的三个问题:

  1. 你的模块需要实现什么任务?

  2. 你的模块是怎么组织工作的?

  3. 在你的puppet环境中,你的模块应该具有什么更好的功能?

puppet使用模块来存放类,在模块中定义的类都会在puppet编译catalog时进行自动加载。模块的命名必须使用小写字母开头,名称中只能包含:小写字母、数字和下划线,因此正则表达式满足:[a-z][a-z0-9_]*。为了使得puppet能够找到相应的类,需要在puppet.conf中设置modulepath的值,现在已经废弃,使用了basemodulepath。

Puppet自动化集群管理进阶篇

模块结构

Puppet自动化集群管理进阶篇

Manifests:存放所有的.pp文件,即puppet的类文件。其中init.pp文件比较特殊,一般会包含一个和模块同名的类,不能够自定义init名称的类。其他类的命名方法如下。

Puppet自动化集群管理进阶篇

划分类名称部分的双冒号称为命名空间分隔符。每个子文件夹都是一个命名空间。

Files:包含了所有的nodes节点需要下载的文件。Source属性赋值方式如下:puppet:///modules/my_module/service.conf,注意路径里面没有files目录,并且puppet后面为三个反斜杠。形式如下。

Puppet自动化集群管理进阶篇

puppet:///modules/my_module/service.conf将映射到my_module/files/service.conf个文件。

Lib:存放插件,包括自定义的facts和自定义资源类型。这些都会被puppet master和puppet agent服务使用到,当他们被请求到时,这些配置会被同步到node。

Templates:包含被manifests文件夹下的文件所使用的.erb或者.epp文件。对于erb文件,使用了ruby中的template函数;对于epp文件,使用了puppet语法,调用了epp函数。模板的输出是一个字符串,作为file资源中的content属性的值。Template和epp被调用的方法如下。Puppet自动化集群管理进阶篇

因此,template('my_module/component.erb')将被映射到my_module/templates/component.erb文件。

Facts.d:存放外部的facts变量这些将被同步到所有的node节点,所以node节点可以提交这些变量的值给puppet master(facter >= 2.0.1)。

Examples:包含了如何声明模块类和类型的样本。

Spec:存放了lib目录下所有插件的spec文件。

Functions:存放自定义的puppet语言的函数。

Types:存放类型的别名。

Installing modules

你完全可以根据模块的结构自行建立模块内容。但是为了方便,puppet提供了命令行工具,只需一条命令即可建立模块。如:在开始写模块时,可以利用Puppet module generate <USERNAME>-<MODULE NAME生成一个基本的模块架构,然后就是填空题。但是名称必须以“-”分割(很不友好),且只能包含一个,形如username-modulename。Puppet自动化集群管理进阶篇

可以使用--skip-interview参数过滤掉所有的提问。建立的模块结构如下。Puppet自动化集群管理进阶篇

其中metadata.json描述了所有的模块信息。

Publish modules

我们可以将自己开发的module发布到forge仓库。Forge仓库是模块的社区仓库,方便管理和下载部署。

自己的模块一般有两个名字:一个短名称,如“mysql”;一个长名称,加上自己的用户名如“puppetlab-mysql”。

  • Forge仓库需要长名称,且要有metadata.json,这个是因为forge会将长模块名分成username/module的格式。

  • 在磁盘上时,只能运用短名称。

发布步骤:

  1. 在puppet官网创建一个forge账号。

  2. 创建一个不包含任何无用信息的模块,并且有正确的metadata.json文件,且都是UTF-8编码。如果使用命令行生成的module,默认都是UTF-8编码。

  3. 删除模块中的符号链接。不然在制作模块时会报错。

  4. 建立模块。Puppet module build <MODULE DIRECTORY>,生成一个.tar.gz的包,放在了模块目录的pkg子目录中。

  5. 上传模块到forge仓库。模块必须小于等于10M。


3

由模块的目录结构,我们可以看到,每个模块都是由许多.pp文件组成的,即每个模块都包含了很多的类文件。类中包含了所有的资源,通常类被存储在模块的manifests文件夹下puppet会通过类名自动加载这些类。

DesigningclassPuppet自动化集群管理进阶篇

类中传入的参数就类似于类中的属性,一旦该类被其他类所继承(inherits),该参数、类中的变量以及资源均可被其他类直接使用,这样的话这些参数必须由默认值或者是自动查找外部数据赋值(hiera),在继承类中无法对这些参数赋值。这样的话,模块的结构就可以确定了,init.pp入口文件中声明的主类继承参数类params,该模块下的所有文件(除了params)都继承init.pp中声明的主类。

通常,一个类的定义形式如下。

Puppet自动化集群管理进阶篇

在类的编写过程中,我们通常会用到标准库中的函数Include、require、contain和hiera_include,这些函数可以让你安全的声明多次类,不管你声明多少次,类只会被添加到编译目录中一次,解决了多重依赖导致的问题。

Using include

Puppet自动化集群管理进阶篇

Include函数是标准的声明类的方式。

Using require

Require函数声明了一个或多个被父类依赖的类,其次也可以声明一个类所依赖的文件。

Puppet自动化集群管理进阶篇

Using contain


contain即包含了被声明的类,属于父类的一部分。

Puppet自动化集群管理进阶篇

Using hiera_include


Puppet通过hiera机制自动的搜索hiera数据作为类模块的参数。但是这一切都是基于hiera配置的。Puppet目录下的hiera.yaml配置文件如下所示。

Puppet自动化集群管理进阶篇

Puppet目录下的hiera数据采用myclass::parameter_one的形式,参数如果没有默认值则报错。所以一般都要给默认的参数赋予默认值。就类似于空指针,声明指针的同时一定要初始化。另外还有特殊的两个变量,title和name不能作为参数传递。

Puppet自动化集群管理进阶篇

通过hiera可以将节点相关的配置从manifests中分离出来。Manifests用于完成不同功能的模块,使用hiera Data调用这些线程的模块将其应用到服务器中。使得节点自定义的配置更容易。应用到节点的个性配置只保存在hiera中。在有新的环境需要部署时,不需要更改manifests中的代码,只需要在hiera中赋予此节点需要的配置数据即可。

Important class keywords

  • Before:当前者资源(before上面的)成功执行后,再通知下一资源(before后面的)执行。

  • Require:在本资源执行之前,需要确认其他资源是否已经成功被执行。

  • Notify:主动通知其他资源本资源的状态。

  • Subscribe:用于被动通知,当subscribe资源公有属性检测依赖资源变化时,主动更新所在资源状态。

  • ->:就相当于箭头符号,指出动作的流向。先执行箭头之前的动作,再执行箭头之后的动作。两个资源的首字母要大写。

  • ~>:指出动作的流向,如果前一个动作执行失败,则后一个动作停止执行。


4

总结

在本文章中,我们讨论了如何同步不同的puppet环境,进一步讨论了如何建立不同环境下的模块,最后介绍了模块中类的结构和设计方法。通过将environments、module、class、hiera等puppet机制结合使用,我们可以轻松实现模块化的puppet代码,在针对不同的安装包、配置文件、执行脚本等资源时可以轻松实现复用。



上一篇:容器化 Confluence 使用拾遗


下一篇:spring boot启动过程源码分析