puppet是一種Linux、Unix、windows平臺的集中配置管理系統,是目前運維主流的運維自動化工具,運維人員或者系統管理員可以通過使用 puppet 來處理所有的管理細節。
puppet使用自有的puppet描述語言(由於puppet是由ruby寫的,因此如ruby語法非常相近),可管理file(文件),user(用戶),group(組),package(軟件包),mount(掛載),schedule和cron(計劃任務),service(服務),tidy(清理),yumrepo(yum倉庫),sshkey(ssh認證)等常用資源。puppet把這些系統實體稱之爲資源,puppet的設計目標是簡化對這些資源的管理以及妥善處理資源間的依賴關係。
下面簡單記錄了關於puppet的安裝和配置的實踐過程,並進行了簡單的測試。
環境說明:
rhel6.5 selinuxand iptables disabled
node | ip | remark |
server1.example.com | 172.25.45.1 | puppet master |
server2.example.com | 172.25.45.2 | puppet agent |
server3.example.com | 172.25.45.3 | puppet agent |
注意:
1、主機名
Puppet 要求所有機器有完整的域名(FQDN),如果沒有 DNS 服務器提供域名的話,可以在兩臺機器上設置主機名。注意要先設置主機名再安裝Puppet,因爲 Puppet 是基於證書的,安裝Puppet 時會把主機名寫入證書,客戶端和服務端通信需要這個證書。
2、必須要有域名解析以及時間必須同步,不然會驗證失敗
軟件包說明:
需要依次安裝ruby、facter和puppet。(安裝facter和puppet時,要使用ruby install.rb。)
· Puppet是用ruby語言寫的,所以要安裝ruby環境,服務器端與客戶端都要安裝。可以用yum直接安裝,也可以精細化安裝(需要4個包)。
· 安裝puppet之前必須先安裝facter。facter是一個系統盤點工具,收集主的一些資料,比如CPU,主機IP等,它收集到值發送給puppet服務器端,服務器端就可以根據不同的條件來對不同的節點機器生成不同的puppet配置文件。
軟件包:
update/:
puppet-server-3.8.1-1.el6.noarch.rpm
puppet-3.8.1-1.el6.noarch.rpm
facter-2.4.4-1.el6.x86_64.rpm
hiera-1.3.4-1.el6.noarch.rpm
rubygem-json-1.5.5-3.el6.x86_64.rpm
ruby-shadow-2.2.0-2.el6.x86_64.rpm
ruby-augeas-0.4.1-3.el6.x86_64.rpm
rubygems-1.3.7-5.el6.noarch.rpm
這裏都放在update/目錄下
1.安裝puppet
【server1】
1 2 | cd update/ yum install -y puppet-server-3.8.1-1.el6.noarch.rpm puppet-3.8.1-1.el6.noarch.rpm facter-2.4.4-1.el6.x86_64.rpm hiera-1.3.4-1.el6.noarch.rpm rubygem-json-1.5.5-3.el6.x86_64.rpm ruby-shadow-2.2.0-2.el6.x86_64.rpm ruby-augeas-0.4.1-3.el6.x86_64.rpm rubygems-1.3.7-5.el6.noarch.rpm |
1 2 | touch /etc/puppet/manifest/site.pp ##site.pp文件是puppet讀取所有模塊pp文件的開始,在3.0版本以前必須設置,否則服務無法啓動。 /etc/init.d/puppetmaster start ##啓動服務,默認監聽8140端口 |
1 | ls /etc/puppet/ ##默認安裝目錄 |
【server2/server3】
1 2 | cd update/ yum install -y puppet-3.8.1-1.el6.noarch.rpm facter-2.4.4-1.el6.x86_64.rpm hiera-1.3.4-1.el6.noarch.rpm rubygem-json-1.5.5-3.el6.x86_64.rpm ruby-shadow-2.2.0-2.el6.x86_64.rpm ruby-augeas-0.4.1-3.el6.x86_64.rpm rubygems-1.3.7-5.el6.noarch.rpm |
1 | ls /etc/puppet/ |
##默認安裝目錄詳解##
/etc/puppet 配置目錄:
組織結構如下:
|-- puppet.conf #主配置文件,詳細內容可執行 puppet --genconfig
|-- fileserver.conf #文件服務器配置文件
|-- auth.conf #認證配置文件(ACL權限控制文件)
|-- autosign.conf #自動驗證配置文件
|-- tagmail.conf #郵件配置文件(將錯誤信息發送)
|-- manifests #文件存儲目錄(puppet 會先讀取該目錄的.PP 文件<site.pp>)
|--nodes
|puppetclient.pp
|-- site.pp #定義 puppet 相關的變量和默認配置。
|-- modules.pp #加載 class 類模塊文件(include syslog)
|-- modules #定義模塊
|-- syslog #以 syslog 爲例
|--file
|--manifests
|--init.pp #class 類配置
|--templates #模塊配置目錄
2.證書
【server1】
1 2 | puppet cert list ##顯示所有等待簽名的證書。此時無。 puppet cert list --all ##顯示所有簽名的證書。puppetmaster第一次啓動會自動生成證書自動註冊自己 |
【server2】
1 | puppet agent --server server1.example.com --no-daemonize -vt ##客戶端向服務器端申請證書 |
puppetd 從 server1.example.com 去讀取puppet配置文件。第一次連接,雙方會進行ssl證書的驗證。由於是新的客戶端,在服務器端那裏還沒有被認證,因此需要在服務器端進行證書認證。
參數--server 指定了需要連接的puppet master 的名字或是地址,默認連接名爲“puppet”的主機。(如要修改默認連接主機可以修改/etc/sysconfig/puppet 文件中的PUPPET_SERVER=puppet選項)
參數--no-daemonize 是 puppet客戶端運行在前臺
參數--verbose使客戶端輸出詳細的日誌
【server1】
1 | puppet cert list ##查看證書申請列表 |
1 2 3 | puppet cert sign server2.example.com ##簽名證書 #puppet cert sign --all ##同時簽名多份證書 puppet cert list --all |
【server2】
1 | puppet agent --server server1.example.com --no-daemonize -vt ##簽名成功 |
##自動註冊##
這種註冊方式簡單來講是通過Puppetmaster端的ACL列表進行控制的,安全系統較低,也就是說符合預先定義的ACL列表中的所有節點請求不需要確認都會被自動註冊上,也就是說你只需要知道ACL列表要求,其次能和PuppetMaster端通信便可輕易註冊成功。當然,它的最大優點就是效率非常高。
1 | vim /etc/puppet/puppet.conf |
在[main]下面加上autosign =true ##允許所有客戶端的認證
在/etc/puppet目錄下創建一個autosign.conf文件,內容如下:
*.example.com ##允許所有example.com域的主機
1 | /etc/init.d/puppetmaster reload ##重啓服務 |
1 | puppet agent --server server1.example.com --no-daemonize -vt ##在server3上 |
【server1】
1 | puppet cert list --all |
在實際中有時會修改client 端的主機名,這樣就需要重新生成證書。可以在服務器端先刪除原客戶端主機名的簽名證書,再在客戶端刪除/var/lib/puppet/ssl/目錄下所有文件,重新對服務器進行證書申請。
具體操作如下:
【server1】
1 | puppet cert clean server2.example.com ##刪除簽名證書 |
【server2】
1 2 | cd /var/lib/puppet/ssl/ rm -rf * |
1 | puppet agent --server server1.example.com --no-daemonize -vt ##由於配置文件,自動簽名證書 |
##預簽名註冊##
預簽名註冊是在agent端未提出申請的情況下,預先在puppetmaster端生成agent端的證書,然後複製到節點對應的目錄下即可註冊成功,這種方式安全係數最高,但是操作麻煩,需要提前預知所有節點服務器的certname名稱,其次需要將生成的證書逐步copy到所有節點上去。不過,如果你的系統中安裝了kickstart或者cobbler這樣的自動化工具,倒是可以將證書部分轉換成腳本集成到統一自動化部署中。(生產環境中更建議此方式)
3.puppet 資源定義
##創建文件##
方法一:
【server1】
1 | vim /etc/puppet/manifest/site.pp ##在沒有指定節點的情況下,對所有已經經過驗證的 client 都生效。 |
file {
'/tmp/testfile':
content=> 'www.westos.org',
mode=> 600,
owner=> puppet,
group=> puppet
}
【server2】
1 2 | puppet agent --server server1.example.com --no-daemonize -vt ll /tmp/testfile |
方法二:
【server1】
1 2 3 | cd /etc/puppet/ mkdir files cp /etc/passwd files/ |
1 | vim fileserver.conf |
在內容的最後加上以下內容:
[files]
path /etc/puppet/files
allow *.example.com
1 | /etc/init.d/puppetmaster reload |
1 | vim /etc/puppet/manifest/site.pp |
在之前內容的最後加上以下內容:
file {
'/tmp/passed':
source=> 'puppet:///files/passwd' ##要求文件從puppetmaster端服務器下載
}
【server2】
1 2 | puppet agent --server server1.example.com --no-daemonize -vt ll /tmp/passed |
##軟件包與服務定義##
【server1】
1 | vim /etc/puppet/manifests/site.pp |
在之前內容的最後加上以下內容:
package {
'httpd':
ensure=> present
}
service {
'httpd':
ensure=> running,
require=> Package['httpd']
}
【server2】
1 | rpm -q httpd |
1 2 3 | puppet agent --server server1.example.com --no-daemonize -vt rpm -q httpd /etc/init.d/httpd status |
##用戶定義##
【server1】
1 | vim /etc/puppet/manifests/site.pp |
在之前內容的最後加上以下內容:
user {
"test":
uid => 900,
home =>"/home/test",
shell =>"/bin/bash",
provider => useradd,
managehome => true,
ensure => present,
password => westos
}
【server2】
1 2 3 | puppet agent --server server1.example.com --no-daemonize -vt tail -n 3 /etc/passwd tail -n 3 /etc/shadow ##此時密碼是明文 |
##將密碼顯示加密##
【server1】
1 | vim /etc/puppet/manifests/site.pp |
註釋掉password => westos
在之前內容的最後加上以下內容:
exec {
'echo westos | passwd--stdin test':
path =>"/usr/bin:/bin",
onlyif => 'idtest'
}
【server2】
1 2 | puppet agent --server server1.example.com --no-daemonize -vt tail -n 3 /etc/shadow ##此時密碼是密文 |
##文件系統掛載##
【server1】
1 | vim /etc/puppet/manifests/site.pp |
將exec這一段內容都加上註釋
將package的內容改爲如下:
package {
['httpd','nfs-utils']:
ensure=> present
}
並在之前內容的最後加上以下內容:
file { "/public":
ensure => directory
}
mount { "/public":
device => "172.25.45.250:/mnt",
fstype => "nfs",
options => "defaults",
ensure =>mounted ##如果需要卸載,改爲absent
}
【物理機】
1 2 | systemctl status nfs systemctl start nfs |
【server2】
1 | puppet agent --server server1.example.com --no-daemonize -vt |
此時報錯不是因爲權限問題,修改之後依然報錯,通過一些技術帖,發現是因爲端口號的問題:
I googled and found that since the port is over 1024 Ineeded to add the "insecure" option to the relevant line in/etc/exports on the server. Once I did that (and ran exportfs -r), the mount -aon the client worked.
##如果端口號大於1024,則需要將 insecure 選項加入到配置文件(/etc/exports)相關選項中mount客戶端才能正常工作。
查看exports手冊中關於secure選項的說明
1 | <span style="font-size:16px;">man exports</span><br> |
##secure 選項要求mount客戶端請求源端口小於1024(然而在使用 NAT 網絡地址轉換時端口一般總是大於1024的),默認情況下是開啓這個選項的,如果要禁止這個選項,則使用 insecure 標識
所以解決方法要修改配置文件/etc/exports,加入 insecure 選項。
【物理機】
1 | vim /etc/exports |
加入以下內容:
/mnt *(insecure,rw,async,no_root_squash)
1 | systemctl restart nfs ##重啓服務 |
【server2】
1 | puppet agent --server server1.example.com --no-daemonize -vt |
1 |
1 | vim /etc/fstab |
## crontab 任務##
【server1】
1 | vim /etc/puppet/manifests/site.pp |
在之前內容的最後加上以下內容:
cron { echo:
command => "/bin/echo `/bin/date` >> /tmp/echo",
user => root,
hour => ['2-4'],
minute => '*/10'
}
【server2】
1 | puppet agent --server server1.example.com --no-daemonize -vt |
1 | /etc/init.d/crond status |
1 2 | cd /var/spool/cron/ ##任務會在該目錄下生成 cat root ##或crontab -l |
##不同節點的定義##
1 2 3 | mkdir nodes cp site.pp nodes/server2.pp cp site.pp nodes/server3.pp |
1 | vim site.pp |
將內容註釋掉,在最前面添上:import 'nodes/*.pp'
建立節點文件:
1 | cd nodes/ |
1 | vim server2.pp |
將內容修改爲如下:
node 'server2.example.com' {
package {
'httpd':
ensure => present
}
service {
'httpd':
ensure => running,
require => Package['httpd']
}
}
1 | vim server3.pp |
將內容改爲如下:
node 'server3.example.com' {
package {
'httpd':
ensure => present
}
service {
'httpd':
ensure => stopped,
require => Package['httpd']
}
}
【server2/server3】
1 | puppet agent --server server1.example.com --no-daemonize -vt |
1 | /etc/init.d/httpd status |
##模塊編寫##
【server1】
1 2 | cd /etc/puppet/modules/ mkdir vsftpd |
1 2 3 | cd vsftpd mkdir files yum install -y vsftpd |
1 2 3 4 5 | cd files/ cp /etc/vsftpd/vsftpd.conf . rpm -e vsftpd ll vsftpd.conf ##權限爲600 chmod 644 vsftpd.conf |
1 | vim vsftpd.conf |
將12行anonymous_enable的值改爲NO
1 | md5sum vsftpd.conf ##當anonymous_enable的值爲YES時,值不同 |
1 2 | cd .. touch install.pp config.pp service.pp init.pp |
1 | vim install.pp |
內容如下:
class vsftpd::install {
package{
'vsftpd':
ensure=> present
}
}
1 | vim config.pp |
內容如下:
class vsftpd::config {
file {
'/etc/vsftpd/vsftpd.conf':
source=> 'puppet:///modules/vsftpd/vsftpd.conf',
##實際路徑爲/etc/puppet/modules/vsftpd/files/vsftpd.conf
mode=> 600,
require=> Class['vsftpd::install'],
notify=> Class['vsftpd::service']
}
}
1 | vim service.pp |
內容如下:
class vsftpd::service {
service {
'vsftpd':
ensure=> running,
require=> Class['vsftpd::install','vsftpd::config']
}
}
1 | vim init.pp |
內容如下:
class vsftpd {
includevsftpd::install,vsftpd::config,vsftpd::service
}
1 | cd /etc/puppet/manifests/nodes |
1 | vim server2.pp |
在node 'server2.example.com' 的下面添上一行:includevsftpd
【server2】
1 | puppet agent --server server1.example.com --no-daemonize -vt |
報錯!
解決方法:在server1的/etc/puppet/modules/vsftpd下建立一個manifests目錄,將*.pp文件移到該目錄下。
【server1】
1 2 3 | cd /etc/puppet/modules/vsftpd mkdir manifests mv *.pp manifests/ |
可以看到該結構:
puppet目錄完整結構:
【server2】
1 | puppet agent --server server1.example.com --no-daemonize -vt |
【server3】
1 | time puppet agent --server server1.example.com --no-daemonize -vt |
4.模板應用(添加虛擬主機配置)##
文件存放在templates 目錄中,以*.erb 結尾。
【server1】
1 2 | cd /etc/puppet/modules/vsftpd/ mkdir templates |
1 2 3 4 | cd .. cp vsftpd/ httpd -r cd httpd/files/ yum isntall -y httpd |
1 2 | cp /etc/httpd/conf/httpd.conf . rm -rf httpd.conf |
1 2 | cd .. cd manifests/ |
將init.pp install.pp config.pp service.pp的vsftpd換成httpd
1 2 | vim init.pp ; vim install.pp ; vim config.pp ; vim service.pp :%s/vsftpd/httpd/g |
1 2 | cd /etc/puppet/manifests/nodes vim server2.pp |
修改內容如下:
node 'server2.example.com' {
include vsftpd,httpd
}
【server2】
1 | puppet agent --server server1.example.com --no-daemonize -vt |
【server1】
1 2 | cd /etc/puppet/modules/httpd/templates vim httpd_vhost.erb |
內容如下:
<VirtualHost *:80>
ServerName <%= domainname %>
DocumentRoot /var/www/<%= domainname %>
ErrorLog logs/<%= domainname %>_error.log
CustomLog logs/<%= domainname %>_access.log common
</VirtualHost>
1 2 | cd /etc/puppet/modules/httpd/manifests vim init.pp |
修改內容如下:
class httpd {
includehttpd::install,httpd::config,httpd::service
}
define httpd::vhost($domainname) {
file {"/etc/httpd/conf.d/${domainname}_vhost.conf":
content =>template("httpd/httpd_vhost.erb"),
require => Class["httpd::install"],
notify => Class["httpd::service"]
}
file { "/var/www/$domainname":
ensure => directory
}
file { "/var/www/$domainname/index.html":
content => $domainname
}
}
1 | vim config.pp |
將'/etc/httpd/httpd.conf'改爲/etc/httpd/conf/httpd.conf
1 2 | cd /etc/puppet/manifests/nodes vim server2.pp |
修改內容如下:
node 'server2.example.com' {
include vsftpd,httpd
httpd::vhost { 'www.example.com':
domainname => "www.example.com",
}
httpd::vhost { 'www.linux.org':
domainname => "www.linux.org",
}
}
1 2 | cd /etc/puppet/modules/httpd/files vim httpd.conf |
將990行 NameVirtualHost *:80 的註釋去掉
在最後面添上以下內容:
<VirtualHost *:80>
DocumentRoot /var/www/html
ServerName server2.example.com
</VirtualHost>
【server2】
1 2 | cd /var/www/html echo server2.example.com > index.html |
1 | puppet agent --server server1.example.com --no-daemonize -vt |
1 2 3 | cd /etc/httpd/conf.d/ ls cat www.example.com_vhost.conf |
1 | cat www.linux.org_vhost.conf |
【物理機】
1 | vim /etc/hosts |
在172.25.45.2的後面添上:www.example.com www.linux.org
http://server2.example.com/
http://www.example.com/
http://www.linux.org/
##錯誤總結##
1.再次啓動的時候報錯,puppetmaster沒有啓動
出現以下報錯:
出現此錯誤是因爲主節點puppetmaster服務沒有開
2.上面的掛載問題
可能是因爲端口號默認設置的問題,如上面方式解決即可。
3.在客戶端獲得證書後同步失敗
(1)時間同步問題 檢查master和client之前時間是否不一樣
(2)/etc/resolv.conf裏面有search localdomain