直接讲了如何在puppetstandlone的模式下如何去构建出一个所谓的希望目标管理状态模式的一种应用
但是puppet通常的业务逻辑,通常不会是standalone模型的,而是master/agent模型的
纲举目张的方式,创建出纲
所有的核心运用都是在资源清单上,清单内容不非就是定义资源
puppet核心资源类型:group, user, file, package, service, exec, cron, notify
查看资源类型 puppet describe [-l] [type]
*资源清单:manifests, .pp
资源类型名称,(必须全部小写) type{‘title’:用于标识在当前类型中,这个资源的ID或身份(可以称为同一类型中的资源ID)
attribute => value,(用键值对来实现,类型的实例化)
…
}
资源被引用,使用type 引用:Type[‘title’]
元参数:
before/require 依赖关系
notify/subscribe 通知或订阅关系
->, ~>
现在左侧都表示要在前资源使用的,右侧的是要在后资源定义的
还可以定义依赖链或者通知链
->,~>
既可以在资源定义时直接在其后面定义依赖或通知量,也可以在所有资源以后,用引用资源的方式,来定义其通知或依赖链,
数据类型:字符串、数值、布尔型、数组、hash(大括号中,关联数组,逗号分隔的键值对)、undef未定义类型(本质上都是ruby编程语言的数据类型)
独特的数据类型,正则表达式(不能赋值给变量,但是支持一个特殊的赋值符号,?问好打头定义所谓的标志位,i表示是否区分大小写,加减号表示区分,不加表示不区分,m是否把点号做换行符,x是否忽略模式中的空字符,一般有?i-mx):
(?<enable_flag>-<disable_flag>:)
flag: i, m, x
可以使用变量,定义时也要加$符号,相对名称,绝对名称FQN
变量:$variable,
FQN: $::scope1::scope2::variable 完全限定名称(一般引用不在当前作用域范围内的变量,就需要使用FQN)
$variable
编程元素:
流程控制:
if, case(简装版多分支if), selector(每一个分支返回一个字符串), unless(if not)
puppet是用ruby语言编写,所以支持类
type是内建的,class是用户自定义的
类:
class class_name[($parameter1[=value1形参可以有默认值,直接在这里加上,否则在内部申明时必须传一个参数,否则等于引用了一个未定义的变量,会报错], $parameter2)] {
…puppet code…
}
class sub_class_name inherits class_name {类可以继承,继承以后可以重载,对应父类中所定义的资源,或者是给对应的父类资源的某一个属性,新增值或覆盖原有值,甚至把资源重新申明都没有什么问题
… puppet code …
}
、sub_class_name:一般的名称方式是=父/基类名称::子类名
base_class::sub_class_name
子类中引用父类的资源:并完成某属性值重置
Type(需要大写)[‘title’] {
attribute => value,给属性赋值
atrribute +> value,
}
声明类:(无须传递参数,直接用include即可)
include class_name
需要传递参数,给形参赋值,用class
class{‘class_name’:
attribute => value,
}
类是puppet非常重要的东西,只有有了他,有了这个概念,才能去组织类为模块
模板:(不同场景下的配置文件可能需要有些变化的,可以在静态文件里内嵌代码)
ansible 用的jinjia2,有一个模块python
erb:Embedded RuBy
<%= erb code %>变量替换用=等号
<% erb code %> 不做变量替换就直接放在%%里面
<%# erb code %> 如果是注释有#号表示
通常模版文件以.erb结尾
file类型的资源
引用方式 content => template(’/PATH/TO/ERB_FILE’)
template这个函数会处理文件中的内容,把代码执行完成,并有返回值的时候放在代码所在处
**众多主机如果都需要某个对应的功能,master/agent通过https协议进行通讯,用到的通信协议是rpcover,https,就是通过https传递的xml,pc的远程过程调用,xml每个标签字描述,以至于双方主机不至于无解
但是xml有额外开销,10K数据,有3K是xml的,现在很多都不要xml了,如果想轻量化用json格式(键值对),相比较可以比xml轻量很多,YML/YAML更轻量的,现在都用这个,因为要想一个数据传递到对方以后,对方要理解,通常要描述一个数据结构,这个结构要被隐藏起来,通常xml,每一个元素都要加一个标签,所以使得标签占用了很多的空间
很重量,所以开始轻量化xml,简装版xml就是json,mongodb和elasticsearch存储的时候都是json的,比xml就轻量很多了。但是key的占用的也很多
但是要想更轻量化,要使用YML格式
现在都转向了YML和json格式,尤其是k8s文件定义时 **
master/agent 对应的node节点都有可能要使用一些功能,比如都需要在同一网络中的时间服务器同步时间
DNS地址,(/etc/resolve)应该指向本网段私有的DNS服务器地址,
对于每一个主机都应该配置好取引用时间服务器的配置,并确保时间服务是运行的,这样就需要我们写的代码复用到多台主机上去,
这些代码就可以组成模块来实现
模块:
modulepath配置参数指定的目录路径下(使用puppet config print modulepath来查看默认设定),每一个模块都遵循特定的组织结构;
manifests/
init.pp (至少得存在一个与模块名同名的类)(3.8之前的版本,需要在INIT.PP中import,把其他的类包含进来)
sub_class_name.pp 子类,(子类文件里的类名应该是完整意义上的类名)
files/
puppet:///modules/MOD_NAME/FILE_NAME 静态文件
templates/模版
template('MOD_NAME(引用模块名)/ERB_FILE’引用文件名)
lib/ 插件
tests/ 适用帮助和示例
spec/ 是对插件的使用帮助
standalone:
puppet apply -e ‘include CLASS_NAME’ 调用使用-e 申明某个类即可
每一个agent会固定的到master端拉取与自己相关的模块(加入服务端有6个模块,如何知道哪个是和自己相关的)
在/etc/puppet/modules目录下有一个路径,专门用来存储模块
一个主机来请求如何知道用哪个模块,master需要指派,有主机配置层,来定义哪一个主机的相关配置,主机是用主机名,不能使用ip地址,因为ip地址是经常会发生改变的,对某某主机调用了哪个模块,直接在这里进行调用,模块无法调用,调用的是模块中的类
主机调用的清单里定义的是主机要调用的类的,所以称为主机清单,而不是资源清单,这定义的不是资源,而是主机,定义主机是定义主机要调用的类,而调用的类都应该是来自于模块的
只需要在master主机为各节点各主机定义出这个主机应该调用的执行的puppet代码即可
一个文件中用于定义N个主机,每一个主机使用node+{}表示
standalone:puppet apply
master/agent:agent每隔30分钟到master端请求与自己相关的catalog
master: site manifest
node ‘node_name’ {
…puppet code…
}
一个主机在请求一个相关资源清单时,master先要去识别节点的主机名,再来匹配与这几个主机名相关的主机清单中的主机资源定义。主机调用的一些类,把被调用的类拿过来进行编译,编译成catalog而后再发送给主机,发送给主机的时候,就已经是编译后生成的结果了,发送过去的不是代码,而是编译后生成的结果,
所以基于此每一个主机,都可以请求与自己相关的配置,默认是每隔半小时一次,请求以后确保每个主机必须处于目标状态,
二者使用https协议通信,而且是双向验证,master要验证agent证书,agent也要验证master证书,
由于是周期性执行,而且都是agent每隔一段时间去服务端请求的,服务端就需要监听在套接字上,tcp协议的8140端口,所以agent才会固定过来请求与自己相关的配置的,服务端要运行守护进程,并监听在一个固定套接字上
对应agent端需要运行成一个守护进程,不过这个进程不监听什么端口,只不过这个进程每个一段时间就自动地去找master端请求与自己相关的配置
通信之前需要配置master端,而且也是CA,能够给自己发证书当master用,每个agent链接到master之前都会有一个证书请求并发送master,master负责签署,安全起见可以手动签,不用使用openssl,puppet内部就 有,使用内部编辑器即可
部署master:
安装程序包:facter, puppet, puppet-server
agent端只需要 facter puppet
初始化master:
puppet master --no-daemonize --verbose
生成一个完整的配置参数列表:
puppet master --genconfig
puppet agent --genconfig
… 站点清单的定义:
主机名定义:
主机名(主机角色)#-机架-机房-运营商-区域.域名
www1-rack1-yz-unicom(联通)-bj(北京).magedu.com
先准备master,master主机上可以现有模块,把模块准备好,把CA准备好,然后把主机清单准备好(每个主机大概拥有什么配置)
再找一个客户端主机,装上puppetagent,启动服务,链接服务端,master收到请求后,先允许CA签证,一旦签证有请求就到master守护进程上,matser就开始查站点清单,找到与这个主机相关的配置
69当master,67,68当agent
node3当,master、node1,2当agent
把etc/host文件复制过去
需要先同步时间
现在去安装部署master主机,需要下载3。8版本以后
puppetfile文件,之前的文件都是通过url从文件系统下载下来的
/etc/puppet/manifest 主机清单,必须要叫做site.pp
unitfile文件
要想启动,得先初始化master端
初始化master:
puppet master --no-daemonize(不要在后台运行) --verbose(显示详细信息)(这个步骤并非必须的)
给CA生成一个私钥,
给ca生成一个证书签收请求
自签证书
创建证书回收列表
给自己服务器生成一个证书签署请求
证书签署以后,请求就可以删除了
一旦完成以后就会监听在一个套接字上
如果想要重新签,就把这个目录删除,生产环境不建议用,会导致agent链接不过来
把agent程序包复制过去
与master通讯是用的agent命令
要指明服务器端,如果不指明,将会读取自己的配置文件
做为agent端应该指明server是谁,才会知道链接哪一个主机
可以在命令行给出
–noop不真正执行只是看一眼
1.给自己生成密钥
2.缓存CA的证书
3.生成一个证书签署请求
4.把这个请求发送给服务端
master就收到了请求了
收到请求,没有签署,对方没有证书,对方就不可能提供给master证书
服务端使用一个命令即可签证
master端管理证书签署:
puppet cert(管理证书的) [–all] []
** action:
list
sign
revoke
clean:吊销指定的客户端的证书,并删除与其相关的所有文件;**
生成证书
列出带签署请求
签署
吊销
-all列出所有的
sign 签署 node节点,只签指定节点
把i请求删除,只保留证书
没有在指定时间,签署,对方就提示没收到,再启动一次即可
出现这个错误很正常,拿到证书与服务端联系了,事实上并没有定义这个节点应该拥有的配置
把之前写的两个配置文件复制过去
定义站点清单,这里支持模式,不加引号,.点好可能会认为是通配任意字符
再请求一次就不报错了,可以加–debug更加详细
改一下master的模块
文件发生 改变,所以文件替换
chronyd 服务重启 refresh
确实已经更改
可以启动服务了
默认每隔半小时给master发送请求
master端也不用这么前台运行了,执行systemctl 运行即可
第二台agent运行为一个NT,现在master端开发模块
这里的mainfest写错,应为manifests
提供配置文件
改个名字
如果文件发生改变,需要重启服务的,ensure = running 处于运行状态
->定义先后关系、
依赖的配置文件,现在另外的node4节点上安装
复制配置文件到master过去
定义node2
把puppet安装包复制过去
运行
matser端应该收到证书签收请求了,sign发证
重新来一次
出现错误,安装程序包的时候直接使用array是不可以的
没什么问题
启动服务,
一次安装多个包,只能再title下,不能再name下,name不支持列表
title写成列表,意味着多个package,隐含循环的意思
本地做下测试
跑一次看看有没有报错,报错
把引号去掉
没问题
启动服务,现在就正常了
打开主页需要的是webapps
对于nginx的模块还需要简单修改下
进行反代时要修改proxy_pass
重启node1,获取配置
现在访问 67就访问tomcat了
完成NT通过puppet配置了