结合源码,简单分析下 OpenStack puppet 安装。
puppet 安装
- 每台机器都要设置好 hostname,因为 ssl 证书需要。
- NTP 保持时间一致
- client 端安装 puppet 包
- master 端安装 puppetmaster 包
puppet 注意点
- 是 C/S 架构
- client 会定期 30 分钟和 master 通信,如果配置信息被修改,则执行。间隔修改的方法: /etc/puppet/puppet.conf 中的[agent]中设置 runinterval = 60
- 也可以人工强制执行: puppet agent -t
client 与 master 的交互过程
- 客户端 puppet 调用 facter,facter 会探测出这台主机的一些变量如主机名、内存大小、IP 地址等。然后 puppet 把这些信息发送到服务器端。
- 服务器端的 puppetmaster 检测到客户端的主机名,然后会到 manifest 里面对应的 node 配置,然后对这段内容进行解析,facter 送过来的信息可以作为变量进行处理的,node 牵涉到的代码才解析,其它的代码不解析,解析分几个过程:语法检查、然后会生成一个中间的伪代码,然后再把伪代码发给客户机。
- 客户端接收到伪代码之后就会执行,客户端再把执行结果发送给服务器。
- 服务器再把客户端的执行结果写入日志。
语法
-
变量
- 声明格式:$变量名=“值”
- 引用格式:${变量名}
- 如果要取 facts 中的值,可以使用 ${::fact-name} ,这种写法告诉人们是 top-scope variable,而不是用户自己定义的 local-scope variable
-
字符串
- ‘不包含变量的字符串用单引号’
- “包含变量的字符串需要用双引号 ${::operatingsystem} ,同时变量要用花括号包裹起来”
- 对变量本身的引用不需要单引号或双引号。 例如 ${::operatingsystem}
-
数组
- [ “apache2” , " httpd " , " ssh " ]
-
资源:
type { "title ": attribute =>"value", ... attribute => "value", }注意:
- type 不能乱写,puppet 已定义了很多 type,例如:
- file
- package
- service
- cron
- user
- group
- exec
- notify
- attribute =>“value"写法
- 属性间“,”分割
- type 不能乱写,puppet 已定义了很多 type,例如:
-
引用 首字母大写是
引用,小写是声明 -
资源之间的关系
- before
- after
- require
-
class:资源的集合
class 类名 { type { "title ": attribute => "value", ... attribute => "value", } type { "title ": attribute => "value", ... attribute => "value", } } -
class 继承
class 类名(新建)inherits 父类名(已存在){ Type ["title"] {attribute => "value",} } -
函数定义
define 函数名(变量名1,...,变量名n) { #格式:$var type { "title ": attribute => "变量名", #格式:${var},下同 ... attribute => "变量名", } type { "title ": attribute => "变量名", ... attribute => "变量名", } } -
引用 define
函数名 { 变量名 => "值", ... 变量名 => "值", }类名::函数名 { 变量名 => "值", ... 变量名 => "值", } -
模块
up-testmodule --模块名 ├── files --pp中需要用到的文件 ├── manifests --所有pp文件 │ └── init.pp --入口,在其中引用其他pp ├── Modulefile ├── templates --xxx.erb -
模块中的 namespace
例如 mysql::server
-
模板 template
- puppet 通过 erb(embedded Ruby)支持模板,模板的文件名必须以 erb 结尾
- 检查模板:
erb -x -T '-' xxx.erb | ruby -c - 可以使用数组、条件语句、变量作用域
-
好的命名规范
- 模块名就是软件名字,例如 apache
- 类名应该是模块名::功能名,例如
apache::vhost
-
node
-
建议专门新建 nodes.pp 来存放 node 信息
-
默认节点定义
node default { 变量的声明 #声明格式:$变量名="值" 引用格式: ${变量名} include 类名,...,类名 #已定义好的类class }
-
自己编写 facter 的方法
举例:/modules/haproxy/lib/facter/haproxy_version.rb
当 agent apply haproxy 时,就在本地增加了自定义的 facter,该 facter 可以收集 agent 上的 haproxy 的版本号
facter -p haproxy_version 可以查看该 facter 值
最佳实践
调试方法:
Exec {'output': logoutput => on_failure}notify { "aaa ${fqdn} "}生成例子:
puppet resource file /etc/keystone/policy.json
file { '/etc/keystone/policy.json':
ensure => 'file',
content => '{md5}459ce538f825ed818c7794beeddf4523',
ctime => '2016-03-02 09:06:02 +0100',
group => '163',
mode => '640',
mtime => '2016-03-02 08:20:02 +0100',
owner => '163',
type => 'file',
}例子: puppet client 在本地执行 manifest
-
文件管理
-
写一个 manifest: test.pp
file { "/tmp/haha": content => "haha" } -
执行
puppet apply test.pp -
在/tmp 目录下会发现新文件
-
-
包管理
-
写一个 manifest: test.pp
package { ["gcc", "make", "nginx", "haproxy"]: ensure => installed } -
执行
sudo puppet apply test.pp -
上述 4 个包会被自动安装
-