puppet(4)-類、模版語言、模塊
puppet(4)-類、模版語言、模塊
代碼重用: class, module
類
類是用於公共目的的一組資源,是命名的代碼塊,創建後可在puppet全局進行調用,類可以繼承類是我們構建模塊的基本組件
類:命名的puppet代碼塊,好處就是可以重復調用,需要時可通過名稱進行調用; class my_class { ...puppet code... } puppet code: 包含變量賦值、各種條件判斷語句、資源聲明等等; 註意: 類的名字只能以小寫字母開頭 調用類: include class1, class2, ... class {‘classname‘: }
每個類都會引入一個新的變量scope(作用域),這意味著在任何時候訪問類的變量時,都得使用其完全限定名稱,不過,在本地scope可以重新為top scope中的變量賦於一個新值
寫法舉例一:
class apache{ package{‘httpd‘: ensure => installed, } file{‘httpd.conf‘: path => ‘/etc/httpd/conf/httpd.conf‘, ensure => file, require => Package[‘httpd‘], } service{‘httpd‘: ensure => running, require => Package[‘httpd‘], subsribe => File[‘httpd.conf‘], } }
寫法舉例二:
class nginx{ $webserver=‘nginx‘ package{$webserver: ensure => latest, } file{"/etc/$webserver/nginx.conf": ensure => file, source => "/opt/puppet/modules/$webserver/files/nginx.conf", require => Package[$webserver], # notify => Service[‘nginx‘], } service{$webserver: ensure => running, enable => true, hasstatus => true, hasrestart => true, # restart => ‘systemctl reload nginx.service‘, require => [ Package[$webserver], File["/etc/$webserver/nginx.conf"]], subscribe => File["/etc/$webserver/nginx.conf"], } } class {‘nginx‘: }
類的聲明有四種方法:
1.使用include
2.使用require
3.像聲明一個資源一樣聲明類
4.使用ENC的風格來聲明一個類
1&3是最常用的
第一種:include base::linux,apache 可以用逗號隔開聲明多個類
include nginx
第二種: require apache這種方式很少用
第三種:
class {‘nginx‘:
version => ‘2.2.21‘
}
可以傳入參數,所以很常用
註意:類只有在聲明後方才執行
定義帶參數的類:
class my_class ($para1=value1, $para2=value2) {
...puppet code...
}
調用時,傳遞參數:
class {‘class_name‘:
para1 => new_value1,
para2 => new_value2,
}
寫法舉例一:
class createuser ($grpname=testgrp,$username=testuser) {
group{"$grpname":
ensure => present,
}
user{"$username":
ensure => present,
gid => $grpname,
}
}
class {‘createuser‘:
grpname => mageedu,
username => mageedu,
}
寫法舉例二:
class nginx ($webserver=‘nginx‘){
package{$webserver:
ensure => latest,
}
file{"/etc/$webserver/nginx.conf":
ensure => file,
source => "/opt/puppet/modules/$webserver/files/nginx.conf",
require => Package[$webserver],
# notify => Service[‘nginx‘],
}
service{$webserver:
ensure => running,
enable => true,
hasstatus => true,
hasrestart => true,
# restart => ‘systemctl reload nginx.service‘,
require => [ Package[$webserver], File["/etc/$webserver/nginx.conf"]],
subscribe => File["/etc/$webserver/nginx.conf"],
}
}
class {‘nginx‘:
$webserver = ‘nginx’,
}
類的繼承:
定義方式:class base_class_name { ... puppet code ... } class base_class_name::class_name inherits base_class_name { ...puppet code... }
base_class_name::class_name 這是繼承類命名的一種規範,讓你一眼就知道這是繼承某個類的子類(它只是一個名字,沒有任何作用,不這樣寫你會以為它沒有繼承其他類,這種命名方式叫做完全限定名稱)
inherits base_class_name 表示繼承哪個類
類的繼承這種寫法的作用:繼承一個已有的類,並實現覆蓋資源屬性,或向資源屬性追加額外值
比如說我之前定義了一個類,這個類就定義了一個package資源-安裝了nginx, 然後我現在又想定義一個類 有修改配置文件和 啟動服務的資源,這時候就可以繼承類。
(1) 繼承資源屬性;
(2) 覆蓋資源屬性;
=>
(3) 追加資源屬性;
+>
類在實現繼承時有幾個要點:(1) 聲明子類時,其基類會被首先聲明; (2) 基類成為子類的父作用域,因為基類變量和屬性默認值會被子類直接復制一份 (3) 子類可以覆蓋父類中同一資源的相同屬性值
繼承類的實例:
class nginx { package {‘nginx‘: ensure => latest, } -> service {‘nginx‘: enable => true, ensure => running, hasrestart => true, hasstatus => true, restart => ‘service nginx reload‘ } } class nginx::webserver inherits nginx { file{‘/etc/nginx/nginx.conf‘: source => ‘/opt/puppet/modules/nginx/files/nginx_web.conf‘ ensure => file, notify => Service[‘nginx‘], } } class nginx::haproxy inherits nginx { file{‘/etc/nginx/nginx.conf‘: source => ‘/opt/puppet/modules/nginx/files/nginx_proxy.conf‘ ensure => file, notify => Service[‘nginx‘], } }
以上puppet code 定義了一個基類實現程序包的安裝,此外我們額外定義了兩個子類,分別實現 webserver 和 proxy功能。
但是一臺機器上怎麽聲明呢?一個節點不能帶兩種角色,什麽時候用呢?
將來我們做master/agent模型,兩個node ,第一個node include nginx::webserver這個類,另外一個node include nginx::haproxy可以引用測試: include nginx::webserver
高級繼承:
繼承後子類改父類資源中屬性的值:class nginx { package {‘nginx‘: ensure => latest, } -> service {‘nginx‘: enable => true, ensure => running, hasrestart => true, hasstatus => true, restart => ‘service nginx reload‘ } } class nginx::webserver inherits nginx { Package[‘nginx‘]{ ##這裏是資源引用 大寫[‘tittle‘] name => ‘tengine‘, } file{‘/etc/nginx/nginx.conf‘: source => ‘/opt/puppet/modules/nginx/files/nginx_web.conf‘ ensure => file, notify => Service[‘nginx‘], } } class nginx::haproxy inherits nginx { file{‘/etc/nginx/nginx.conf‘: source => ‘/opt/puppet/modules/nginx/files/nginx_proxy.conf‘ ensure => file, notify => Service[‘nginx‘], } } 從新定義父資源中的屬性時要使用資源引用 即 Package[‘nginx‘]{ name => ‘tengine‘, } 在子類總不僅可以修改屬性,還可以加 比如: Package[‘nginx‘]{ name +> ‘varnish‘, }
有了類我們就可以組織模塊了,不過為了讓模塊功能更加強大,我們可以在puppet中使用模版,那麽我們就要學習puppet的模版語言。
學習模版語言之前我們先想下,模版語言有什麽作用?
舉個例子,前面我們 定義了nginx類,類中定義了package資源,file資源,service資源。 其中file資源定義的是 nginx的配置文件,配置文件裏有一個配置項需要根據服務器的cpu個數,如何靈活的根據服務器cpu的個數來配置nginx中的這一項參數呢?寫死是一種方式,然後在拷貝多個配置文件,定義不同的子類,子類在重新定義file資源中的source屬性,也可以實現,但是不是很繁瑣,所以我們可以想象有這麽一種方式,在nginx.conf文件中定義一個變量,變量的值就是取服務器的cpu個數,那麽靜態文件中定義變量,用什麽來解釋呢。在puppet中當然就由puppet來解釋,而這種在靜態文件中定義變量以及寫邏輯判斷的做法就叫做模版語言。所以我覺得模版語言 其實就是針對file資源使用的語言。puppet是ruby語言開發的,所以puppet 模版文件中嵌套的語言也是ruby語言。
模版:基於ERB嵌入式的ruby模版語言,他表示在靜態文件中使用變量等編程元素生成適用於多種環境的文本文件(配置文件)。Embedded Ruby簡稱ERB,它主要用於實現在文本文件嵌入ruby代碼。原來的文本信息不回被改變,但是ruby代碼會執行。執行的結果將直接替換原來的代碼處:
語法: <%= Ruby Expression %>: 替換為表達式的值; <% Ruby Expression %>: 僅執行代碼,而不替換。 <%# comment %>: 文本註視 <%% 表示轉義符 輸出為<%這個符號,一般用不到 %%> 輸出為 %> ,用不到 <%- Ruby code %>, 忽略空白字符 <% Ruby code -%> ,忽略空白行。 能夠用到的只有第一種 模版語言中可以使用puppet中的任意可用變量,但是變量名要以@符號開頭。 在模版中還可以使用循環 ,條件判斷等各種復雜語法格式。 條件判斷: <% if condition -%> some text <% else %> some other text <% end %> 叠代,像for循環 <% @ArrayName.echo do | variable_name %> some text with <%- variable_name %> <% end %> 這裏ArrayName是 puppet的一個數組變量。 variable_name 為賦值給的變量,相當於 for i in list ,list是ArrayName , i是 variable_name 條件和叠代 不要求會,能看懂別人寫的代碼就行 了,關鍵我們會使用變量就行了。比如上面說到nginx的配置文件問題。
如何在資源定義中引用模版?
首先我們把file文件的source 改成關於啟動進程的部分改成如下:
user nginx; worker_processes <%= @processorcount %>; error_log /var/log/nginx/error.log; pid /run/nginx.pid;
對於這種含有模版語言的文件,我們應用到file資源屬性要改變一下用法了,不能用source 屬性,改用 content屬性以及 puppet內置的模版函數template() ,具體如下:
class nginx { package {‘nginx‘: ensure => latest, } -> service {‘nginx‘: enable => true, ensure => running, hasrestart => true, hasstatus => true, restart => ‘service nginx reload‘ } } class nginx::webserver inherits nginx { Package[‘nginx‘]{ name => ‘tengine‘, } file{‘/etc/nginx/nginx.conf‘: source => ‘/opt/puppet/modules/nginx/files/nginx_web.conf‘, ensure => file, notify => Service[‘nginx‘], } } class nginx::haproxy inherits nginx { file{‘/etc/nginx/nginx.conf‘: #source => ‘/opt/puppet/modules/nginx/files/nginx_proxy.conf‘ content => template(‘/opt/puppet/modules/nginx/files/nginx_proxy.conf‘), ensure => file, notify => Service[‘nginx‘], } } include nginx::haproxy
以上就是模版語言,以及模版語言是如何調用的。
modules
puppet模塊:為了實現某種完備功能而組織成的一個獨立的、自我包含的目錄結構
模塊名:目錄名
目錄結構:
modules/
module_name/:
manifests/
init.pp: 必須聲明一個類,類名與模塊名相同;
*.pp:
MODULE_NAME::[SUBDIR_NAME]::MANIFESTS_FILE_NAME
files/:
靜態文件
puppet url:
puppet:///modules/MODULE_NAME/[SUBDIR_NAME]/FILE_NAME
file{‘nginx.conf‘:
source => puppet:///modules/nginx/nginx.conf
}
templates/:
模板文件:*.erb
template(‘MODULE_NAME/TEMPLATE_FILE_NAME‘);
file{‘nginx.conf‘:
content => template(‘模板文件‘),
}
lib/: 插件
tests/: 模塊使用說明文檔,以及事例example
spec/: lib目錄下的插件使用說明文檔
puppet model
ACTIONS:
build Build a module release package.
changes Show modified files of an installed module.
generate Generate boilerplate for a new module.
install Install a module from the Puppet Forge or a release archive.
list List installed modules
search Search the Puppet Forge for a module.
uninstall Uninstall a puppet module.
upgrade Upgrade a puppet module.
puppet(4)-類、模版語言、模塊