### 使用版本控制
> Unix was not designed to stop you from doing stupid things, because that would also stop you from doing clever things.
>
> — Doug Gwyn
你曾經遇到過誤刪除了某些文件而又希望恢復的情形吧? 本書中提及的最重要的技巧就是將 Puppet 的 配置清單(manifests)納入像 Git 或 Subversion 這樣的 **版本控制系統(Version Control System,VCS)**。 直接在 **Puppetmaster** 上編輯配置清單并非明智之舉,因為在你還沒確信應用這些更改之前可能已經被應用。 Puppet 會自動檢測配置清單的變化,因此可能會將配置清單的半成品應用到客戶端。 這可是個令人討厭的結果。
取而代之的正確做法是:使用 VCS (我推薦 Git)并從一個版本倉庫導出(checkout) Puppetmaster 上所需的 /etc/puppet 目錄內容。這樣做有如下好處:
* 你不用擔心 Puppet 會應用未完成的配置清單
* 你可以撤消更改,并將配置清單恢復到以前的任何版本
* 你可以使用分支(branch)來嘗試使用新功能,而不會影響到生產線上使用的主版本(master version)
* 如果多個人需要修改配置清單,他們可以彼此獨立的工作,修改他們自己的工作副本,之后合并(merge)他們的改動
* 你可以使用日志來查看何時,何人改動了什么
#### 準備工作
你需要一個運行 Puppetmaster 的主機并且配置清單文件集存放在 /etc/puppet 目錄。 如果你還沒有準備好這些,可以參考 Puppet 文檔([http://docs.puppetlabs.com/](http://docs.puppetlabs.com/)): 如何安裝 Puppet([http://docs.puppetlabs.com/guides/installation.html](http://docs.puppetlabs.com/guides/installation.html))以及如何建立自己的第一個配置清單 ([http://docs.puppetlabs.com/guides/setting_up.html](http://docs.puppetlabs.com/guides/setting_up.html))。
然后將你的配置清單納入版本控制,可以從 Pupppetmaster 上的 /etc/puppet 目錄導入到版本控制系統中, 并使用它作為工作副本。在本例中,我們將使用一個 **GitHub** 賬號存儲 Puppet 的所有配置。
你需要一個 GitHub 賬號(可以免費注冊)和并創建一個倉庫。跟隨 [www.github.com](http://www.github.com) 的指示去創建一個吧。
>  譯者注
> 可以參考 [蔣鑫](http://www.worldhello.net/) 撰寫的 [GotGitHub](http://www.worldhello.net/gotgithub/) 學習 GitHub 的使用。
> 
> 你可以使用你的賬號從 [http://www.PacktPub.com](http://www.PacktPub.com) 下載你購買的 Packt 出版的所有書籍的案例代碼文件。 如果你從其他地方購買了本書,你可以訪問 [http://www.PacktPub.com/support](http://www.PacktPub.com/support) , 注冊并直接從 e-mail 獲得案例代碼文件。
#### 操作步驟
1. 將 Puppetmaster 上的 /etc/puppet 目錄納入一個 Git 倉庫,執行如下命令:
```
root@cookbook:/etc/puppet# git init
Initialized empty Git repository in /etc/puppet/.git/
root@cookbook:/etc/puppet# git add manifests/ modules/
root@cookbook:/etc/puppet# git commit -m "initial commit"
[master (root-commit) c7a24cf] initial commit
59 files changed, 1790 insertions(+), 0 deletions(-)
create mode 100644 manifests/site.pp
create mode 100644 manifests/utils.pp
...
```
2. 關聯你的 GitHub 倉庫并執行推送(push):
```
# git push -u origin master
Counting objects: 91, done.
Compressing objects: 100% (69/69), done.
Writing objects: 100% (91/91), 21.07 KiB, done.
Total 91 (delta 4), reused 0 (delta 0)
To git@github.com:bitfield/puppet-demo.git
* [new branch] master -> master
```
分支 master 設置為從 origin 跟蹤遠程分支 masters。
#### 工作原理
你已經在 GitHub 上創建了一個 “master” **倉庫(repository)**(通常簡寫為 **repo**), 它包含了你的 Puppet 配置清單。 你可以在不同的地方導出多個副本,提交變更之前在這些副本上工作。 例如, 如果你有一個系統管理員的團隊,他們每個人都可以在他們自己的本地倉庫副本上工作。
Puppetmaster 上的 /etc/puppet 目錄僅是從屬于 GitHub 倉庫的另外一個工作副本。 當你決定要在 /etc/puppet 的工作副本上應用 GitHub 倉庫上的變更時, 你可以更新這個本地副本,從 GitHub 倉庫上獲取(pull)最近的變更。
#### 更多用法
既然已經配置了版本控制,你就可以使用如下的工作流程編輯你的 Puppet 配置清單了:
1. 使用自己偏愛的文本編輯器在你自己的工作副本上修改 Puppet 配置清單。
例如:在我的筆記本電腦上自己的工作副本上添加新的配置清單文件(或做一些編輯工作):
```
john@laptop:~$ cd puppet-work
john@laptop:~/puppet-work$ mkdir manifests
john@laptop:~/puppet-work$ touch manifests/nodes.pp
john@laptop:~/puppet-work$ git add manifests/nodes.pp
```
2. 提交(commit)變更并推送(push)變更至 GitHub 倉庫。
```
john@laptop:~/puppet-work$ git commit -m "adding nodes.pp"
[master 5c7b94c] adding nodes.pp
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 manifests/nodes.pp
john@laptop:~/puppet-work$ git push
Counting objects: 7, done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 409 bytes, done.
Total 4 (delta 1), reused 0 (delta 0)
To git@github.com:bitfield/puppet-demo.git
c7a24cf..b74d452 master -> master
```
3. 使用 git pull 從 Github 倉庫更新 Puppetmaster 上的工作副本。
```
root@cookbook:/etc/puppet# git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From git@github.com:bitfield/puppet-demo.git
26d668c..5c7b94c master -> origin/master
Updating 26d668c..5c7b94c
Fast-forward
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 manifests/nodes.pp
```
你可以使用像 **Rake** 這樣的工具實現這一過程的自動化。
#### 參見本書
* 本章的 [使用 Rake 部署變更](#ch01sec03) 一節
* 本章的 [創建去中心化的分布式 Puppet 架構](#ch01sec10) 一節
* 本章的 [使用提交鉤子](#ch01sec02) 一節
- Puppet 2.7 Cookbook 中文版
- 中文翻譯版
- 譯者序
- 項目緣起
- 翻譯方法
- 社區鏈接
- 社區建議
- 貢獻者
- 原書版權頁
- 關于作者
- 前言
- 本書內容
- 閱讀前提
- 適用讀者
- 格式約定
- 讀者反饋
- 客戶支持
- 下載案例代碼
- 勘誤表
- Puppet 基礎設施
- 使用版本控制
- 使用提交鉤子
- 使用 Rake 部署變更
- 配置 Puppet 的文件服務器
- 從 cron 運行 Puppet
- 使用自動簽名
- 預簽名證書
- 從 Puppet 的 filebucket 檢索文件
- 使用 Passenger 擴展 Puppet 的部署規模
- 創建去中心化的分布式 Puppet 架構
- 監控、報告和排錯
- 生成報告
- 通過 Email 發送包含特定標簽的日志信息
- 創建圖形化報告
- 自動生成 HTML 文檔
- 繪制依賴關系圖
- 測試你的 Puppet 配置清單
- 執行模擬運行
- 檢測編譯錯誤
- 理解 Puppet 的錯誤信息
- 顯示命令的輸出結果
- 輸出調試信息
- 檢查配置設置
- 使用標簽
- 使用運行階段
- 使用不同的環境
- Puppet 語言及其寫作風格
- 使用 Puppet 社區規范
- 使用模塊
- 使用標準的命名規范
- 使用嵌入式 Ruby 代碼
- 使用純 Ruby 代碼書寫配置清單
- 遍歷多個項目
- 書寫強大的條件語句
- 在 if 語句中使用正則表達式
- 使用選擇器和 case 語句
- 檢測字符串中是否包含指定的值
- 使用正則表達式替換
- 書寫更優質的配置清單
- 使用資源的數組
- 使用 define 資源
- 指定資源的依賴關系
- 使用節點繼承
- 使用類的繼承和重載
- 給類傳遞參數
- 書寫可重用的跨平臺配置清單
- 獲得系統的環境信息
- 導入動態信息
- 從 CSV 文件導入數據
- 給 Shell 命令傳遞參數
- 使用文件和軟件包
- 為配置文件添加配置行
- 使用 Augeas 自動修改配置文件
- 使用配置片段構建配置文件
- 使用 ERB 模板
- 在模板中遍歷數組
- 從第三方倉庫安裝軟件包
- 配置 APT 軟件倉庫
- 配置 GEM 倉庫
- 從源碼包自動構建軟件
- 比較軟件包的版本
- 用戶和虛擬資源
- 使用虛擬資源
- 使用虛擬資源管理用戶
- 管理用戶基于密鑰的 SSH 訪問
- 管理用戶的自定義文件
- 有效地分發 cron 任務
- 當文件更新時運行命令
- 使用主機資源
- 為文件資源指定多個源
- 使用文件資源遞歸地分發整個目錄樹
- 清理過期的舊文件
- 使用日程表資源
- 資源的審計
- 臨時禁用資源
- 管理時區
- 應用程序
- 管理 Apache 服務
- 創建 Apache 虛擬主機
- 創建 Nginx 虛擬主機
- 創建 MySQL 數據庫及用戶
- 管理 Drupal 站點
- 管理 Rails 應用程序
- 服務器和云基礎設施
- 部署 Nagios 監控服務器
- 使用 Heartbeat 構建高可用服務
- 管理 NFS 服務和文件共享
- 使用 HAProxy 為多個 web 服務器實現負載均衡
- 使用 iptables 管理防火墻
- 管理 Amazon 的 EC2 實例
- 使用 Vagrant 管理虛擬機
- 外部工具和 Puppet 生態環境
- 創建 Facter 的自定義 fact
- 在運行 Puppet 之前和之后執行命令
- 從 Shell 會話生成 Puppet 配置清單
- 從運行的系統上生成 Puppet 配置清單
- 使用 Puppet Dashboard
- 使用 Foreman
- 使用 MCollective
- 使用公共模塊
- 使用外部節點分類器
- 創建自定義的資源類型
- 創建自定義的提供者