最佳實踐

這裡有些給使用和編寫 Ansible playbook 的貼士.

你能在我們的 ansible-example repository.找到展示這些最佳實踐的 playbook 樣例.(注意: 這些示例用的也許不是最新版的中所有特性,但它們仍舊是極佳的參考.)

Content Organization

接下來的章節將向你展示一種組織 playbook 內容方式.

你對 Ansible 的使用應該符合你的需求而不是我們的,所以請隨意根據你的需求來組織修改接下來的示例.

有件事絕對是你想要做的,那就是使用 “roles” 組織特性.它作為主要的 playbook 的主要部分被文件化.詳情參見 Playbook Roles and Include Statements. 你絕對應該使用 roles. roles 是極好的. 快去使用 roles! roles! 重要的事情要重複說!roles 是極好的.(譯者:..老外也知道重要的事情重複三遍啊!~~~)

Directory Layout

頂層目錄結構應當包括下列檔案和目錄:

production                # inventory file for production servers 關於生產環境伺服器的清單檔案
stage                     # inventory file for stage environment 關於 stage 環境的清單檔案

group_vars/
   group1                 # here we assign variables to particular groups 這裡我們給特定的組賦值
   group2                 # ""
host_vars/
   hostname1              # if systems need specific variables, put them here 如果系統需要特定的變數,把它們放置在這裡.
   hostname2              # ""

library/                  # if any custom modules, put them here (optional) 如果有自定義的模組,放在這裡(可選)
filter_plugins/           # if any custom filter plugins, put them here (optional) 如果有自定義的過濾外掛,放在這裡(可選)

site.yml                  # master playbook 主 playbook
webservers.yml            # playbook for webserver tier Web 伺服器的 playbook
dbservers.yml             # playbook for dbserver tier 資料庫伺服器的 playbook

roles/
    common/               # this hierarchy represents a "role" 這裡的結構代表了一個 "role"
        tasks/            #
            main.yml      #  <-- tasks file can include smaller files if warranted
        handlers/         #
            main.yml      #  <-- handlers file
        templates/        #  <-- files for use with the template resource
            ntp.conf.j2   #  <------- templates end in .j2
        files/            #
            bar.txt       #  <-- files for use with the copy resource
            foo.sh        #  <-- script files for use with the script resource
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role
        meta/             #
            main.yml      #  <-- role dependencies

    webtier/              # same kind of structure as "common" was above, done for the webtier role
    monitoring/           # ""
    fooapp/               # ""

Use Dynamic Inventory With Clouds

如果你正在使用雲服務,你不應該在一個靜態檔案管理你的清單.詳見 動態 Inventory.

這不僅適用於雲環境 – 如果你的基礎設施中還有其他系統維護著一系列標準系統,使用 動態清單 會是個好主意.

How to Differentiate Stage vs Production

