由 puppet 自动化集群管理基础篇,我们了解了 puppet 系统的基本架构、配置方法、资源以及简单的应用。对于大厂来说,puppet 简单应用很难有效解决集群管理中的问题,急需开发模块化、可复用的 puppet 代码结构。接下来作者将带领大家对 puppet 中的 environments、hiera、module、facter、模板进行介绍,从而轻松实现大厂中对大量软件包、配置文件、服务等的管理。
上次我们谈了 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 的值。
Creating environments
在 $confdir 目录下建立 environments 文件夹,目录结构如下。
其中,每个 environment.conf 都是这个环境模块的主配置文件。可以覆盖全局配置文件 puppet.conf 中所设置的变量的值。变量 Environment_timeout 设置了 puppet master 刷新环境信息的频率。不设置时,值为 0,会影响 master 的性能,但是给代码部署带来了方便。所以一旦熟悉了代码部署,就应该设置该值为无限大,即 environment_timeout = unlimited。
测试模块路径是否配置正确。
Synchronizing environments
Agent 在执行不同环境的同步命令时,只需要给 environment 参数赋予不同的值即可。当然你也可以在 agent 的 puppet.conf 配置文件中设置 environment 的值。
同步线上环境:
同步测试环境:
2 模块
由 environments 的组织结构知道,每种环境都是由模块和该环境的配置文件组成。那么什么是模块呢?
写模块前需要注意的三个问题:
1.你的模块需要实现什么任务?
2.你的模块是怎么组织工作的?
3.在你的 puppet 环境中,你的模块应该具有什么更好的功能?
puppet 使用模块来存放类,在模块中定义的类都会在 puppet 编译 catalog 时进行自动加载。模块的命名必须使用小写字母开头,名称中只能包含:小写字母、数字和下划线,因此正则表达式满足:[a-z][a-z0-9_]*。为了使得 puppet 能够找到相应的类,需要在 puppet.conf 中设置 modulepath 的值,现在已经废弃,使用了 basemodulepath。
模块结构
Manifests:存放所有的.pp 文件,即 puppet 的类文件。其中 init.pp 文件比较特殊,一般会包含一个和模块同名的类,不能够自定义 init 名称的类。其他类的命名方法如下。
划分类名称部分的双冒号称为命名空间分隔符。每个子文件夹都是一个命名空间。
Files:包含了所有的 nodes 节点需要下载的文件。Source 属性赋值方式如下:puppet:///modules/my_module/service.conf,注意路径里面没有 files 目录,并且 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 被调用的方法如下。
因此,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。
可以使用–skip-interview 参数过滤掉所有的提问。建立的模块结构如下。
其中 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,生成一个.tar.gz 的包,放在了模块目录的 pkg 子目录中。5.上传模块到 forge 仓库。模块必须小于等于 10M。
3 类
由模块的目录结构,我们可以看到,每个模块都是由许多.pp 文件组成的,即每个模块都包含了很多的类文件。类中包含了所有的资源,通常类被存储在模块的 manifests 文件夹下 puppet 会通过类名自动加载这些类。
Designingclass
类中传入的参数就类似于类中的属性,一旦该类被其他类所继承(inherits),该参数、类中的变量以及资源均可被其他类直接使用,这样的话这些参数必须由默认值或者是自动查找外部数据赋值(hiera),在继承类中无法对这些参数赋值。这样的话,模块的结构就可以确定了,init.pp 入口文件中声明的主类继承参数类 params,该模块下的所有文件(除了 params)都继承 init.pp 中声明的主类。
通常,一个类的定义形式如下。
在类的编写过程中,我们通常会用到标准库中的函数 Include、require、contain 和 hiera_include,这些函数可以让你安全的声明多次类,不管你声明多少次,类只会被添加到编译目录中一次,解决了多重依赖导致的问题。
Using include
Include 函数是标准的声明类的方式。
Using require
Require 函数声明了一个或多个被父类依赖的类,其次也可以声明一个类所依赖的文件。
Using contain
contain 即包含了被声明的类,属于父类的一部分。
Using hiera_include
Puppet 通过 hiera 机制自动的搜索 hiera 数据作为类模块的参数。但是这一切都是基于 hiera 配置的。Puppet 目录下的 hiera.yaml 配置文件如下所示。
Puppet 目录下的 hiera 数据采用 myclass::parameter_one 的形式,参数如果没有默认值则报错。所以一般都要给默认的参数赋予默认值。就类似于空指针,声明指针的同时一定要初始化。另外还有特殊的两个变量,title 和 name 不能作为参数传递。
通过 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 代码,在针对不同的安装包、配置文件、执行脚本等资源时可以轻松实现复用。
本文转载自公众号 360 云计算(ID:hulktalk)。
原文链接:
https://mp.weixin.qq.com/s/5XLIKKbewtKd2f2LPQI23A
评论