Ansible応用編:より実践的なPlaybookを作り上げる

2016年6月20日(月)
小野寺 大地
Ansible Best Practiceを参考に、より実践的なPlaybookの作成方法を紹介する。

本連載の第4回、第5回では、「Ansible応用編」と題してAnsibleの応用的な使い方やTipsについて詳しく解説します。第3回ではAnsibleを利用して、1台のサーバー内にLAMP環境を準備して、WordPressを構築しました。Ansibleが身についてきた後には、どのようにPlaybookを管理すれば良いのかという課題や疑問が出てきます。今回は、AnsibleのBest Practiceをご紹介した上でWordPressのPlaybookを整理します。

環境の変更点と構築のための振り返り

前回までに利用した環境のうち、実行サーバーのみを再利用して、操作対象のサーバーは新規に作り直します。

今回作成する環境の概要

今回作成する環境の概要

実行サーバーCentOS 7.2
Ansible 2.0
Web兼APサーバーCentOS 7.2
DBサーバーCentOS 7.2

WordPress構築に必要な処理

第3回を振り返って、WordPressの構築に必要な処理を確認してみましょう。

必要な処理具体的な手順
Apacheの導入yumによるhttpdのインストール
firewalldの設定
httpdサービスの起動
PHPの導入yumによるPHPのインストール
タイムゾーンの設定
テストページの作成
httpdサービスの再起動
MySQLの導入yumによるMySQLのインストール
MySQLサービスの起動
WordPressの導入WordPressのダウンロード
WordPressの展開
WordPressの所有権の変更
httpdサービスの再起動

今回はこれらの手順を見直し、サーバーの役割ごとに実行されるPlaybookをコントロールします。

対象サーバー必要な処理
Webサーバー
(Web兼APサーバー)
Apacheの導入
PHPの導入
WordPressの導入
データベースサーバーMySQLの導入

Ansible Best Practiceに入る前に

前回までの学習内容をベースとして実際にPlaybookを記述し始めると、構成が複雑化するにつれ可読性が下がり、再利用性も悪化することに気付くかと思います。こうした課題を解決するために、AnsibleではPlaybookの管理方法をBest Practiceとして紹介しています。今回は、前回までに作成したPlaybookをBest Practiceに沿って再構成します。これにより可読性や再利用性を向上させることで、さらに実践的なPlaybookにしていきます。

Ansible Best Practice

作業の開始にあたって Ansible Best Practiceを確認しましょう。Ansible Best Practiceでは、Rolesを使ってPlaybookを分割する方法が書かれています。よく利用する項目について確認していきます。

Inventory file

Inventory fileとはAnsibleが複数のサーバーに対して処理を行う際に利用するファイルで、対象となるサーバーのIPアドレスやホスト名を列挙します。Best Practiceの例ではproductionとstagingの2ファイルが挙げられています。列挙する際に、[webservers]といった形でサーバーをグルーピングすることができます。このグルーピングを用いることで、複数サーバーをまとめることができ、グループ内のサーバーに対して同一のPlaybookを実行することができます。また、本番環境とステージング環境といったように複数環境が存在する場合に、このInventory fileを使い分けることで、環境間のIPアドレス等の差異を吸収できます。

リスト1:Inventory fileの例

[webservers]
192.168.0.10

[dbservers]
192.168.0.20

[staging:children]
webservers
dbservers

Vars file

