運維自動化管理工具之Puppet

一、相關概念

1、puppet是什麼?

a、開源的集中式配置管理工具。通過自有配置語言對節點進行目標狀態定義,並能夠基於網絡實現目標狀態的維護。

b、採用C/S架構即master和agent,master作爲中心配置庫,agent用來讀取並應用配置的節點。

c、puppet定義目標狀態的核心組件:"資源",

d、發行版本: 0.24,0.25,2.6,2.7(巨大變化),3.x(基於2.7爲原型) 

e、管理目標:衆多linux發行版本,windows等幾乎所有操作系統。


2、puppet認證方式是什麼?

        puppet的master與agent是基於ssl認證,而證書的頒佈依賴於使用主機的主機名。(好處:ip變了,主機名沒變那麼證書還依然能用),因此master需要可以解析所有agent的主機名。


3、master與agent是怎麼通訊的?

通訊基於https的XMLRPC協議進行的,master不會主動發起對agent的請求,而是客戶端每個固定時長(默認半個小時)去服務器端查找是否有關於本節點的配置信息,如果有master就將配置模板發給agent,然後agent讀到後,就根據模板進行操作了。


4、puppet的工作原理(重點理解部分):

        宏觀理解工作原理:要想使某臺主機到達某目標狀態需要每隔一段時間去master查找配置文件,這個配置文件定義了需要安裝哪些模塊,而模塊組織了所有的依賴關係,agent拿到配置需求進行執行,然後將結果返回給master,master將結果保存到databases中,這些結果可以用通過puppet dashboard或foreman來進行展示。


微觀:define -> 模擬 -> 強制 -> REPORT, 即(define) 在master端定義了資源信息 (模擬)agent讀到這些信息後不會立即執行而是先模擬執行一次,如果成功,(強制)則執行這些變更,最後(report)報告自己的工作狀態。


master與agent信息交互細節:agent通過factor將執行結果(主機名,ip等)發給master,master會根據agent的情況來選擇一些清單manifest然後,將其進行編譯成僞代碼catalog,然後交給agent,agent在進行上邊所述的"模擬"->"報告"的工作。


二、puppet安裝

#puppet(2.7比較流行的穩定版本)

1、下載地址:

https://yum.puppetlabs.com/el/6.5/products/x86_64/puppet-2.7.25-1.el6.noarch.rpm
https://yum.puppetlabs.com/el/6.5/products/x86_64/facter-1.7.6-1.el6.x86_64.rpm

2、使用模型:

a、單機使用
安裝puppet
b、master/agent
master:puppet,puppet-server
agent:puppet

3、安裝:

安裝部分比較簡單,也不是本文介紹的重點所以這裏就不多介紹了,我這裏採用rpm安裝。

rpm -ivh xxxx.rpm


三、puppet詳解

1、定義資源:

資源是以.pp結尾的。

格式:

type {"title":
v1 => k1,
v2 => k2,
}

說明:

1、在定義資源時候,資源類型必須使用字符串;

 2、同一個類型中其必須唯一   比如:package app1 與 service app1可以,都是package則不行。

[root@l-mem-test2 tmp]# cat test.pp
notify{'notice':
message => 'welcome to puppet.',
}
[root@l-mem-test2 tmp]# puppet apply test.pp    ## 應用這個puppet
notice: welcome to puppet.
notice: /Stage[main]//Notify[notice]/message: defined 'message' as 'welcome to puppet.'
notice: Finished catalog run in 0.02 seconds
[root@l-mem-test2 tmp]# puppet apply test.pp -v    ## 詳細的信息 包括版本號
info: Applying configuration version '1483548877'
notice: welcome to puppet.
notice: /Stage[main]//Notify[notice]/message: defined 'message' as 'welcome to puppet.'
notice: Finished catalog run in 0.05 seconds
[root@l-mem-test2 tmp]# puppet apply test.pp -v     ## 你會發現及時沒變更版本號也會變更
info: Applying configuration version '1483548887'
notice: welcome to puppet.
notice: /Stage[main]//Notify[notice]/message: defined 'message' as 'welcome to puppet.'
notice: Finished catalog run in 0.05 seconds


