學習puppet不得不掌握的基礎知識

目錄

1、puppet簡介

2、puppet工作原理

3、puppet的安裝

4、puppet常用資源類型

5、puppet的表達式與條件判斷語句

6、puppet類

7、puppet模塊

8、總結

1、puppet簡介 

     puppet是一個爲實現數據中心自動化管理而設計的配置管理軟件,能夠管理IT基礎設施的整個生命週期:供應(provisioning)配置(configuration)、聯動(orchestration)及報告(reporting)。puppet基於C/S架構,類似於zabbiz,有master與agent節點之分。它是一個開源的(談不上真正的開源,因爲有商業版與社區版之分)、新一代的、集中化的配置管理工具,由ruby語言研發,它擁有自己的配置語言(PCL,puppet configuration language)。

    puppet能夠把IT日常的系統管理代碼化,而代碼可重用,這樣可以減少運維人員的工作量,而且能快速、大規模部署服務器。在puppet的世界有其自己的哲學思想:在IT系統管理中,puppet只關注結果,不關心過程!這名話怎樣理解,比如puppet的master端向各agent下達把nginx這個包安裝上並啓動服務,puppet的agent端面只向master端報告軟件是否安裝完成,服務是否已啓動,puppet不關心軟件是怎樣安裝上的,服務是怎樣啓動的,它只關心結果。

2、puppet工作原理

2.1、puppet兩種工作方式介紹    

    puppet有兩種工作方式,一種是獨立工作方式(standalon),另一種是master-agent的方式 。以兩張圖片來說明這兩種工作方式。

wKioL1V6pWuz2Sb9AAFI5bxlT_4074.jpg

(圖一:puppet以standalone方式工作流程示意圖,圖片來自網絡)

圖片中各術語解釋:

manifest:字面意思是清單,在這裏指被puppet代碼化的各種資源,是一種用PCL編寫的代碼;

catalog:表示把各種manifest編譯後生成的可執行代碼,也叫僞代碼;

apply:生成catalog後puppet就可以把代碼進行運用,在運用時也要先對僞代碼進行檢測,檢測後才執行。

wKiom1V6o9_QsxE-AAGI7fvKL08166.jpg

(圖二:puppet的master-agent工作流程圖,圖片來自網絡)

簡述:

a)、agent向主機請求catalog代碼,在請求時要帶上自己的主機名與facts,facts裏包含了agent服務器自身的一些系統特徵,比如操作系統是什麼,是哪個版本,cpu是什麼型號,內存有多大等信息;

b)、master接收到agent的請求後開始查詢此節點包含的清單,把這些資源找出後編譯成catalog,再發送給agent;

c)、agent收到catalog後就開始應用代碼,並把執行的狀態結果生成報告返還給master;

d)、master接收報告並記錄日誌。

2.2、puppet的認證機制簡介

     puppet有其自己的證書管理機制,agent與master間的通信是需要得到master的認證,證書存放在/var/lib/puppet/ssl/。

在master/agent首次啓用的過程:

a)、master啓動時會爲自己生成key,並簽署證書,讓自己成爲一個ca;

b)、agent首次啓動要爲自己生成key,生成證書籤署請求,並將證書請求發送給master請求籤署;

c)、master收到agent的證書籤署請求後,由管理員先驗證請求是否合法,而後對證書籤署請求作出簽署或不簽署。

3、puppet的安裝

    puppet既然是C/S架構,那安裝包就有master安裝包與agent安裝包之分。以下的安裝及測試都是基於CentOS 6.4_x86_64的系統進行,在epel源也包含了puppet的軟件包,所以我以yum安裝爲例。並且下邊代碼的測試都以standalone的工作方式運行。

[root@nod2 ~]# yum -y install puppet-server puppet

#puppet-server是master端所需要安裝包,而puppet是agent,在安裝過程中會安裝許多ruby包依賴的包,並且還會自動安裝好facter相關包。

[root@nod2 ~]# puppet -V  #epel源中是2.7.26的版本
2.7.26

puppet基礎命令:

[root@php ~]# puppet help  #獲取puppet的幫助命令
[root@php ~]# puppet  man parser  #表示獲取parser子命令的幫助信息
[root@php ~]# puppet parser validate init.pp #驗證init.pp文件的語法是否正確
[root@php ~]# puppet describe -l   #獲取支持的資源類型命令,最後接上參數“-l”是L的小寫
[root@php ~]# puppet describe user   #查看特定資源類型的詳細信息,這裏查看user這個資源類型的詳細信息。
[root@php ~]# puppet apply *.pp   #表示對一個資源清單進行運用,“*.pp”表示一個具體的資源清單文件。