If managing static inventory, it is frequently asked how to differentiate different types of environments. The following example shows a good way to do this. Similar methods of grouping could be adapted to dynamic inventory (for instance, consider applying the AWS tag “environment:production”, and you’ll get a group of systems automatically discovered named “ec2_tag_environment_production”.

如果你管理著靜態清單,如何區分不同的環境類型是個常見的問題.接下來的示例會做一個很好地說明.

Let’s show a static inventory example though. Below, the production file contains the inventory of all of your production hosts.

It is suggested that you define groups based on purpose of the host (roles) and also geography or datacenter location (if applicable):

# file: production

[atlanta-webservers]
www-atl-1.example.com
www-atl-2.example.com

[boston-webservers]
www-bos-1.example.com
www-bos-2.example.com

[atlanta-dbservers]
db-atl-1.example.com
db-atl-2.example.com

[boston-dbservers]
db-bos-1.example.com

# webservers in all geos
[webservers:children]
atlanta-webservers
boston-webservers

# dbservers in all geos
[dbservers:children]
atlanta-dbservers
boston-dbservers

# everything in the atlanta geo
[atlanta:children]
atlanta-webservers
atlanta-dbservers

# everything in the boston geo
[boston:children]
boston-webservers
boston-dbservers

Group And Host Variables

本章節內容基於前一章節示例.

分組有利於組織結構,但不是所有的分組都是有益的.你也可以給他們賦值!比如說亞特蘭大有它自己的網路時間協議, 所以當配置 ntp.conf 時,我們就該使用它.讓我們現在設定它們:

---
# file: group_vars/atlanta
ntp: ntp-atlanta.example.com
backup: backup-atlanta.example.com

Variables aren’t just for geographic information either! Maybe the webservers have some configuration that doesn’t make sense for the database servers:

---
# file: group_vars/webservers
apacheMaxRequestsPerChild: 3000
apacheMaxClients: 900

If we had any default values, or values that were universally true, we would put them in a file called group_vars/all:

---
# file: group_vars/all
ntp: ntp-boston.example.com
backup: backup-boston.example.com

We can define specific hardware variance in systems in a host_vars file, but avoid doing this unless you need to:

---
# file: host_vars/db-bos-1.example.com
foo_agent_port: 86
bar_agent_port: 99

Again, if we are using dynamic inventory sources, many dynamic groups are automatically created. So a tag like “class:webserver” would load in variables from the file “group_vars/ec2_tag_class_webserver” automatically.

Top Level Playbooks Are Separated By Role

在 site.yml 中,我們包含了一個定義了整個基礎設施的 playbook.注意這個 playbook 是非常短的, 因為它僅僅包含了其他 playbooks.記住, playbook 不過就是一系列的 plays:

---
# file: site.yml
- include: webservers.yml
- include: dbservers.yml

在諸如 like webservers.yml 的檔案中(同樣也在頂層結構),我們僅僅將 Web 伺服器組與對應的 role 行為做對映.同樣值得注意的是這也非常的短小精悍.例如:

---
# file: webservers.yml
- hosts: webservers
  roles:
    - common
    - webtier

理念是我們能夠通過 “執行”(running) site.yml 來選擇整個基礎設施的配置.或者我們能夠通過執行其子集 webservers.yml 來配置. 這與 Ansible 的 “–limit” 類似,而且相對的更為顯式:

ansible-playbook site.yml --limit webservers
ansible-playbook webservers.yml

Task And Handler Organization For A Role

接下來的示例任務檔案展示了一個 role 是如何工作的.我們這裡的普通 role 僅僅用來配置 NTP,但是如果我們想的話,它可以做更多:

---
# file: roles/common/tasks/main.yml

- name: be sure ntp is installed
  yum: pkg=ntp state=installed
  tags: ntp

- name: be sure ntp is configured
  template: src=ntp.conf.j2 dest=/etc/ntp.conf
  notify:
    - restart ntpd
  tags: ntp

- name: be sure ntpd is running and enabled
  service: name=ntpd state=running enabled=yes
  tags: ntp

這是個處理檔案樣例.作為一種稽核,它只有當特定的任務報告發生變化時會被觸發,並在每個 play 結束時執行:

---
# file: roles/common/handlers/main.yml
- name: restart ntpd
  service: name=ntpd state=restarted

詳情請參閱 Playbook Roles and Include Statements.

What This Organization Enables (Examples)

我們在前文分享了我們基礎的組織結構.

那這種結構適用於何種應用場景? 很多!若我想重新配置整個基礎設施,如此即可:

ansible-playbook -i production site.yml

那隻重新配置所有的 NTP 呢?太容易了.:

ansible-playbook -i production site.yml --tags ntp

只重新配置我的 Web 伺服器呢?:

ansible-playbook -i production webservers.yml

只重新配置我在波士頓的 Web伺服器呢?:

ansible-playbook -i production webservers.yml --limit boston

前10臺 和 接下來的10臺呢?

ansible-playbook -i production webservers.yml –limit boston[0-10] ansible-playbook -i production webservers.yml –limit boston[10-20]

當然,只使用基礎的 ad-hoc 也是 OK 的啦.:

ansible boston -i production -m ping
ansible boston -i production -m command -a '/sbin/reboot'

這裡還有些有用的命令你需要知道(版本至少 1.1 或更高):

# confirm what task names would be run if I ran this command and said "just ntp tasks"
ansible-playbook -i production webservers.yml --tags ntp --list-tasks

# confirm what hostnames might be communicated with if I said "limit to boston"
ansible-playbook -i production webservers.yml --limit boston --list-hosts

Deployment vs Configuration Organization

The above setup models a typical configuration topology. When doing multi-tier deployments, there are going to be some additional playbooks that hop between tiers to roll out an application. In this case, ‘site.yml’ may be augmented by playbooks like ‘deploy_exampledotcom.yml’ but the general concepts can still apply.

Consider “playbooks” as a sports metaphor – you don’t have to just have one set of plays to use against your infrastructure all the time – you can have situational plays that you use at different times and for different purposes.

Ansible allows you to deploy and configure using the same tool, so you would likely reuse groups and just keep the OS configuration in separate playbooks from the app deployment.

Stage vs Production

如前所述,通過使用不同的清單檔案來分離你的 stage 和 生產環境是個好方法.你可以通過 -i 來指定.把它們放在同一個檔案中會有驚喜哦! 在部署到生產環境之前,先在 stage 環境中做測試是個好主意.你的環境不必保持同樣的大小,你可以通過 分組變數來對不同的環境進行控制.

Rolling Updates

請理解 ‘serial’ 關鍵字.你會在批量升級中使用它來控制升級機器的數量.

See 委託,滾動更新,本地動作.

Always Mention The State

parameter in your playbooks to make it clear, especially as some modules support additional states. 對於很多模組來說 ‘state’ 參數是可選的.無論是 ‘state=present’ 亦或 ‘state=absent’ ,你最好在 playbook 中顯式指定該參數,畢竟有些模組是支援附加的 ‘state’ 參數.

Group By Roles

在這條貼士中,我們某種程度上在重複自己,但這是值得的.一個系統可能被分成多分組.詳情請查閱 Inventory檔案Patterns. 在樣例中,分組名之後的 webserversdbservers ,它們因為是很重要的概念所以反覆出現.(譯者:恩,重要的事情要重複三遍!)一個系統可以出現在多個分組中.

通過給 role 賦予特定的變數,這允許 playbooks 能基於角色來鎖定機器.

See Playbook Roles and Include Statements.

Operating System and Distribution Variance

當處理在不同作業系統間參數值不同的參數時,使用 group_by 模組是個好主意.

這使宿主機的動態分組有了匹配的標準,即使該分組尚未在清單檔案中被定義

---

# talk to all hosts just so we can learn about them
- hosts: all
  tasks:
     - group_by: key=os_{{ ansible_distribution }}

# now just on the CentOS hosts...

- hosts: os_CentOS
  gather_facts: False
  tasks:
     - # tasks that only happen on CentOS go here

這會拋出所有基於作業系統名的分組.

如果需要對特定分組做設定,這也是可以的.例:

---
# file: group_vars/all
asdf: 10

---
# file: group_vars/os_CentOS
asdf: 42

在上述的例子中, CentOS 的機器獲取的 asdf 的值為 42,但其他機器獲得是 ‘10’.這不止可以用於設定變數,也可以將特定的 role 應用於特定的作業系統.

相對的,如果只需要變數:

- hosts: all
  tasks:
    - include_vars: "os_{{ ansible_distribution }}.yml"
    - debug: var=asdf

這將根據作業系統名來拉取相應的值.

Bundling Ansible Modules With Playbooks

如果一個 playbook 有一個與它 YMAL 檔案相關的 ”./library” 目錄,該目錄可以用於新增 Ansible 模組,它會被自動新增到 Ansible 模組的路徑中.這是一個將 playbook 與其模組放置在一起的方式.如下面的目錄結構樣例所展示:

.. _whitespace:

Whitespace and Comments

鼓勵使用空格來分隔內容,用 ‘#’ 來寫註釋.

Always Name Tasks

雖然推薦提供關於為什麼要這麼做的描述,但是直接給一個給定任務命名也是可以的.名字會在 playbook 執行時顯示.

Keep It Simple

當你能簡單的搞定某事時,就簡單的搞定.不要試圖一次性使用 Ansible 的所有的特性.僅僅使用對你有用的即可. 比如說你基本上不會需要一次性使用 vars , vars_files , vars_prompt--extra-vars 同時還是用一個外部的節點配置檔案.

如果你感覺任務很複雜時,它可能真的很複雜,這也許是個簡化它的好機會.

Version Control

請使用版本控制.保持你的 playbook 和 清單檔案 在 git(或其他版本控制系統)中,並將你的修改做提交. 這樣你就有審計軌跡來描述什麼時候以及為什麼你做了這樣的修改.

See also

YAML 語法
Learn about YAML syntax
Playbooks
Review the basic playbook features
模組相關
Learn about available modules
Developing Modules
Learn how to extend Ansible by writing your own modules
Patterns
Learn about how to select hosts
GitHub examples directory
Complete playbook files from the github project source
Mailing List
Questions? Help? Ideas? Stop by the list on Google Groups