一、相關概念
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插件存儲目錄用於實現自定義功能,一般很少用到