Ansible Best Practices

  • 投稿者:
  • 投稿カテゴリー:ansible

Best Practicesを意訳してみた。
たぶん誤訳もある。Google翻訳の精度が向上したことをすごく感じた。

Content Organization

次の章では、playbookを構成するさまざまな方法の1つを示します。
要望に合う形で改変してください。
なにがどうあってもroleは必ず利用してください!

Directory Layout

production                # inventory file for production servers
staging                   # inventory file for staging environment

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
webservers.yml            # playbook for webserver tier
dbservers.yml             # playbook for dbserver tier

roles/
    common/               # this hierarchy represents a "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
        library/          # roles can also include custom modules
        lookup_plugins/   # or other types of plugins, like lookup in this case

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

Alternative Directory Layout

inventories/
   production/
      hosts               # inventory file for production servers
      group_vars/
         group1           # here we assign variables to particular groups
         group2           # ""
      host_vars/
         hostname1        # if systems need specific variables, put them here
         hostname2        # ""

   staging/
      hosts               # inventory file for staging environment
      group_vars/
         group1           # here we assign variables to particular groups
         group2           # ""
      host_vars/
         stagehost1       # if systems need specific variables, put them here
         stagehost2       # ""

library/
filter_plugins/

site.yml
webservers.yml
dbservers.yml

roles/
    common/
    webtier/
    monitoring/
    fooapp/

別の方法としてinventoryファイルとgroup_vars/host_varsを分割することが可能。
group_vars/host_vars がproductionとstagingで共通である必要が無い時はこちらの構成のほうが便利。

メリットは、より広い環境での柔軟性と異なる環境間での変数の完全な分離が可能であること。
デメリットは、ファイルが増えているため保守が難しいこと。

Use Dynamic Inventory With Clouds

クラウドを利用しているのであれば、Dynamic Inventoryを利用したほうがよい。
クラウドだけでなくシステムからサーバリストを出力できるような場合も、
Dynamic Inventoryを利用することができる。
(参考:Ansible dynamic inventory + Zabbix APIで監視対象を動的に構成管理)

How to Differentiate Staging vs Production

inventoryファイル分類方法をよく聞かれる。以下はそのよい例である。
グループ化方法を動的インベントリに適用することもできます。

以下の例ではすべての本番ホストがひとつのinventoryファイルに含まれています。
ホストの目的、データセンターの場所などに基づいてのグループ定義をオススメします。

# 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サーバがある場合、

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

WEBサーバ専用の変数は

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

もしデフォルト値が存在する場合は

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

特定のハードウェアのみに適用する場合は(必要がなければ避けたほうがよいが)

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

Dynamic Inventoryを利用する場合は、自動的にグループが作成されるため要注意。

Top Level Playbooks Are Separated By Role

site.yml:インフラストラクチャ全体を定義するplaybookが含まれている。そのためとても短い。

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

webservers.ymlなどはグループとroleを指定するだけにすること。

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

webserversでの実行は2つの方法がある

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

Task And Handler Organization For A Role

以下はNTPサーバを設定するtaskファイルです。

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

- name: be sure ntp is installed
  yum: name=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=started enabled=yes
  tags: ntp

以下がhandlerファイルとなります。タスクに変更があった場合最後に実行されます。

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

What This Organization Enables (Examples)

実行例について。
すべての構成を反映させる場合

ansible-playbook -i production site.yml

NTPのみを再構成する場合

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

webserversを再構成する場合

ansible-playbook -i production webservers.yml

ボストンのwebserversを再構成する場合

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

10ホストずつ再構成する場合

ansible-playbook -i production webservers.yml --limit boston[1-10]
ansible-playbook -i production webservers.yml --limit boston[11-20]

基本的な使い方も可能

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

有用なコマンドも覚えておくべき

# 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

上記の設計モデルは典型的なもの。複数層でのデプロイが必要な場合はplaybookが追加され、
site.yml は deploy_exampledotcom.yml といったplaybookが追加されるかもしれないが、上記設計モデルと構成は変わらない。

1つのplaysにこだわらず、状況や目的に合わせてplaysを作成したほうがよい。

同じツールを利用してデプロイできるため、グループを再利用し、アプリケーション設定とは別のplaybookにOS設定を保存すればよい。

Staging vs Production

すでに記載しているがステージング環境と本番環境を別々にするためには inventory ファイルを別々にしたほうがよい。
1つのinventoryファイルにしてしまうと、予期せぬ動作をする可能性がある。

本番環境の前にステージング環境で試すことは非常に良いこと。サイズが違う場合は、グループ変数で制御すること。

Rolling Updates

‘serial’ キーワードを理解すること。これを利用して、制御すること。
Delegation, Rolling Updates, and Local Actions

Always Mention The State

stateパラメーターは多くのモジュールで利用されている。
‘state=present’や‘state=absent’についてplaybookに明示的に記載しておいたほうがよい。

Group By Roles

システムには複数のグループがある。
playbookは役割ごとに作成することが大切。

Operating System and Distribution Variance

異なるOS間でことなるパラメーターを利用する場合、group_by モジュールの利用がオススメ。
inventoryで定義しなくても、特定の条件に一致する動的なグループが作成される。

---

# 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

これによりすべてのホストがOSに基づいた動的グループに分類される。
グループ特有の設定が必要な場合は、以下のように設定します。

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

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

上の例では、CentOSマシンはasdfに42の値を取得しますが、他のマシンは10になる。
これは変数の設定だけでなく、特定のシステムに特定の役割を適用するためにも使用できる。
変数だけが必要な場合は、OS名に基づいて変数が取り込むことも可能。

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

Bundling Ansible Modules With Playbooks

libraryディレクトリがある場合、自動的にansibleのモジュールパスとして認識される。
playbookで実行されるモジュールを保持するためのよい方法。

Whitespace and Comments

空白を利用してわかりやすくすること、#でのコメントを推奨。

Always Name Tasks

タスクの名前は記載しなくてもよいが、タスクの目的を記載することを推奨。
playbook実行時に表示される。

Keep It Simple

とくかくシンプルに。ansibleのすべての機能を1度に使い分けてはいけない。
必要ないもの(vars,vars_files,vars_prompt,–extra-vars )は利用しないこと。

Version Control

gitなどのバージョン管理システムを利用し、変更した理由がわかるようにしておくこと。

Variables and Vaults

一般的な管理方法として、変数を見つけるためにgrepなどのツールが利用されます。
暗号化などで覆い隠されているときは、間接的に作業する必要があります。
playbook実行時に暗号化されていないファイルから変数を取得し
機密変数は暗号化されたファイルから取得します。

ベストプラクティスとして、group_vars/ のサブディレクトリを利用する。
vars と vault という2つのファイル名やプレフィックスを利用する。