4、puppet常用資源類型

    在介紹資源類型前先來看下怎樣定義一個資源,即定義一個資源的語法。

語法格式:

type {'title':
       attribute => value,
       .......
}

解釋:type表示具體的一個資源類型,必須爲小寫,title可以單引號或雙引號,雙引號可實現變量替換,後邊有一個冒號,這樣由許多資源定義成的文件就是一個puppet的manifest,這些文件都是以“.pp”結尾。

定義資源時要注意:

a)、同一類型中,資源名稱必須唯一,默認時就是“title”

b)、資源名稱是否區分大小寫是根據操作系統本身

4.1、puppet常用的資源類型介紹

notify:表示發送一個消息

例如:

[root@nod2 puppet]# vim notify.pp
notify {'message':
    message => "hello.",
}
[root@nod2 puppet]# puppet apply notify.pp
notice: hello.
notice: /Stage[main]//Notify[message]/message: defined 'message' as 'hello.'
notice: Finished catalog run in 0.08 seconds

package:這是一個關於軟件包管理的類型

可以用“puppet describe package”查看詳細的說明文檔,常用的參數爲:

ensure:常用值如下

        present(也叫installed),表示一定要安裝指定的軟件包;

        absent,表示一定不要安裝指定的軟件包

        latest,表示安裝的軟件包是最新版本

name:指定軟件包名,但一般會省略,直接引用“title”作爲軟件包名

source:指定軟件包的路徑,可以是本地路徑,也可以是網絡路徑,注:這些包是在agent上的,並且需要provider指定包的類型

provider:當安裝指定的軟件時需要指定其類型,比如rpm。

file:文件管理的資源類型

常用參數如下:

content:直接生成文件的內容

ensure:常用值如下:

        present:表示文件必須存在

        absent:表示文件一定不能存在

        file:表示存在的一定是一個文件

        directory:表示存在的一定是個目錄

        link:表示創建的是一個鏈接文件,用link時需要用target參數來指定鏈接文件的源文件路徑

source:指定URL下載文件至目標位置

target:當ensure指定爲link時,指定符號鏈接的目標

owner:指定文件的屬主

group:指定文件的屬組

mode:指定文件權限

path:指定文件路徑,如果在title裏指定的全路徑,那path省略

force:強制刪除,與“ensure => absent”時使用

purge:修剪、清理,清除指定目錄中存在但在puppet中未定義的文件

replace:是否替換已經存在的文件

例如:

[root@nod2 puppet]# vim file.pp
file {'file.text':
    ensure => present,
    content => "hello file.\n",
    path   =>  '/tmp/file.text',
    mode   => '0600',
    owner  => root,
    group  => root,
}
[root@nod2 puppet]# puppet apply file.pp
notice: /Stage[main]//File[file.text]/ensure: created
notice: Finished catalog run in 0.05 seconds
[root@nod2 puppet]# cat /tmp/file.text
hello file.
[root@nod2 puppet]# ll /tmp/file.text
-rw-------. 1 root root 12 Jun 11 09:25 /tmp/file.text

service:用於管理系統服務的資源類型

ensure:指定service的狀態,此參數的取值如下:

        true或running:指定服務的狀態是啓動的

        false或stopped:指定服務的狀態是關閉的

enable:指定此服務開機是否自動啓動,有如下值:

        true:表示此服務開機自動啓動

        false:表示此服務開機不自動啓動

name:指定服務名稱,可省略,直接引用“title”

path:指定服務腳本路徑,如果是在系統默認的路徑可省略,如在centos系統上的/etc/rc.d/init.d/下的腳本

restart:指定restart此服務時,執行的指令,在生產環境一般是替換成reload操作

exec:可遠程執行命令的資源類型

此屬性用於在各agent節點執行系統命令,但只是限於不得不需要使用命令才能完成的工作時才這樣使用,這不是puppet的強項,可以用absible來代替。

常用參數有:

command:指定要執行的命令的完全路徑

path:指定命令搜索路徑,多個路徑用冒號隔開,類似於PATH環境

user:命令以哪個用戶身份運行

group:命令以哪個組身份運行

refresh:默認爲收到所依賴的資源的事件時會重新執行此命令,但refresh可以修改此默認執行此命令的動作,而去運行其他的命令或操作

