10 月,开发者不可错过的开源大数据大会-2021 WeDataSphere 社区大会深圳站 了解详情
写点什么

Puppet 自动化集群管理进阶篇

2019 年 11 月 15 日

Puppet自动化集群管理进阶篇

由 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 的值。


basemodulepath= $confdir/modules:$confdir/environments/$environment/modules
复制代码


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 的值。


同步线上环境:


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。



模块结构


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


2019 年 11 月 15 日 15:56489

评论

发布
暂无评论
发现更多内容

新工业化如何实现?今年的信息化百人会中藏着“懂行”密码

脑极体

面经手册 · 第18篇《AQS 共享锁,Semaphore、CountDownLatch,听说数据库连接池可以用到!》

小傅哥

Java 并发编程 共享锁 Semaphore 信号量

国网浙江建设公司推进“信用基建+区块链”建设

CECBC区块链专委会

区块链 国网 基建

阿里P8以hashmap讲解如何学习jdk源码,还不学习

小Q

Java 学习 源码 jdk mybatis

什么是云服务?

anyRTC开发者

音视频 WebRTC 云服务 RTC

Android热修复之DexPatch介绍

阿里云金融线TAM SRE专家服务团队

android

微服务通信之feign的配置隔离

云流

编程 微服务 计算机

vue项目实战经验汇总

徐小夕

Java 面试 Vue 前端 Vue3

Dubbo 接口,导出 Markdown ,这些功能 DocView 现在都有了!

程序员小航

markdown idea插件 IntelliJ IDEA 文档生成 Doc View

学习笔记:架构师训练营-第八周

四夕晖

我真的尽力了,最经典Redis面试14题,没时间复习就看这个吧

小Q

redis 学习 编程 架构 面试

《网络是怎样连接的》PDF下载

计算机与AI

网络

MySQL中的锁机制

AI乔治

Java MySQL 架构 线程 锁机制

注册中心原理剖析

石刻掌纹

CSS 排版与正常流 —— 重学CSS

三钻

CSS 排版

架构师训练营 -week09-总结

大刘

极客大学架构师训练营

读谱对吉他手来说重要吗?试试它提升你的读谱效率

奈奈的杂社

学习 编曲 打谱

【MySQL】如何最大程度防止人为误操作MySQL数据库?这次我懂了!!

冰河

MySQL 数据库 性能优化 数据安全 分布式数据储存

智变的八个瞬间,京东智联云化“?”为“!”

脑极体

Redis 持久化之 RDB 与 AOF 详解

AI乔治

Java 架构 redis持久化 redia

11.11 应对海量访问的网络基石 京东智联云自研交换机发展之路

京东科技开发者

运维 网络 交换机

架构师训练营 -week09-作业

大刘

极客大学架构师训练营

在Codurance是如何面试技术人员的

sherlockq

面试 TDD

数字货币引发的金融变革

CECBC区块链专委会

数字化时代

高承实:区块链的工业革命带来了什么?

CECBC区块链专委会

区块链 分布式

nginx 平滑升级、以及导入第三方模块

sinsy

nginx 升级

会装虚拟机,删库不用跑

MySQL从删库到跑路

虚拟机 virtualbox

MySQL从库维护经验分享

Simon

MySQL 主从复制

Springboot过滤器和拦截器详解及使用场景

AI乔治

Java spring 架构 Spring Boot

【薪火计划】03 - 从错误中认识到管理

brave heart

管理

甲方日常53

句子

工作 随笔杂谈 日常

Puppet自动化集群管理进阶篇-InfoQ