Vars file(group_vars、host_varsでは、特定のグループやホストに対する変数の値を定義できます。ここでいう変数とは環境によって変化するものを示します。例えば、利用するライブラリのバージョンや、ファイルのパス、連携するサーバーのIPアドレス等を記載します。処理手順のようにに変化しないものに関しては、Playbookに記述します。これにより再利用性の高いPlaybookを作成することが可能となります。

※ varsはPlaybookの中に書くことも可能ですが、Best Practiceでは変数専用のファイルに外出しすることを勧めています。

Roles

Rolesは、サーバーの役割ごとにPlaybookを独立させるために用いられます。具体的な処理(Playbook)はtasks内のmain.ymlなどに記述します。しかし、サーバーの「役割ごとに分割」といっても「Webサーバー」「DBサーバー」のような分け方は再利用性の観点からおすすめできません。

例えば今回作成するWordPressサーバーの導入は、大きく分けて以下の3つの手順で構成されています。

  • Apacheの導入
  • PHPの導入
  • WordPressの導入

作成したPlaybookを別のアプリケーションでも活用することを考えた場合に、一つのファイルに全て記述すると再利用性が下がってしまいます。役割ごとに分割して記述することで、例えばWebサーバにApacheではなくnginxを採用する場合でも、WordPress、PHPの部分はそのまま再利用可能となります。その結果、新規に書く必要があるのはnginx導入の部分のみとなります。

この分割方法の指針は、分割単位が大きすぎると詰め込みすぎで良く分からないRoleになり、小さすぎると見通しが悪くなります。ミドルウェアや独立したアプリケーション単位で、再利用しやすい粒度の分割を心がけるのが良いでしょう。

Top LevelのPlaybook

先ほど「Roleは役割を意識して分割しましょう」と書きました。分割した際に課題となってくるのは、分割したRoleをそれぞれどのサーバに対して適用するかです。WordPressサーバーを構築するためには3つのRoleを適用する必要があります。その管理をするのが、Top LevelのPlaybookとなります。Best Practiceでは下記の3点の例が挙げられています。

※ファイル名は一例であり、分割対象の役割や用途によって変更します。

  • webservers.yml
  • dbservers.yml
  • site.yml

これらのファイルには、使用するPlaybookをRole単位で指定します。今回構築するwebserverには、3つのRoleが必要となるため、webservers.ymlは下記のようになります。

リスト2:webservers.yml

- name: deploy webservers
  hosts: webservers
  become: yes
  roles:
    - common
    - httpd
    - php
    - wordpress

また、dbservers.ymlは下記になります。

リスト3:dbservers.yml

- name: deploy dbservers
  hosts: dbservers
  become: yes
  roles:
    - common
    - mysql

site.ymlは、システム全体でどのPlaybookを利用するかを制御します。今回のWordPressであれば、webserversとdbserversでの構築を前提とするため、下記のようになります。

リスト4:site.yml

- include: webservers.yml
- include: dbservers.yml

今回作成するPlaybookの概要

これまでの内容を踏まえて、WebサーバーとDBサーバー2台構成のPlaybookを作成していきます。site.ymlを親Playbookとして、子のwebserver.yml、dbserver.ymlのPlaybookを読み込む形式にします。下図のように、webserver.ymlとdbserver.ymlからRoleを呼び出すことで、実際のTaskを処理します。

Playbookの構成

Playbookの構成

実際のディレクトリ構造

ディレクトリとファイルの構造は、以下のようになります。ファイルが入っていないディレクトリは、今回は利用していませんが、Best Practiceに記載されているものです。今後の追加開発等で利用する可能性があるため、予め作成しておきます。

リスト5:ディレクトリ構造

.
│  dbservers.yml
│  site.yml
│  staging
│  webservers.yml
│
├─group_vars
│      staging
│
└─roles
    ├─common
    │  ├─handlers
    │  ├─tasks
    │  │      main.yml
    │  │
    │  ├─templates
    │  └─vars
    ├─httpd
    │  ├─handlers
    │  ├─tasks
    │  │      main.yml
    │  │
    │  ├─templates
    │  └─vars
    ├─mysql
    │  ├─handlers
    │  ├─tasks
    │  │      main.yml
    │  │
    │  ├─templates
    │  └─vars
    ├─php
    │  ├─files
    │  │      phpinfo.php
    │  │
    │  ├─handlers
    │  ├─tasks
    │  │      main.yml
    │  │
    │  ├─templates
    │  └─vars
    └─wordpress
        ├─handlers
        ├─tasks
        │      main.yml
        │
        ├─templates
        └─vars

Playbookの作成

WordPressを構築するためのPlaybookについて、必要なファイルを一つづつ紹介します。

Playbookを管理するためのファイル

先ほど紹介したinventory fileや、vars fileなどを組み合わせて、タスクを管理するためのファイルとなります。

staging(inventory file)

stagingは、前述したinventory fileとなります。ここでは[webservers]と[dbservers]の2つのグループを使うことで、サーバーごとの役割を分類しています。ファイル下部の[staging:children]により、staging環境に[webservers]と[dbservers]を所属させます。この記述により、後述のgroup_vars内のstagingというファイルと連携させることが可能となります。

リスト6:staging環境のinventory file

[webservers]
192.168.0.10

[dbservers]
192.168.0.20

[staging:children]
webservers
dbservers

group_vars/staging

staging環境用の変数を、このファイルに記述します。WordPressの構築にあたり下記4項目について、変数として外出しをしています。これによりPlaybookに手を加えることなく、WordPressをダウンロードするURLや、データベース(MySQL)のユーザ情報を変更することができます。

  • wordpress_url
  • db_name
  • db_user
  • db_password

以下の例では、WordPressは4.4.2を利用し、データベースの各種パラメータを「wordpress」としています。

リスト7:staging環境のvars file

wordpress_url:  https://ja.wordpress.org/wordpress-4.4.2-ja.tar.gz
db_name: wordpress
db_user: wordpress
db_password: wordpress

site.yml

Top LevelのPlaybookであるsite.ymlは、例と同様にwebservers.ymlとdbservers.ymlを読みこむ形としています。

リスト8:site.yml

- include: webservers.yml
- include: dbservers.yml

webservers.yml

webservers.ymlでは、下記4つのRoleを読み込みます。この中でcommon Roleはdbserversにも利用しており、本環境内で共通となる設定を記述しています。

  • common
  • httpd
  • php
  • wordpress

リスト9:webservers.yml

- name: deploy webservers
  hosts: webservers//}
  become: yes
  roles:.. literalinclude:: ./code/webservers.yml
    - common  :language: python
    - httpd  :linenos:
    - php
    - wordpress

dbservers.yml

dbservers.ymlでは、下記2つのRoleを読み込みます。

  • common
  • mysql

リスト10:dvservers.yml

- name: deploy dbservers
  hosts: dbservers
  become: yes
  roles:
    - common
    - mysql

Roleの内容

ここからは、具体的な処理手順を見ていきます。これまでご紹介したsite.yml、webservers.yml、dbservers.ymlから呼び出される各ファイルを見ていきましょう。なお、各ファイルの内容については、第2、3回の説明も合わせてご覧ください。

roles/common/tasks/main.yml

common roleは、Ansibleで構築されるサーバーの共通の設定を入れるためのRoleです。本環境では、webserversとdbserversの共通設定を記述しています。

リスト11:roles/common/tasks/main.yml

- name: SELinuxの無効化
  selinux:
    policy: targeted
    state: disabled

- name: Firewalldのインストール
  yum: name=firewalld state=present

- name: Firewalldの有効化
  service: name=firewalld state=started enabled=yes

roles/httpd/tasks/main.yml

リスト12:roles/httpd/tasks/main.yml

- name: apache(httpd)のインストール
  yum: name=httpd state=latest

- name: firewalld で HTTP を許可
  firewalld: permanent=True service=http state=enabled immediate=true

- name: サービスの起動
  service: name=httpd state=started enabled=yes

roles/php/tasks/main.yml

リスト13:roles/php/tasks/main.yml

- name: PHP のインストール
  yum: name="{{item}}" state=latest
  with_items:
    - php
    - php-mysql

- name: タイムゾーンの設定
  ini_file: >
    dest=/etc/php.ini
    section=Date
    option=date.timezone
    value='"Asia/Tokyo"'

- name: php テストページの作成
  copy: src=phpinfo.php dest=/var/www/html/phpinfo.php

- name: http サービスの再起動
  service: name=httpd state=restarted enabled=yes

roles/wordpress/tasks/main.yml

ここでは、前述のgroup_vars/stagingに記載したwordpress_urlの値を利用しています。

リスト14:roles/wordpress/tasks/main.yml

- name: wordpress のダウンロード
  get_url:
    url="{{ wordpress_url }}"
    dest=/tmp/wordpress.tar.gz

- name: wordpress の展開
  unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/html/ copy=no

- name: wordpress の所有権を apache に変更
  file: path=/var/www/html/wordpress/ owner=apache group=apache recurse=yes

- name: http サービスの再起動
  service: name=httpd state=restarted

roles/mysql/tasks/main.yml

第2、3回ではMySQLのデータベースを手動で作成しましたが、今回はAnsibleのmysql moduleを利用して、データベース作成とユーザの作成を行っています。

リスト15:roles/mysql/tasks/main.yml

- name: mariadb(mysql)のインストール
  yum: name="{{item}}" state=latest
  with_items:
    - mariadb
    - mariadb-server
    - MySQL-python

- name: mariadb サービスの起動
  service: name=mariadb state=started enabled=yes

- name: firewalld で mariadb(mysql) を許可
  firewalld: permanent=True service=mysql state=enabled immediate=true

- name: データベースの作成
  mysql_db: name={{ db_name }} state=present encoding=utf8

- name: DBユーザの作成
  mysql_user: >
    name={{ db_user }}
    password={{ db_password }}
    priv={{ db_name }}.*:ALL
    host="%"
    state=present

実行結果

今回作成したPlaybookの実行方法及び、実行結果は以下のようになります。

リスト16:Playbookの実行結果

$ ansible-playbook -i staging site.yml

PLAY [deploy webservers] ******************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.10]