refreshonly:指定此exec資源不會自動被執行,除非被依賴的資源發生改變

returns:指定狀態返回值

tries:指定運行命令嘗試的次數

例如:

[root@nod2 puppet]# vim exec.pp
exec {'date':
    command => '/bin/date > /tmp/date.txt',
    user    => root,
    group   => root,
}
[root@nod2 puppet]# puppet apply exec.pp
notice: /Stage[main]//Exec[date]/returns: executed successfully
notice: Finished catalog run in 0.11 seconds
[root@nod2 puppet]# cat /tmp/date.txt
Thu Jun 11 10:00:39 CST 2015

group:組管理的資源類型

此類型用於管系統組,常用參數:

ensure:表示對組管理的目標狀態,有兩個值

     present:表示一定得有這個組

     absent:表示一定不能有這個組

name:表示指定的組名

gid:表示組的GID號

system:表示這個組是否爲系統組,取值爲

     true:表示爲系統組

     false:表示爲非系統組


user:用戶管理的資源類型

此類型用於管理用戶,常用參數:

ensure:表示對用戶管理的目標狀態,常用值

        present:表示一定得有這個用戶

        absent:表示一定不能有這個用戶

name:表示指定的用戶名

gid:表示組的UID號

system:表示這個用戶是否爲系統用戶,取值爲

         true:表示爲系統用戶

         false:表示爲非系統用戶

gid:用戶所屬的基本組

groups:用戶所屬的附加組

home:用戶的家目錄路徑,並不代表會被創建

managehome:當指定home後,需要此參數爲控制是否真正創建家目錄,有兩個值

         true:表示創建家目錄

         false:表示不創建家目錄,這是默認值

password:指定用戶的密碼,是加密後的密碼串

shell:指定用戶的shell

例如:

[root@nod2 puppet]# vim user.pp
group {'testuser':
    ensure  => present,
    gid     => 555,
}
user {'testuser':
    ensure   => present,
    gid      => 555,
    uid      => 555,
    home     => '/home/testuser',
    managehome => true,
    shell    => '/bin/bash',
}
[root@nod2 puppet]# puppet apply user.pp
notice: /Stage[main]//Group[testuser]/ensure: created
notice: /Stage[main]//User[testuser]/ensure: created
notice: Finished catalog run in 0.32 seconds
[root@nod2 puppet]# id testuser
uid=555(testuser) gid=555(testuser) groups=555(testuser)
[root@nod2 puppet]# ls /home/ 
testuser

cron:任務計劃管理資源類型

ensure:表示cron是否得存在,值有兩個

         present:表示有這個cron

         absent:表示不能有這個cron

command:週期性執行的命令

environment:設置環境變量

hour:小時

minute:分鐘

month:月

monthday:一個月中的哪一天,取值爲1-31

weekday:星期

例如:

[root@nod2 puppet]# vim cron.pp 
cron {'ntpdate':
        ensure  => present,
        command => 'ntpdate time.nist.gov',
        environment => 'PATH=/bin:/usr/bin:/usr/sbin',
        minute  => '*/5',
        user    => root,
}
[root@nod2 puppet]# puppet apply cron.pp
notice: Finished catalog run in 0.04 seconds
[root@nod2 puppet]# crontab -l
# HEADER: This file was autogenerated at Fri Jun 12 16:19:29 +0800 2015 by puppet.
# HEADER: While it can still be managed manually, it is definitely not recommended.
# HEADER: Note particularly that the comments starting with 'Puppet Name' should
# HEADER: not be deleted, as doing so could cause duplicate cron jobs.
# Puppet Name: ntpdate
PATH=/bin:/usr/bin:/usr/sbin
*/5 * * * * ntpdate time.nist.gov

對資源類型的小結:

    puppet的資源類型有幾十種,根據版本的不同數量可能不同,但常用的資源類型會涉及到對用戶、組、文件、軟件包、服務這些資源的管理,可以用“puppet describe resoure_type”來查看其支持的參數,通過上邊對常用資源類型的介紹,發現每個資源類型裏都會有一個“ensure”參數,而根據資源類型的不同其取值也不盡相同。

4.2、資源類型中特殊參數

    資源類型中有幾個比較特殊的參數,叫元參數。元參數是用來定義資源間的相關性、依賴性,既然是參數,那元參數的也有值,它的值是其它資源或資源數組,這也稱爲資源引用。

資源引用有其固定的語法:“Type['title']”,資源類型的第一個字母必須大寫,“title”表示資源的名稱。

元參數有四個:before、require、notify和subscrible。

before  => Type['title']  :表示before所在資源必須執行完成後,Type['title']這個資源才能執行,即該資源先於Type['title']資源執行,例如:

[root@nod2 puppet]# vim user.pp 
group {'testuser':
    ensure  => present,
    gid     => 555,
    before  => User['testuser'],
}
user {'testuser':
    ensure   => present,
    gid      => 555,
    uid      => 555,
    home     => '/home/testuser',
    managehome => true,
    shell    => '/bin/bash',
}

#這裏就表示group這個資源必須執行完成後,“User['testuser']”這個資源才能執行。創建用戶時是需要先創建組,再創建用戶。

require  => Type['title'] :與before相對應,表示require所在的資源是依賴於"Type['title']"這個資源,必須等"Type['title']"這個資源執行完成後,require所在的資源才能執行,例如:

[root@nod2 puppet]# vim user.pp 
group {'testuser':
    ensure  => present,
    gid     => 555,
}
user {'testuser':
    ensure   => present,
    gid      => 555,
    uid      => 555,
    home     => '/home/testuser',
    managehome => true,
    shell    => '/bin/bash',
    require => Group['testuser'],
}

notify  => Type['title']:表示notify所在的資源發生變化後,就會通知“Type['title']”資源進行相應的操作,例如:

[root@nod2 puppet]# vim nginx.pp
package {'nginx':
    ensure => present,
    before => Service['nginx'],
}
service {'nginx':
    ensure => running,
    enable => true,
    path   => '/etc/rc.d/init.d/nginx',
    restart => 'reload',
}
file {'/etc/nginx/nginx.conf':
    ensure => file,
    source => '/root/nginx.conf',
    owner  => root,
    group  => root,
    mode   => 644,
    notify => Service['nginx'],
}

#這個manifest是進行nginx軟件包的安裝,軟件包安裝好後,如果想修改nginx.conf這個配置文件,那我們去修改“/root/nginx.conf”這個配置模板,修改好後,puppet就會在一定時間後去通知把"/root/nginx.conf"這個配置文件拷貝到“/etc/nginx/nginx.conf”進行覆蓋,然後再通知"Service['nginx']"去執行“/etc/rc.d/init.d/nginx reload”命令重新載入配置文件。

subscrible => Type['title']:與“notify => Type['title']”相對應,表示subscrible所在的資源依賴於“Type['title']”,它隨時關注着“Type['title']”這個資源,一旦“Type['title']”有事件發生,subscrible所在的資源就發生相應的動作,例如:

[root@nod2 puppet]# vim nginx.pp
package {'nginx':
    ensure => present,
    before => Service['nginx'],
}
service {'nginx':
    ensure => running,
    enable => true,
    path   => '/etc/rc.d/init.d/nginx',
    restart => '/etc/rc.d/init.d/nginx reload' ,
    subscrible => File['/etc/nginx/nginx.conf'],
}
file {'/etc/nginx/nginx.conf':
    ensure => file,
    source => '/root/nginx.conf',
    owner  => root,
    group  => root,
    mode   => 644,
}

除了用上before、require、notify和subscrible四個元參數來定義資源間的依賴、通知關係外,還可以用次序鏈、通知鏈來定義。

次序鏈用“->”表示,通知鏈用“~>”。例如:

[root@nod2 puppet]# vim nginx.pp
package {'nginx':
    ensure => present,
    before => Service['nginx'],
}
service {'nginx':
    ensure => running,
    enable => true,
    path   => '/etc/rc.d/init.d/nginx',
    restart => '/etc/rc.d/init.d/nginx reload',
}
file {'/etc/nginx/nginx.conf':
    ensure => file,
    source => '/root/nginx.conf',
    owner  => root,
    group  => root,
    mode   => 644,
}
Package['nginx'] -> File['/etc/nginx/nginx.conf'] ~> Service['nginx']

#最後定義的次序和通知鏈表示nginx安裝好後就去複製配置文件,配置文件準備好後就通知服務重新載入。

5、puppet的表達式與條件判斷語句

5.1、變量及變量類型

在puppet中使用變量有其獨特的要求:

a)、變量的賦值與引用都要在前加“$”號,賦值用“=”,支持追加賦值“+=”

b)、變量的引用格式:有簡短名和FQN($scope::variable)

puppet有如下三種變量類型:

a)、自定義變量

b)、facter變量,這些變量在manifest中可直接調用

c)、內置變量,分master端內置變量和agent端內置變量


5.2、puppet支持的數據類型

字符型:即字符串,爲了養成良好的編程習慣,使用單引號引起,也可不用;雙引號可以完成變量替換物。

數值型:可以爲整數或浮點數

數組型:格式爲“[元素,元素,....]”,元素可以爲任意可用數據類型,包括hash或其它數組,數組的引用索引從0開始,也可以使用負數索引引用。

布爾型:true和false,不能加引號

undef:從未被聲明的變量的值類型爲undef,即此變量值爲空,不加引號

hash:鍵值對數據,格式爲{key=>value,key=>value,.....},key爲字符型數據,value可以爲puppet支持的任意數據類型,引用是以key當索引使用

正則表達式:puppet的非標準數據類型,不能直接賦值給變量

注:在正則表達式中有三個選項,選項“i”表示忽略字符大小寫,選項“m”表示把“.”點號當作換行符,選項“x”表示忽略模式中的空間字符和註釋,而在puppet中正則有其特定的語法格式,以一個例子說明:

$package = $operatingsystem ? {
    /(?i-mx:ubuntu|debian)/   =>  'apache2',
    /(?i-mx:centos|fedora|redhat)/   => 'httpd',
}

#這個資源定義表示判斷“$operatingsystem”的值是apahce2還是httpd。

5.3、puppet支持的操作符號

a)、比較操作符

==:等值判斷

!=:不等值判斷

<:小於

>:大於

<=:小於等於

>=:大於等於

=~:正則匹配判斷

!~:正則不匹配判斷

in:表示在某一個列表中

b)、布爾操作符

and:且

or   :或

!     :非

c)、算術操作符號

+  :加

-  :減

*   :乘

/   :除

<<  :左移位

>>  :右移位


5.4、puppet的條件判斷語句

在puppet中有三種條件判斷語句,if,case,selector,在puppet3.0後增加了一個unless。

a)、if判斷語句

單分支

if  CONDITION {
    statement
     ...
}


雙分支

if CONDITION {
    statement
    ...
}
else {
    statement
    ...
}

多分支

if CONDITION {
    statement
    ....
}
elsif CONDITION {
    statement
    ...
}
... ...
else {
    statement
    ...
}

舉例:

if多分支舉例:

[root@nod2 puppet]# vim if.pp
if $operatingsystem == 'CentOS' {
    notice("hello CentOS.")
}
elsif $operatingsystem == 'RedHat' {
    notice("hello RedHat.")
}
elsif $operatingsystem == 'Fedora' {
    notice("hello Fedora.")
}
else {
    notice("who are you?")
}
[root@nod2 puppet]# puppet apply if.pp
notice: Scope(Class[main]): hello CentOS.
notice: Finished catalog run in 0.07 seconds

if中配置正則表達式舉例:

[root@nod2 puppet]# vim reg.pp
if $operatingsystem =~ /^(?i-mx:(centos|redhat))/ {
    notice("hello $1")
}
[root@nod2 puppet]# puppet apply reg.pp
notice: Scope(Class[main]): hello CentOS
notice: Finished catalog run in 0.07 seconds

b)、case判斷語句

語法:

case CONTROL_EXPRESS {
    case1,...: {    statement...   }
    case2,...: {    statement...   }
    ... ...
    default:   {   statement...   }
}

CONTROL_EXPRESS表示一個控制表達式,可以爲變量、表達式和一個有返回值的函數。

case可以爲一個特定的字符串、一個變量、一個有返回值的函數、一個正則表達式。

default表示默認分支

例如:

[root@nod2 puppet]# vim case.pp
case $operatingsystem {
    'CentOS','RedHat':  { notice("hello RedHAt OS Family") }
    /^(?i-mx:(Debian|Ubuntu))$/:{ notice("hello $1") }
    default:            { notice("who are you") }
}
[root@nod2 puppet]# puppet apply case.pp
notice: Scope(Class[main]): hello RedHAt OS Family
notice: Finished catalog run in 0.08 seconds

c)、selector判斷語句

只能用於期望出現直接值的地方,包括變量賦值、資源屬性、函數參數、資源標題等。

語法:

CONTROL_VARIABLE  ?  {
    case1  => value1,
    case2  => value2,
    ...
    default  => valueN,
}

注意:default必須要有,不然在編譯時會出錯

舉例:

[root@nod2 puppet]# vim selector.pp
$webpackage = $operatingsystem ? {
    /^(?i-mx:(centos|redhat|fedora))$/  => httpd,
    /^(?i-mx:(debian|ubuntu))$/         => apache2,
    default                             => httpd,
}
package {"$webpackage":
    ensure => installed,
}
[root@nod2 puppet]# puppet apply selector.pp
notice: /Stage[main]//Package[httpd]/ensure: created
notice: Finished catalog run in 8.99 seconds

6、puppet類

我給類下的一個定義:類就是把有相關性的,最直接的資源定義代碼整合在一起,以實現以“類”爲單位的管理,目的是實現代碼重用

6.1、類定義的語法:

class   clall_name  {
    ...puppet code...
}

#類的名稱只能由小寫字母開頭,可以包含小寫字母、數字和下劃線。

6.2、調用類的方法:

a)、include  class_name,class_name,常用此方法

b)、require,不常用

c)、class {'class_name':},像定義資源一樣來調用類

6.3、帶參數的類的定義:

語法:

class class_name ($para1='val1',$para2='val2',..) {
    puppet code
    ......
}

#($para1='val1',$para2='val2',..)中表示資源的默認值,即如果在調用類時沒有向其傳遞參數,那就默認參數。

例如:

class mysql ($user = 'mysql',$port = 3306) {
    ....puppet code....
}
class {'mysql':
    user => mysqluser,
}

例如:

[root@nod2 puppet]# vim class.pp 
class createuser ($gpname=test,$uname=test) {
        group {"$gpname":
                ensure => present,
        }
        user {"$uname":
                ensure => present,
                gid    => $gpname,
                home   => “/home/$uname”,
                managehome => true,
                shell  => '/bin/bash',
        }
}
class {'createuser':
        gpname => zcj,
        uname  => zcj,
}
[root@nod2 puppet]# puppet apply class.pp
notice: /Stage[main]/Createuser/Group[zcj]/ensure: created
notice: /Stage[main]/Createuser/User[zcj]/ensure: created
notice: Finished catalog run in 0.28 seconds
[root@nod2 puppet]# id zcj
uid=556(zcj) gid=556(zcj) groups=556(zcj)
[root@nod2 puppet]# ls /home/
testuser  zcj

6.4、類的繼承

語法:

class BASENAME {
    ...puppet code...
}

#上邊定義的這個類對下邊的類來說是一個基本類

class BASENAME::CLASSNAME inherits BASENAME {
    ...puppet code....
}

#這個類在第一個基本類的前提下再增加了一個類,即第二個類是繼承了第一個類的。第二個類中的“BASENAME”與第一個類中的“BASEDNAME”名稱相同,“CLASSNAME”是第二個類的名稱。

舉例:

[root@nod2 puppet]# vim nginx.pp
class nginx {
        package {'nginx':
                ensure => present,
                before => Service['nginx'],
        }
        service {'nginx':
                ensure => running,
                enable => true,
                path   => '/etc/rc.d/init.d/nginx',
                restart => '/etc/rc.d/init.d/nginx reload',
        }
}
class nginx::reloadnginx inherits nginx {
        file {'/etc/nginx/nginx.conf':
                ensure => file,
                source => '/root/nginx.conf',
                owner  => root,
                group  => root,
                mode   => 644,
        }
}
Package['nginx'] -> File['/etc/nginx/nginx.conf'] ~> Service['nginx']
#include nginx::reloadnginx
class {"nginx::reloadnginx":}

在類的繼承中有兩個問題要注意,如果在子類中定義了與父類相同的資源,那子類中定義的參數將會覆蓋父類中定義的參數;如果子類想在父類中已定義的資源上追加一些額外的參數或資源,那用“+>”符號。

舉例:

 [root@nod2 puppet]# vim nginx.pp
  1 class nginx {
  2         package {'nginx':
  3                 ensure => present,
  4                 before => Service['nginx'],
  5         }
  6         service {'nginx':
  7                 ensure => running,
  8                 enable => true,
  9                 path   => '/etc/rc.d/init.d/nginx',
 10                 restart => '/etc/rc.d/init.d/nginx reload',
 11         }
 12 }
 13 class nginx::reloadnginx inherits nginx {
 14         file {'/etc/nginx/nginx.conf':
 15                 ensure => file,
 16                 source => '/root/nginx.conf',
 17                 owner  => root,
 18                 group  => root,
 19                 mode   => 644,
 20         }
 21 }
 22 file {'/etc/nginx/conf.d/virtual.conf':
 23         ensure => file,
 24         source => '/tmp/virtual.conf',
 25 }
 26
 27 class nginx::reloadnginx::virtualhost inherits nginx::reloadnginx {
 28         File['/etc/nginx/nginx.conf'] {
 29                 require +> File['/etc/nginx/conf.d/virtual.conf'],
 30         }
 31 }
 32 Package['nginx'] -> File['/etc/nginx/nginx.conf'] ~> Service['nginx']
 33 #include nginx::reloadnginx
 34 class {"nginx::reloadnginx":}
#這個例子中定義多級繼承,仔細看27行,資源的追加請看29行。

7、puppet模塊

7.1、模塊的目錄結構及應用舉例

在puppet中模塊就是一個目錄名,此目錄下各個規劃好的子目錄,各個目錄存放的文件都有其規定。

模塊的目錄結構:

Module Name

        manifests

                init.pp

        files

        templates

        lib

        tests

        spec

manifests目錄:用於存放清單文件,即以“.pp”結尾的文件,ini.pp文件必須存在,且此文件必須聲明一個類,類名與模塊名相同。在puppet中manifests下的清單文件的訪問格式爲:“modulename::[subdirectoryname::]manifestfilename”,這裏的"subdirectoryname"是指在manifests目錄下所創建的子目錄名稱,“manifestfilename”是指清單文件名稱,但不要加上“.pp”後綴。

files目錄:用於存放各種靜態文件,訪問格式爲:puppet:///modules/MODULE_NAME/[SUBDIR_NAME/]FILE_NAME,這裏的“SUBDIR_NAME”表示在files目錄下自定義創建的目錄名稱。

templates目錄:存放manifests的模板文件,以“.erb”結尾,調用方式爲:template('ModuleName/TemplateName'),模板名一樣不需要加“.erb”後綴。

lib目錄:存放插件目錄

tests目錄:存放模塊使用說明文檔目錄

spec:存放lib目錄下插件的使用說明文檔

舉例:

[root@nod2 ~]# mkdir modules
[root@nod2 ~]# cd modules/
[root@nod2 modules]# mkdir -pv nginx/{manifests,files,templates,lib,tests,spec}
[root@nod2 modules]# vim nginx/manifests/init.pp
class nginx {
        package {'nginx':
                ensure => present,
        }
        file {'nginx.conf':
                ensure => file,
                path   => '/etc/nginx/nginx.conf',
                source => 'puppet:///modules/nginx/nginx.conf',
                owner  => root,
                group  => root,
                mode   => 644,
                require => Package['nginx'],
        }
        service {'nginx':
                ensure => running,
                enable => true,
                path   => '/etc/rc.d/init.d/nginx',
                subscribe => File['nginx.conf'],
        }
}

在files目錄中要準備好nginx.conf這個配置文件,我這裏從之前安裝過的nginx的配置文件複製過來

[root@nod2 modules]# cp /etc/nginx/nginx.conf nginx/files/

並把nginx.conf配置文件中的"worker_process = 1"修改爲“worker_process = 3”。

卸載之前安裝過的nginx:

[root@nod2 modules]# rpm -e nginx
warning: /etc/nginx/conf.d/virtual.conf saved as /etc/nginx/conf.d/virtual.conf.rpmsave
[root@nod2 modules]# rm -rf /etc/nginx/
[root@nod2 modules]# puppet apply -dv --modulepath=/root/modules -e "include nginx"

#“--modulepath=/root/modules”只指定模塊的上級目錄,“-e "include nginx"”表示調用的是nginx這個類

運行此命令後出現“notice: Finished catalog run in 26.26 seconds”類似的字樣表示運行成功

[root@nod2 modules]# ps aux | grep nginx
root      5697  0.0  0.4  96432  2084 ?        Ss   23:35   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx     5698  0.0  0.5  96780  2836 ?        S    23:35   0:00 nginx: worker process                  
nginx     5699  0.0  0.5  96780  2836 ?        S    23:35   0:00 nginx: worker process                  
nginx     5700  0.0  0.5  96780  2744 ?        S    23:35   0:00 nginx: worker process                  
root      5706  0.0  0.1 103236   860 pts/0    S+   23:35   0:00 grep nginx
#nginx啓用了三個worker進程。

上邊我們把模塊放在了“/root/modules”下,其實puppet的模塊有默認的存放位置,用以下命令可以查看:

[root@nod2 modules]# puppet agent --genconfig | grep modulepath
    modulepath = /etc/puppet/modules:/usr/share/puppet/modules

