本連載の第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アドレス等の差異を吸収できます。
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
1 | - name: deploy webservers |
また、dbservers.ymlは下記になります。
リスト3:dbservers.yml
1 | - name: deploy dbservers |
site.ymlは、システム全体でどのPlaybookを利用するかを制御します。今回のWordPressであれば、webserversとdbserversでの構築を前提とするため、下記のようになります。
リスト4:site.yml
1 | - include: webservers.yml |
2 | - include: dbservers.yml |
今回作成するPlaybookの概要
これまでの内容を踏まえて、WebサーバーとDBサーバー2台構成のPlaybookを作成していきます。site.ymlを親Playbookとして、子のwebserver.yml、dbserver.ymlのPlaybookを読み込む形式にします。下図のように、webserver.ymlとdbserver.ymlからRoleを呼び出すことで、実際のTaskを処理します。
Playbookの構成
実際のディレクトリ構造
ディレクトリとファイルの構造は、以下のようになります。ファイルが入っていないディレクトリは、今回は利用していませんが、Best Practiceに記載されているものです。今後の追加開発等で利用する可能性があるため、予め作成しておきます。
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
group_vars/staging
staging環境用の変数を、このファイルに記述します。WordPressの構築にあたり下記4項目について、変数として外出しをしています。これによりPlaybookに手を加えることなく、WordPressをダウンロードするURLや、データベース(MySQL)のユーザ情報を変更することができます。
- wordpress_url
- db_name
- db_user
- db_password
以下の例では、WordPressは4.4.2を利用し、データベースの各種パラメータを「wordpress」としています。
site.yml
Top LevelのPlaybookであるsite.ymlは、例と同様にwebservers.ymlとdbservers.ymlを読みこむ形としています。
リスト8:site.yml
1 | - include: webservers.yml |
2 | - include: dbservers.yml |
webservers.yml
webservers.ymlでは、下記4つのRoleを読み込みます。この中でcommon Roleはdbserversにも利用しており、本環境内で共通となる設定を記述しています。
- common
- httpd
- php
- wordpress
リスト9:webservers.yml
1 | - name: deploy webservers |
4 | roles:.. literalinclude:: ./code/webservers.yml |
5 | - common :language: python |
dbservers.yml
dbservers.ymlでは、下記2つのRoleを読み込みます。
リスト10:dvservers.yml
1 | - name: deploy dbservers |
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
06 | - name: Firewalldのインストール |
07 | yum: name=firewalld state=present |
10 | service: name=firewalld state=started enabled=yes |
roles/httpd/tasks/main.yml
リスト12:roles/httpd/tasks/main.yml
1 | - name: apache(httpd)のインストール |
2 | yum: name=httpd state=latest |
4 | - name: firewalld で HTTP を許可 |
5 | firewalld: permanent=True service=http state=enabled immediate=true |
8 | service: name=httpd state=started enabled=yes |
roles/php/tasks/main.yml
リスト13:roles/php/tasks/main.yml
02 | yum: name="{{item}}" state=latest |
15 | copy: src=phpinfo.php dest=/var/www/html/phpinfo.php |
18 | service: name=httpd state=restarted enabled=yes |
roles/wordpress/tasks/main.yml
ここでは、前述のgroup_vars/stagingに記載したwordpress_urlの値を利用しています。
リスト14:roles/wordpress/tasks/main.yml
01 | - name: wordpress のダウンロード |
03 | url="{{ wordpress_url }}" |
04 | dest=/tmp/wordpress.tar.gz |
07 | unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/html/ copy=no |
09 | - name: wordpress の所有権を apache に変更 |
10 | file: path=/var/www/html/wordpress/ owner=apache group=apache recurse=yes |
13 | service: name=httpd state=restarted |
roles/mysql/tasks/main.yml
第2、3回ではMySQLのデータベースを手動で作成しましたが、今回はAnsibleのmysql moduleを利用して、データベース作成とユーザの作成を行っています。
リスト15:roles/mysql/tasks/main.yml
01 | - name: mariadb(mysql)のインストール |
02 | yum: name="{{item}}" state=latest |
08 | - name: mariadb サービスの起動 |
09 | service: name=mariadb state=started enabled=yes |
11 | - name: firewalld で mariadb(mysql) を許可 |
12 | firewalld: permanent=True service=mysql state=enabled immediate=true |
15 | mysql_db: name={{ db_name }} state=present encoding=utf8 |
20 | password={{ db_password }} |
21 | priv={{ db_name }}.*:ALL |
実行結果
今回作成したPlaybookの実行方法及び、実行結果は以下のようになります。
リスト16:Playbookの実行結果
01 | $ ansible-playbook -i staging site.yml |
03 | PLAY [deploy webservers] ****************************************************** |
05 | GATHERING FACTS *************************************************************** |
08 | TASK: [common | SELinuxの無効化] ************************************* |
11 | TASK: [common | Firewalldのインストール] ****************************************** |
14 | TASK: [common | Firewalldの有効化] ********************************************* |
17 | TASK: [httpd | apache(httpd)のインストール] **************************** |
18 | changed: [192.168.0.10] |
20 | TASK: [httpd | firewalld で HTTP を許可] ********************************** |
21 | changed: [192.168.0.10] |
23 | TASK: [httpd | サービスの起動] ***************************************** |
24 | changed: [192.168.0.10] |
26 | TASK: [php | PHP のインストール] *************************************** |
27 | changed: [192.168.0.10] => (item=php,php-mysql) |
29 | TASK: [php | タイムゾーンの設定] ************************************* |
30 | changed: [192.168.0.10] |
32 | TASK: [php | php テストページの作成] ********************************* |
33 | changed: [192.168.0.10] |
35 | TASK: [php | http サービスの再起動] *********************************** |
36 | changed: [192.168.0.10] |
38 | TASK: [wordpress | wordpress のダウンロード] *************************** |
39 | changed: [192.168.0.10] |
41 | TASK: [wordpress | wordpress の展開] *************************************** |
42 | changed: [192.168.0.10] |
44 | TASK: [wordpress | wordpress の所有権を apache に変更] **************** |
45 | changed: [192.168.0.10] |
47 | TASK: [wordpress | http サービスの再起動] ***************************** |
48 | changed: [192.168.0.10] |
50 | PLAY [deploy dbservers] ******************************************************* |
52 | GATHERING FACTS *************************************************************** |
55 | TASK: [common | SELinuxの無効化] ************************************* |
58 | TASK: [common | Firewalldのインストール] ****************************************** |
61 | TASK: [common | Firewalldの有効化] ********************************************* |
64 | TASK: [mysql | mariadb(mysql)のインストール] *************************** |
65 | changed: [192.168.0.20] => (item=mariadb,mariadb-server,MySQL-python) |
67 | TASK: [mysql | mariadb サービスの起動] ********************************* |
68 | changed: [192.168.0.20] |
70 | TASK: [mysql | firewalld で mariadb(mysql) を許可] ************************ |
71 | changed: [192.168.0.20] |
73 | TASK: [mysql | データベースの作成] *********************************** |
74 | changed: [192.168.0.20] |
76 | TASK: [mysql | DBユーザの作成] ****************************************** |
77 | changed: [192.168.0.20] |
79 | PLAY RECAP ******************************************************************** |
80 | 192.168.0.10 : ok=15 changed=11 unreachable=0 failed=0 |
81 | 192.168.0.20 : ok=9 changed=5 unreachable=0 failed=0 |
実行後は、ブラウザでhttp://10.10.0.10/wordpressにアクセスすることで、WordPressの最終インストール画面になります。これ以降は基本的に第3回と同じ作業となりますが、今回の環境に合わせてデータベース関係の設定値を変更します。
WordPressの最終インストール
まとめと次回予告
今回はAnsible Best Practiceに従い、第2、3回で作成したPlaybookを改良しました。改良箇所は主に以下の2点となります。
- Roles機能を活用したPlaybookの分割
- Inventory fileによる管理対象の指定
Roles機能を使うことで、Playbookを役割単位に分割し管理できるようになりました。各々のPlaybookを疎結合に作成することが可能となります。これにより、Playbookの可読性や再利用性が向上し、複数メンバーによる開発も効率的に行えるようになりました。
Inventory fileを使用することで管理対象を環境によって切り替えたり、グループ化して複数対象に同じ処理を実行させられるようになりました。
このような改良によって、Playbookの管理性を向上させられることを理解いただけたかと思います。
次回は、実環境で使う際に出てくるTipsをご紹介致します。