TASK: [common | SELinuxの無効化] *************************************
ok: [192.168.0.10]

TASK: [common | Firewalldのインストール] ******************************************
ok: [192.168.0.10]

TASK: [common | Firewalldの有効化] *********************************************
ok: [192.168.0.10]

TASK: [httpd | apache(httpd)のインストール] ****************************
changed: [192.168.0.10]

TASK: [httpd | firewalld で HTTP を許可] **********************************
changed: [192.168.0.10]

TASK: [httpd | サービスの起動] *****************************************
changed: [192.168.0.10]

TASK: [php | PHP のインストール] ***************************************
changed: [192.168.0.10] => (item=php,php-mysql)

TASK: [php | タイムゾーンの設定] *************************************
changed: [192.168.0.10]

TASK: [php | php テストページの作成] *********************************
changed: [192.168.0.10]

TASK: [php | http サービスの再起動] ***********************************
changed: [192.168.0.10]

TASK: [wordpress | wordpress のダウンロード] ***************************
changed: [192.168.0.10]

TASK: [wordpress | wordpress の展開] ***************************************
changed: [192.168.0.10]

TASK: [wordpress | wordpress の所有権を apache に変更] ****************
changed: [192.168.0.10]

TASK: [wordpress | http サービスの再起動] *****************************
changed: [192.168.0.10]