2、核心資源:notify、package、user、group、file、exec,cron、service


notify通知,用於調試輸出:

常用參數:

message:要輸出什麼信息

name:名稱


package(管理軟件包):

常用屬性:

ensure:程序包的目標狀態;

name:資源的名稱,即軟件包的名字;

provider:軟件包管理器(yum,rpm,apt,ports,gem,msi,dpkg,pkg)

source:指定程序包文件路徑

install_options:指定安裝選項 最常用的通過INSTALLDIR來指定安裝目錄


例如windows下安裝mysql

package {'mysql':

ensure   => installed,

provider => 'msi',

source   => 'D:\software\mysql-5.5.36.msi',

install_options => {'INSTALLDIR' => 'C:\mysql'},

}


service(管理服務):

常用屬性:

ensure:服務目標狀態,true和false

enable:是否開機自啓動,true和false

name:服務名稱

path:服務腳本路徑(如果不寫默認到/etc/init.d/找name相同的腳本);

start:訂製啓動命令

stop:停止命令

restart:訂製重啓命令

status:狀態信息獲取命令


file(管理文件、目錄、符號連接、生成文件內容、管理文件權限、管理文件屬性、通過source屬性到制定位置下載文件、通過recurse屬性來獲取整個目錄)

常用屬性:

ensure:目標狀態present,absent,file,directory

backup:通過filebucket資源來備份文件;對應值通常問filebucket資源名稱;

content:文件內容,生成方式有三種(content,source,target),這三種互斥僅能使用一種;

source:通過指定的url下載文件至本地;獲取方式通常爲puppet url,格式puppet:///modules/MODULES_NAME/file_names;

target:爲符號鏈接指定目標;

links:文件爲符號鏈接(follow|manage);

path:文件路徑,注意必須使用雙引號;

mode:定義權限;

owner:屬主;

group:屬組;

force:強制執行刪除文件、連接、或目錄,因此該屬性僅用於ensure爲absent時;

purge:清空指定目錄中存在,但未在資源中定義的文件;

recurse:用於目錄遞歸,值true,false,inf,remote

replace:替換;如果本地存在的文件與資源中指定的文件內容不同時是否執行替換,默認爲否;

#####示例:

[root@l-mem-test2 tmp]# cat test3.pp
file {'abc4.txt':
    ensure  => present,
    content => "hello puppet",
    path    => "/tmp/abc4.txt",
}
file {'fstab.symbolic':
    ensure  => present,
    target  => "/etc/fstab",
    path    => "/tmp/fstab.symbolic",
    links  => follow,
}
[root@l-mem-test2 tmp]# ls -l |grep fstab
lrwxrwxrwx. 1 root root   10 1月   5 18:27 fstab.symbolic -> /etc/fstab


exec(執行命令,通常在不得不用時才使用,通常用於完成puppet自身無法完成的功能):

常用屬性:

command:要執行的命令,通常爲命令的完成路徑;

path:命令搜索路徑;

group:以誰爲屬主執行;

user:以誰爲屬主執行;

onlyif:0,表示僅在命令狀態返回值爲0時才執行此命令;

refresh:接收到其他資源的通知時,重新執行此命令;

refreshonly:僅當被以來的資源發生改變時,才被觸發;

tries:嘗試次數,默認爲1;

try_sleep;嘗試次數大於1時的時間間隔;


####示例:

[root@l-mem-test2 tmp]# cat test4.pp
exec {'echo command':
    command => 'touch /tmp/tmp.xxx',
    path    => '/bin:/sbin:/usr/bin:/usr/sbin'
}
[root@l-mem-test2 tmp]# puppet apply test4.pp
notice: /Stage[main]//Exec[echo command]/returns: executed successfully
notice: Finished catalog run in 0.09 seconds
[root@l-mem-test2 tmp]# ls |grep tmp
tmp.xxx


group管理系統上的用戶組:

常用屬性:

ensure:目標狀態 present,absent

name:組名

gid:GID

system:系統組

###示例:

[root@l-mem-test2 tmp]# cat group.pp
group {'testgrp':
    ensure => present,
    gid    => 1001,
}
[root@l-mem-test2 tmp]# puppet apply group.pp
notice: /Stage[main]//Group[testgrp]/ensure: created
notice: Finished catalog run in 0.53 seconds
[root@l-mem-test2 tmp]# tail /etc/group|grep test
testgrp:x:1001:


user管理用戶:

常用屬性:

ensure:目標狀態

uid:UID

name:用戶名

system:是不是系統用戶

home:家目錄

shell:

gid:用戶組id

password:密碼(要是用加密後的密碼串)

managehome:是否創建家目錄 ture,false


###示例:

user {'testuser':
    ensure  => present,
    gid     => 1001,
    uid     => 1001,
    home    => '/home/test',
    shell   => '/bin/tcsh',
    password => '$1$25fb0f71$M3Ny.rWQjSy.mOcONDEO9.',
    managehome => true,
}


cron定義週期性任務:

常用屬性:

ensure:目標狀態present absent

command:命令或腳本

environment:運行時的環境變量

hour

minute

month

monthday

weekday

name:名字

user:運行時的用戶身份(默認爲root)

###示例:

[root@l-mem-test2 tmp]# cat cron.pp
cron {'ntpdate':
    ensure => present,
    command => '/usr/sbin/ntpdate time.nist.gov',
    minute => '*/3',### 每三分鐘,只定義分鐘,其他可以省略
}
[root@l-mem-test2 tmp]# crontab -l
# HEADER: This file was autogenerated at Fri Jan 06 00:15:11 +0800 2017 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
*/3 * * * * /usr/sbin/ntpdate time.nist.gov


3、元參數與資源引用

資源引用:
Type['title']  #type開通字母大寫
例如:
Package['httpd']


屬性中的特殊屬性

1、name(都有,一般不寫調用title)

2、ensure

3、元參數

用於定於資源間的依賴關係,及應用次序,通知機制;

require:
package {'nginx':
ensure => present,
}
service {'nginx':
ensure => true,
enable => true,
require => Package['nginx'],   ### 表示該服務依賴 package
}
## 另一種寫法:
before
package {'nginx':
ensure => present,
before => Service['nginx']
}
service {'nginx':
ensure => true,
enable => true,
}



notify,subscribe 通知與訂閱 同require和before一個意思 一個寫在前面一個寫在後面

[root@l-mem-test2 tmp]# cat test5.pp
file {'/tmp/tt.txt':
    ensure => present,
    content => "hello",
}
exec {'monitor':
    command => 'echo "/tmp/tt.txt changed">>/tmp/monitor.txt',
    subscribe => File['/tmp/tt.txt'],### 訂閱了資源
    refreshonly => true,## 檢查文件改變時重新執行
    path     => "/bin:/sbin:/usr/bin:/use/sbin/",## 給echo定義path路徑
}


資源間的應用次序鏈

"->"用於定義次序鏈,而"~>"用於定於通知鏈

例如:nginx先安裝軟件包在操作nginx配置文件,當nginx配置文件改變時通知service服務啓動

package{"nginx":ensure => present,} -> 
file {'nginx.conf': ensure => present,} ~> 
service {'nginx':
ensure => running,
enable => true,
}


4、puppet變量

a、puppet變量:

(1)、名稱必須以“$”開頭,賦值操作符爲“=”

(2)、任何正常數據類型(非正則)的值都可以賦予puppet中的變量,如字符串、數值、布爾值、數組、hash以及特殊的undef值(即變量未被賦值)

(3)、puppet的每個變量都有2個名字,簡短名稱和長格式完全限定名稱(FQN),完全限定名稱格式爲“$scope::variable”


b、puppet分爲哪幾種?

(1)、自定義變量

(2)、facter變量

(3)、內置變量:

agent:$environment、$clientcert、$clientversion

master:$serverip,$serverversion,$servername


c、puppet變量的數據類型:

1、字符型

非結構化的文本字符串,可以使用雙引號,也可以不用;

單引號中的變量不會被替換,而雙引號中的能夠替換變量

字符型值也支持使用轉移符 例如“\n”

2、數值型

可爲整數或浮點數,不過puppet只有在數值上下文才能把數值當數值型對待,其他情況一律以字符串處理

3、數組

數組值爲中括號"[]"中的以逗號分隔的項目列表,最後一個項目後面可以有逗號

數組中的元素可以爲任意可用數據類型,包含hash或其他數組

數組索引爲從0開始的整數,也可以使用負數索引。

4、布爾型

true和false,不能加引號

if語句的測試條件和比較表達式都會返回布爾型值

另外其他數據類型也可自動轉換爲布爾型,如空字符串爲false等。

5、undef

未被聲明的變量的值類型undef

也可以手動爲某變量賦予undef,即直接使用不加引號的undef字符串。

6、hash

即爲外鍵值數據類型,建和值之間使用“=>”分隔,建值對兒定義在“{}”中,彼此間以逗號分隔

其建爲字符型數據,而值可以爲puppet支持的任意數據類型

訪問hash類型的數據元素要使用“鍵”當做索引進行

7、正則表達式

屬於puppet的非標準數據類型,不能複製給變量,僅能用於有限的幾個接受正則表達式的地方,即接受使用“=~”及“!~”匹配操作符的位置,通常包括case語句中的selector,以及節點名稱匹配的位置;

它們不能傳遞給函數或用於資源屬性的定義;

puppet中的正則表達式支持使用(?<ENABLED OPTION>:<SUBPATTERN)和(?-<DISENABLED OPTION>:<SUBPATTERN)2個特殊符號

例如下面的實例表示做正則表達式匹配時已用選項“i”(忽略字符大小寫),但不支持使用"m"(把.當做換行符)和"x"(忽略模式中的空白字符和註釋)

$packages = $operatingsystem ? {

/(?i-mx:ubuntu|debian)/=> 'apache2',   ### ?固定格式,i啓動忽略大小寫,禁用吧.當做換行符,啓用忽略模式中的空白字符和註釋

/(?i-mx:centos|fedora|redhat)/ => 'httpd',

}


###示例:自定義變量

[root@l-mem-test2 tmp]# cat test7.pp
$pkgname='haproxy'
package {$pkgname:## 注意:title可不用引號,或使用雙引號,不能使用單引號
    ensure => present,
}
[root@l-mem-test2 tmp]# rpm -q haproxy
package haproxy is not installed
[root@l-mem-test2 tmp]# puppet apply test7.pp  -v
info: Applying configuration version '1483605620'
notice: /Stage[main]//Package[haproxy]/ensure: created
notice: Finished catalog run in 7.32 seconds
[root@l-mem-test2 tmp]# rpm -q haproxy
haproxy-1.5.4-3.el6.x86_64

例子factor變量:

[root@l-mem-test2 tmp]# cat test8.pp
file {'/tmp/issue.test':
    ensure  => file,
    content => $operatingsystem,
}
[root@l-mem-test2 tmp]# cat issue.test
CentOS


5、常見的變量操作符

常用操作符:

比較操作符
== 等於
!= 不等於
<
>
<=
>=
=~ 正則匹配
!~ 不匹配
in 是否存在某個集合中
布爾操作符
and 
or
!
運算操作符
+
-
*
/
<< 左移位
>> 右移位


6、puppet的條件表達式

(1、)if語句

單分之
if 1>3 {
}
       雙分之
if 1>2{
}
else{
}
多分支
if 1>2{
}elsif 1>3{
}else{
}

if的條件

變量:有值爲真,無值爲假, 未定義變量也爲假

表達式: 大於、小於、等於、不等於 可以嵌套

函數:支持函數

###示例1:

[root@l-mem-test2 tmp]# cat test10.pp
if $operatingsystem =~ /^(?i-mx:(centos|redhat|fedora))/{
    notice ("Welcome to $1 system.")
}
[root@l-mem-test2 tmp]# puppet apply test10.pp
notice: Scope(Class[main]): Welcome to CentOS system.
notice: Finished catalog run in 0.02 seconds

###示例2:

[root@l-mem-test2 tmp]# cat test11.pp
if $operatingsystem == 'CentOS'{
    notify {'centos':message => "welcome to CentOS system.",}
}elsif $operatingsystem == 'RedHat'{
    notify {'redhat':message => "welcome to RedHat system.",}
}else{
    notify {'other':message => "welcome to the system",}
}

(2)、case語句(匹配第一個滿足的執行就結束)

語法:

case CONTORL_EXPRESS{
case2:{xx}
case1,case4: {xxx}
case2,case5:{xxx}
/^(Debian|Ubuntu)$/:{notice{"welcome to $1 system"}}  ## 可基於正則匹配,用引用$1
default:{xxx}
}

case語句的條件

可是一個值

可以是變量

可以使表達式

可以使函數



(3)、selectors語句

 跟case語句很像,但區別是case直接返回一個動作,而selectors返回一個值

語法:

CONTORL_VARIABLE ? {
case1 => value1
case2 => value2
...
defalut => valueN
}

###示例:

[root@l-mem-test2 tmp]# cat test12.pp
$webserver = $operatingsystem ? {
    /^(?i-mx:centos|fedora|redhat)/ => 'httpd',
    /^(?i-mx:ubutu|debian)/ => 'apache',
}
$webprovider = $operatingsystem ? {
    /^(?i-mx:centos|fedora|redhat)/ => 'yum',
    /^(?i-mx:ubutu|debian)/ => 'apt',
}
package {"$webserver":
    ensure => present,
    provider => $webprovider,
}
上邊的例子表示 $operationgsystem匹配如果是 ubuntu或者是debian那麼 值是apache2,最後再將apache2賦值給$webserver


7、puppet的類class

(1)、概述:puppet類(爲了通用目的或目標組織在一起的一個或多個資源;只有調用才能執行,聲明才能被使用),使用 include CLASS_NAME 或者 class {'CLASS_NAME':}就可以調用了。

###示例1:

[root@l-mem-test2 tmp]# cat test13.pp
class nginx {
    package {'httpd':
        ensure => present,
    }
    service {'httpd':
        ensure => true,
        require => Package['httpd'],
    }
}
# 常用的兩種方式
#include nginx              # 第一種聲明方式
class {'nginx':}            # 第二種聲明方式
[root@l-mem-test2 tmp]# puppet apply test13.pp
notice: /Stage[main]/Nginx/Package[httpd]/ensure: created
notice: /Stage[main]/Nginx/Service[httpd]/ensure: ensure changed 'stopped' to 'running'
notice: Finished catalog run in 10.06 seconds


(2)、帶參數的類:

格式:

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


###示例:

class myql ($user = 'mysql',$port = 3306){
...
}
class {'mysql':
user = mysqlserver,     #給user賦值,不給port賦值則使用默認值3306
}


###示例:

[root@l-mem-test2 tmp]# cat test14.pp
$webserver = $operatingsystem ?{
    /^(?i-mx:redhat|centos|fedora)/ => "httpd",
    /^(?i-mx:ubuntu|debian)/ => "apache2",
}
class httpd ($pkgname = 'apache2'){
    package {"$pkgname":
        ensure => present,
    }
    service {"$pkgname":
        ensure => true,
        require => Package["$pkgname"],
    }
}
class {"httpd":
    pkgname => $webserver,
}
執行:
[root@l-mem-test2 tmp]# puppet apply test14.pp -v
info: Applying configuration version '1483693735'
notice: /Stage[main]/Httpd/Package[httpd]/ensure: created
notice: /Stage[main]/Httpd/Service[httpd]/ensure: ensure changed 'stopped' to 'running'
notice: Finished catalog run in 10.27 seconds
[root@l-mem-test2 tmp]# rpm -q httpd
httpd-2.2.15-55.el6.centos.2.x86_64
[root@l-mem-test2 tmp]# netstat -lntup|grep 80
tcp        0      0 :::80                       :::*                        LISTEN      23133/httpd


(3)、類的繼承及清單的導入:

class C_NAME inherits PARENG_CALSS_NAME{
}

子類的命名方式:nginx::rproxy#父類::子類

基類:安裝nginx

子類1:提供web配置的配置文件

子類2:提供反向代理的配置文件

###示例:

[root@l-mem-test2 tmp]# cat test15.pp
class httpd {                 ### 定義基類
    package {"httpd":
        ensure => present,
    }
}
class httpd::rproxy inherits httpd{              ## 定義子類 httpd::rproxy inherits 父類 #固定格式
    file {'/tmp/qw.conf':
        ensure => file,
        source => "/tmp/xxx.conf",
        notify => Service['httpd'],
    }
    service {'httpd':
        ensure => true,
    }
}
class httpd::web inherits httpd{
    file {'/tmp/qw.conf':
        ensure => file,
        source => "/tmp/xxxweb.conf",
        notify => Service['httpd'],
    }
    service {'httpd':
        ensure => true,
    }
}

清單的導入:

[root@l-mem-test2 tmp]# cat node.pp
import "/tmp/test15.pp"                   ## 導入清單
include httpd::rproxy                     ## 聲明

------ 執行

[root@l-mem-test2 tmp]# puppet apply node.pp -v
info: Applying configuration version '1483695028'
info: FileBucket adding {md5}2cb3f4eea6c0334eb8bca787e704622b
info: /Stage[main]/Httpd::Rproxy/File[/tmp/qw.conf]: Filebucketed /tmp/qw.conf to puppet with sum 2cb3f4eea6c0334eb8bca787e704622b
notice: /Stage[main]/Httpd::Rproxy/File[/tmp/qw.conf]/content: content changed '{md5}2cb3f4eea6c0334eb8bca787e704622b' to '{md5}6de9439834c9147569741d3c9c9fc010'
info: /Stage[main]/Httpd::Rproxy/File[/tmp/qw.conf]: Scheduling refresh of Service[httpd]
notice: /Stage[main]/Httpd::Rproxy/Service[httpd]: Triggered 'refresh' from 1 events
notice: Finished catalog run in 0.61 seconds
[root@l-mem-test2 tmp]# cat qw.conf
xxx


8、模塊

爲了實現某種完備功能而組織成一個獨立的,自我包含的目錄結構:模塊

總結:模塊是目錄結構,目錄名稱即爲模塊名

注意:模塊名稱以小寫字母開頭,但不能使用main或settings作爲模塊名。

目錄結構:

/tmp/modules/
    nginx/
    files/           :文件存儲目錄
        nginx.conf
    manifests/:清單存儲目錄
        init.pp         #必須有的 必須包含且只能包含與模塊同名的類
        nginx.pp     # 每個清單通常只包含一個類,其他清單不能包含模塊名的類
        ...
    templates/       :模板存放目錄
        *.erb
    lib/:ruby插件存儲目錄用於實現自定義功能,一般很少用到


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