所以可以把我們自己開發的模塊放在此目錄下,在執行時就不需要加“--modulepath=/root/modules”參數

[root@nod2 modules]# mv /root/modules/nginx /etc/puppet/modules/

再去修改下files目錄下的nginx.conf,把"worker_process = 3"修改成“worker_process = 1”後再執行一下nginx類:

[root@nod2 modules]# puppet apply -dv -e "include nginx"
[root@nod2 modules]# ps aux | grep nginx
root      5893  0.0  0.4  96432  2088 ?        Ss   23:41   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx     5894  0.0  0.5  96780  2736 ?        S    23:41   0:00 nginx: worker process                  
root      5897  0.0  0.1 103236   856 pts/0    S+   23:41   0:00 grep nginx
#worker進程只有一個了。

再來做一個練習,編寫一個自動安裝mysql的模塊:

[root@nod2 modules]# pwd
/etc/puppet/modules
[root@nod2 modules]# ls
nginx
[root@nod2 modules]# mkdir -pv mysql{manifests,files,templates,lib,tests,spec}
[root@nod2 modules]# vim mysql/manifests/init.pp
class mysql {
        package {'mysql':
                ensure => present,
                name   => 'mysql-server',
                before => Service['mysqld'],
        }
        service {'mysqld':
                ensure  => true,
                enable  => true,
                require => Package['mysql'],
        }
        file {'my.cnf':
                ensure  => file,
                source  => 'puppet:///modules/mysql/my.cnf',
                path    => '/etc/my.cnf',
                require => Package['mysql'],
                notify  => Service['mysqld'],
        }
}

再提供一個my.cnf文件:

[root@nod2 modules]# cat  mysql/files/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
innodb_file_per_table = 1
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[root@nod2 modules]# puppet parser validate mysql/manifests/init.pp #測試manifest文件,如果有語法錯誤會報告
[root@nod2 modules]# puppet apply -dv -e "include mysql"  #安裝測試

當出現“notice: Finished catalog run in 0.39 seconds”這樣的類似字樣表示執行成功。

[root@nod2 modules]# ss -antl | grep 3306
LISTEN     0      50                        *:3306                     *:*    
#測試成功

7.2、站點清單的使用

在7.1中我們編寫了兩個模塊,一個是nginx,一個是mysql,如下:

[root@nod2 modules]# pwd
/etc/puppet/modules
[root@nod2 modules]# ls
mysql  nginx

思考:如果一個主機需要安裝mysql,又需要安裝nginx,那要怎樣操作?你會說執行兩次apply,分別聲明調用nginx類和mysql類就行了。不錯,這樣做是可以的,但如果主機需要安裝的軟件多達數十個,每個軟件都寫成了一個模塊,那你不是要手動執行數十次apply。顯然puppet不會讓我這麼做,這就是站點清單的作用。

默認時站點清單的路徑是“/etc/puppet/manifests/site.pp”,這個site.pp文件名是不能更改的,現在我們來定義這樣一個站點清單。

[root@nod2 puppet]# vim /etc/puppet/manifests/site.pp
node 'nod2.test.com' {
        include nginx
        include mysql
}

#node是關鍵字,表示定義一個站點清單,“nod2.test.com”這是我本地主機的主機名,大括號裏的內容就是我這個主機需要執行的類,注意後邊沒有“,”逗號。

[root@nod2 puppet]# puppet parser validate /etc/puppet/manifests/site.pp  #語法測試

把之前安裝的nginx,mysql統統卸載後,執行下站點清單看一下能否把nginx與mysql都安裝上:

卸載軟件過程略!

[root@nod2 puppet]# puppet apply -dv /etc/puppet/manifests/site.pp
[root@nod2 puppet]# ss -antl
State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port
LISTEN     0      128                       *:80                       *:*    
LISTEN     0      128                      :::22                      :::*    
LISTEN     0      128                       *:22                       *:*    
LISTEN     0      100                     ::1:25                      :::*    
LISTEN     0      100               127.0.0.1:25                       *:*    
LISTEN     0      50                        *:3306                     *:* 
#兩個服務已啓動

8、總結

     這是我在學習puppet時整理出的一些知識要點,通過對它的學習,也讓我認識到大規格的環境下使用這樣的自動化運維工具的必要性,它能讓管理人員從繁重且重複性的工作中解放出來,讓管理者有更多的精力關注技術。路漫漫其修遠兮,我也在不斷的學習與摸索,此文希望對想學習puppet的朋友有所幫助。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章