PLAY [deploy dbservers] *******************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.20]

TASK: [common | SELinuxの無効化] *************************************
ok: [192.168.0.20]

TASK: [common | Firewalldのインストール] ******************************************
ok: [192.168.0.20]

TASK: [common | Firewalldの有効化] *********************************************
ok: [192.168.0.20]

TASK: [mysql | mariadb(mysql)のインストール] ***************************
changed: [192.168.0.20] => (item=mariadb,mariadb-server,MySQL-python)

TASK: [mysql | mariadb サービスの起動] *********************************
changed: [192.168.0.20]

TASK: [mysql | firewalld で mariadb(mysql) を許可] ************************
changed: [192.168.0.20]

TASK: [mysql | データベースの作成] ***********************************
changed: [192.168.0.20]

TASK: [mysql | DBユーザの作成] ******************************************
changed: [192.168.0.20]

PLAY RECAP ********************************************************************
192.168.0.10               : ok=15   changed=11   unreachable=0    failed=0
192.168.0.20               : ok=9    changed=5    unreachable=0    failed=0

実行後は、ブラウザでhttp://10.10.0.10/wordpressにアクセスすることで、WordPressの最終インストール画面になります。これ以降は基本的に第3回と同じ作業となりますが、今回の環境に合わせてデータベース関係の設定値を変更します。

WordPressの最終インストール

WordPressの最終インストール

まとめと次回予告

今回はAnsible Best Practiceに従い、第2、3回で作成したPlaybookを改良しました。改良箇所は主に以下の2点となります。

  • Roles機能を活用したPlaybookの分割
  • Inventory fileによる管理対象の指定

Roles機能を使うことで、Playbookを役割単位に分割し管理できるようになりました。各々のPlaybookを疎結合に作成することが可能となります。これにより、Playbookの可読性や再利用性が向上し、複数メンバーによる開発も効率的に行えるようになりました。

Inventory fileを使用することで管理対象を環境によって切り替えたり、グループ化して複数対象に同じ処理を実行させられるようになりました。

このような改良によって、Playbookの管理性を向上させられることを理解いただけたかと思います。

次回は、実環境で使う際に出てくるTipsをご紹介致します。

新日鉄住金ソリューションズ

連載バックナンバー

運用・管理技術解説
第10回

Ansible Towerのクラウド連携機能による効率化を目指す

2017/9/26
Ansible Towerが備えるクラウド連携機能を用いることで、Playbookやユーザーの管理を効率良く行えることを紹介する。
運用・管理技術解説
第9回

Ansible Towerによる権限の管理

2017/7/27
複数のユーザーによる使用を前提としたAnsible Towerでの権限管理の方法を紹介する。
運用・管理
第8回

Ansibleの機能を拡張するAnsible Tower

2017/4/18
好評の連載「注目の構成管理ツールAnsibleを徹底活用する」の追加コンテンツとして、Ansible Towerを取り上げる。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています