類是puppet中命名的代碼模塊,經常使用於定義一組通用目標的資源,可在puppet全局調用;
類能夠被繼承,也能夠包含子類;
具體定義的語法以下:html
class NAME{ ... puppet code ... }
其中,在咱們定義的時候,須要注意的是:node
下面,咱們來看一個簡單的例子:mysql
vim class1.pp class redis { #定義一個類 package{'redis': ensure => installed, } -> file{'/etc/redis.conf': ensure => file, source => '/root/manifests/file/redis.conf', owner => 'redis', group => 'root', mode => '0640', tag => 'redisconf' } ~> service{'redis': ensure => running, enable => true, hasrestart => true, hasstatus => true } } include redis #調用類
注意:類只有被調用纔會執行。include後能夠跟多個類,直接用","隔開便可。redis
咱們定義的類也能夠進行參數設置,能夠進行參數的傳遞。
具體語法以下所示:sql
class NAME(parameter1, parameter2) { #注意,大括號前有一個空格 ...puppet code... }
咱們來看一個例子:編程
vim class2.pp class instpkg($pkg) { package{"$pkg": ensure => installed, } } class{"instpkg": #給參數傳入值 pkg => 'memcached', }
注意:單個主機上不能被直接聲明兩次。
若是對應的參數未傳值的話,執行會報錯。
可是咱們能夠在定義形參的時候,設定一個默認值,這樣的話,咱們不傳入值的話,就會自動調用默認值:vim
vim class3.pp class instpkg($pkg='wget') { package{"$pkg": ensure => installed, } } include instpkg
這樣的話,咱們直接使用include
調用便可,就不須要給參數傳入值了。
由上,咱們能夠總結出,調用類的方式有兩種:服務器
1. include CLASS_NAME1, CLASS_NAME2, ... 2. class{'CLASS_NAME': attribute => value, }
咱們來看一個比較全面的例子:
首先,判斷咱們系統的版本,是6仍是7,由此來肯定,是安裝mysql
仍是mariadb
,同時,使用調用參數的方式來實現如上需求。
具體實現的代碼以下:架構
vim dbserver.pp class dbserver($dbpkg='mariadb-server',$svc='mariadb') { #定義類並給參數賦值 package{"$dbpkg": ensure => installed, } service{"$svc": ensure => running, enable => true, hasrestart => true, hasstatus => true, } } if $operatingsystem == 'CentOS' { if $operatingsystemmajrelease == '7' { include dbserver #直接調用類 } else { class{"dbserver": #調用類並對參數從新賦值 dbpkg => 'mysql-server', svc => 'mysqld' } } }
相似於其它編程語言中的類的功能,puppet 的Class 能夠被繼承,也能夠包含子類。
其定義的語法以下:app
class SUB_CLASS_NAME inherits PARENT_CLASS_NAME { ...puppet code... }
下面咱們來看一個例子:
vim class4.pp class redis { #定義class類 package{'redis': ensure => installed, } service{'redis': ensure => running, enable => true, } } class redis::master inherits redis { #調用父類 file {'/etc/redis.conf': ensure => file, source => '/root/manifests/file/redis-master.conf', owner => 'redis', group => 'root', } Service['redis'] { #定義依賴關係 subscribe => File['/etc/redis.conf'] } } class redis::slave inherits redis { #調用父類 file {'/etc/redis.conf': ensure => file, source => '/root/manifests/file/redis-slave.conf', owner => 'redis', group => 'root', } Service['redis'] { #定義依賴關係 subscribe => File['/etc/redis.conf'] } }
同樣的,咱們的類在調用的時候,能夠實現修改原有值和額外新增屬性的功能。
咱們的繼承父類的時候,能夠定義一些父類本來沒有的屬性:
在繼承的類中,咱們能夠在屬性原有值的基礎上,使用 +> 進行新增修改:
在繼承的類中,咱們能夠直接把原有的值進行覆蓋修改,使用 =>
進行覆蓋便可:
在繼承的類中,咱們還能夠在總體調用的基礎上,根據不一樣的需求,把父類中的部分值進行重寫修改:
模板一般以erb
結尾。模板均使用erb
語法。
關於puppet
兼容的erb
語法,咱們能夠去官方文檔查看,下面附上官方文檔地址:https://docs.puppet.com/puppet/latest/reference/lang_template_erb.html
如下,附上部分重要內容:
<%= EXPRESSION %> — 插入表達式的值,進行變量替換 <% CODE %> — 執行代碼,但不插入值 <%# COMMENT %> — 插入註釋 <%% or %%> — 插入%
接着咱們來看一個實例:
咱們使用puppet 模板來實現,將redis 監聽端口修改成本機的ip地址。
首先,咱們先來定義一個file.pp
文件,在該文件中調用咱們的模板:
vim file.pp file{'/tmp/redis.conf': #僅用於測試模板是否生效,因此放在tmp目錄下 ensure => file, content => template('/root/manifests/file/redis.conf.erb'), #調用模板文件 owner => 'redis', group => 'root', mode => '0640', }
接着,咱們去修改配置文件的源,也就是咱們的模板文件:
vim file/redis.conf.erb bind 127.0.0.1 <%= @ipaddress_eth0 %> #修改監聽端口
修改完成之後,咱們就能夠執行查看結果了:
puppet apply -v file.pp
而後,咱們去查看一下/tmp/redis.conf
文件:
vim /tmp/redis.conf
能夠看出,咱們的變量替換已經成功。
實踐中,通常須要把manifest 文件分解成易於理解的結構,例如將類文件、配置文件甚至包括後面將提到的模塊文件等分類存放,而且經過某種機制在必要時將它們整合起來。
這種機制即模塊,它有助於以結構化、層次化的方式使用puppet,而puppet 則基於「模塊自動裝載器」。
從另外一個角度來講,模塊實際上就是一個按約定的、預約義的結構存放了多個文件或子目錄的目錄,目錄裏的這些文件或子目錄必須遵循其命名規範。
模塊的目錄格式以下:
其中,每一個文件夾中存放的內容及其要求以下:
puppet:///modules/MODULE_NAME/FILE_NAME
;tempate('MOD_NAME/TEMPLATE_FILE_NAME')
; 下面咱們就來看一個實例來具體的瞭解應該如何定義一個模塊:
1)咱們先來建立對應的目錄格式:
[root@master ~]# mkdir modules [root@master ~]# cd modoules/ [root@master modules]# ls [root@master modules]# mkdir -pv redis/{manifests,files,templates,tests,lib,spec} mkdir: created directory ‘redis’ mkdir: created directory ‘redis/manifests’ mkdir: created directory ‘redis/files’ mkdir: created directory ‘redis/templates’ mkdir: created directory ‘redis/tests’ mkdir: created directory ‘redis/lib’ mkdir: created directory ‘redis/spec’
2)目錄格式建立完成以後,咱們就能夠來建立對應的父類子類文件了。
首先,咱們來建立父類文件:
[root@master modules]# cd redis/ [root@master redis]# vim manifests/init.pp class redis { package{'redis': ensure => installed, } -> service{'redis': ensure => running, enable => true, hasrestart => true, hasstatus => true, require => Package['redis'], } }
建立完成後,咱們再來建立對應的子類文件:
[root@master redis]# vim manifests/master.pp class redis::master inherits redis { file {'/etc/redis.conf': ensure => file, source => 'puppet:///modules/redis/redis-master.conf', owner => 'redis', group => 'root', mode => '0640', } Package['redis'] -> File['/etc/redis.conf'] ~> Service['redis'] } [root@master redis]# vim manifests/slave.pp class redis::slave($master_ip,$master_port='6379') inherits redis { file {'/etc/redis.conf': ensure => file, content => template('redis/redis-slave.conf.erb'), owner => 'redis', group => 'root', mode => '0640', } Package['redis'] -> File['/etc/redis.conf'] ~> Service['redis'] }
3)準備文件:
如今咱們須要把模板文件準備好,放入咱們的templates
目錄下:
scp redis.conf.erb /root/modules/redis/templates/redis-slave.conf.erb
還有咱們的靜態文件,也要放入咱們的files
目錄下:
scp redis.conf /root/modules/redis/files/redis-master.conf
4)查看目錄結構,肯定咱們是否都已準備完成:
[root@master modules]# tree . └── redis ├── files │ └── redis-master.conf ├── lib ├── manifests │ ├── init.pp │ ├── master.pp │ └── slave.pp ├── spec ├── templates │ └── redis-slave.conf.erb └── tests 7 directories, 5 files
5)如今就能夠把咱們的準備好的模塊放入系統的模塊目錄下:
[root@master mdoules]# cp -rp redis/ /etc/puppet/modules/
注意,模塊是不能直接被調用的,只有放在/etc/puppet/modules
下,或/usr/share/puppet/modules
目錄下,使其生效才能夠被調用。
咱們能夠來查看一下咱們的模塊到底有哪些:
[root@master mdoules]# puppet module list /etc/puppet/modules └── redis (???) /usr/share/puppet/modules (no modules installed)
能夠看出,咱們的模塊已經定義好了,如今咱們就能夠直接調用了。
6)調用模塊
咱們能夠直接命令行傳入參數來調用咱們準備好的模塊:
[root@master modules]# puppet apply -v --noop -e "class{'redis::slave': master_ip => '192.168.37.100'}" #若是有多個參數,直接以逗號隔開便可
也能夠把咱們的調用的類賦值在.pp
文件中,而後運行該文件。
[root@master ~]# cd manifests/ [root@master manifests]# vim redis2.pp class{'redis::slave': master_ip => '192.168.37.100', } [root@master manifests]# puppet apply -e --noop redis2.pp
以上。實驗完成。
注意,以上實驗是咱們在單機模式下進行的,若是是要在master/agent 模式下進行,步驟還會略有不一樣。
master/agent模型時經過主機名進行通訊的,下面,就來看看 master-agent 模式的puppet運維自動化如何實現:
1)下載包
master 端:puppet.noarch
,puppet-server.noarch
agent 端:puppet.noarch
2)主機名解析
爲了方便咱們後期的操做,咱們能夠經過定義/etc/hosts
文件實現主機名的解析。若是機器不少的話,可使用DNS進行解析。
[root@master ~]# vim /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.37.111 master.keer.com 192.168.37.122 server1.keer.com
注意,該操做須要在每一臺主機上進行。
修改完成之後,咱們能夠來測試一下是否已經成功:
[root@master ~]# ping server1.keer.com
3)時間同步
[root@master ~]# systemctl start chronyd.service
全部機器上都開啓chronyd.service
服務來進行時間同步
開啓事後能夠查看一下狀態:
[root@master ~]# systemctl status chronyd.service
咱們可使用chronyc sources
命令來查看時間源:
1)手動前臺開啓,觀察服務開啓過程:
puppet master -v --no-daemonize #前臺運行
2)直接systemctl
開啓服務,監聽在8140端口。
1)在配置文件中指明server端的主機名:
[root@server1 ~]# vim /etc/puppet/puppet.conf server = master.keer.com
接着,咱們能夠經過puppet config print
命令來打印輸出咱們配置的參數:
[root@server1 ~]# puppet config print 顯示配置文件中的配置參數 [root@server1 ~]# puppet config print --section=main 顯示main 段的配置參數 [root@server1 ~]# puppet config print --section=agent 顯示agent 段的配置參數 [root@server1 ~]# puppet config print server 顯示server 的配置參數
2)開啓 agent 服務
咱們能夠發現,他會一直卡在這裏等待CA頒發證書。
3)在 master 端簽署證書
[root@master ~]# puppet cert list "server1.keer.com" (SHA256) B5:67:51:30:5C:FB:45:BA:7A:73:D5:C5:87:D4:E3:1C:D7:02:BE:DD:CC:7A:E2:F0:28:34:87:86:EF:E7:1D:E4 [root@master ~]# puppet cert sign server1.keer.com #頒發證書 Notice: Signed certificate request for server1.keer.com Notice: Removing file Puppet::SSL::CertificateRequest server1.keer.com at '/var/lib/puppet/ssl/ca/requests/server1.keer.com.pem'
master 端管理證書部署的命令語法以下:
puppet cert <action> [–all|-a] [<host>]
action:
list 列出證書請求
sign 簽署證書
revoke 吊銷證書
clean 吊銷指定的客戶端的證書,並刪除與其相關的全部文件;
注意:某agent證書手工吊銷後從新生成一次;
On master host:
puppet cert revoke NODE_NAME
puppet cert clean NODE_NAME
On agent host:
從新生成的主機系統,直接啓動agent;
變換私鑰,建議先清理/var/lib/puppet/ssl/目錄下的文件
4)終止服務開啓,再次開啓
[root@server1 ~]# puppet agent -v --noop --no-daemonize
能夠看出咱們的服務開啓成功,可是因爲master 端沒有配置站點清單,因此沒有什麼動做。
1)設置站點清單
① 查詢站點清單應存放的目錄,(能夠修改,去配置文件修改)
[root@master ~]# puppet config print |grep manifest
[root@master ~]# cd /etc/puppet/manifests/ [root@master manifests]# vim site.pp node 'server1.along.com' { include redis::master }
分析:就是簡單的調用模塊,只有模塊提早定義好就能夠直接調用;我調用的是上邊的redis 模塊
2)給puppet 用戶受權
由於agent 端要來master 端讀取配置,身份是puppet
[root@master manifests]# chown -R puppet /etc/puppet/modules/redis/*
3)[root@server1 ~]# puppet agent -v --noop --no-daemonize 手動前臺開啓agent 端服務
(4)直接開啓服務,agent 會自動去master 端獲取配置
[root@server1 ~]# systemctl start puppetagent 包已下載,服務也開啓了
機器名稱 | IP配置 | 服務角色 |
---|---|---|
puppet-master | 192.168.37.111 | puppet的master |
puppet-server1-master-redis | 192.168.37.122 | puppet的agent,redis 的master |
puppet-server2-slave-redis | 192.168.37.133 | puppet的agent,redis 的slave |
1)下載包
master 端:puppet.noarch
,puppet-server.noarch
agent 端:puppet.noarch
2)主機名解析
爲了方便咱們後期的操做,咱們能夠經過定義/etc/hosts
文件實現主機名的解析。若是機器不少的話,可使用DNS進行解析。
[root@master ~]# vim /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.37.111 master.keer.com 192.168.37.122 server1.keer.com 192.168.37.133 server2.keer.com
注意,該操做須要在每一臺主機上進行。
修改完成之後,咱們能夠來測試一下是否已經成功:
[root@master ~]# ping server1.keer.com
3)時間同步
[root@master ~]# systemctl start chronyd.service
三臺機器上都開啓chronyd.service
服務來進行時間同步
開啓事後能夠查看一下狀態:
[root@master ~]# systemctl status chronyd.service
咱們可使用chronyc sources
命令來查看時間源:
(1)開啓服務
[root@master ~]# systemctl start puppetmaster [root@server1 ~]# systemctl start puppetagent [root@server2 ~]# systemctl start puppetagent
由於server2 是第一次鏈接,需master 端簽署證書
(2)master 簽署頒發證書
[root@master manifests]# puppet cert list [root@master ~]# puppet cert sign server2.keer.com
[root@master manifests]# cd /etc/puppet/manifests [root@master manifests]# vim site.pp 直接調上邊完成的模塊 node 'server1.keer.com' { include redis::master } node 'server2.keer.com' { class{'redis::slave': master_ip => 'server1.keer.com' } }
[root@server2 ~]# vim /etc/redis.conf
[root@server2 ~]# redis-cli -a keerya info Replication
(1) 建立一個 chrony 模塊,前準備
[root@master ~]# cd modules/ 進入模塊工做目錄 [root@master modules]# mkdir chrony 建立chrony 的模塊 [root@master modules]# mkdir chrony/{manifests,files} -pv 建立模塊結構
(2)配置chrony 模塊
[root@master modules]# cd chrony/ [root@master chrony]# cp /etc/chrony.conf files/ [root@master puppet]# vim files/chrony.conf # test #用於測試實驗結果
[root@master chrony]# vim manifests/init.pp class chrony { package{'chrony': ensure => installed } -> file{'/etc/chrony.conf': ensure => file, source => 'puppet:///modules/chrony.conf', owner => 'root', group => 'root', mode => '0644' } ~> service{'chronyd': ensure => running, enable => true, hasrestart => true, hasstatus => true } }
(3)puppet 添加這個模塊,並生效
[root@master modules]# cp -rp chrony/ /etc/puppet/modules/ [root@master modules]# puppet module list
[root@master ~]# cd /etc/puppet/manifests/ [root@master manifests]# vim site.pp node 'base' { include chrony } node 'server1.keer.com' inherits 'base' { include redis::master } node 'server2.keer.com' inherits 'base' { class{'redis::slave': master_ip => 'server1.keer.com' } } #node /cache[1-7]+\.keer\.com/ { #能夠用正則匹配多個服務器使用模塊 # include varnish #}
咱們如今直接去server2機器上,查看咱們的配置文件是否已經生效,是不是咱們添加過一行的內容:
[root@server2 ~]# vim /etc/chrony.conf
發現咱們的實驗成功。