Ansible応用編:より実践的な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アドレス等の差異を吸収できます。
[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は下記のようになります。
- name: deploy webservers hosts: webservers become: yes roles: - common - httpd - php - wordpress
また、dbservers.ymlは下記になります。
- name: deploy dbservers hosts: dbservers become: yes roles: - common - mysql
site.ymlは、システム全体でどのPlaybookを利用するかを制御します。今回のWordPressであれば、webserversとdbserversでの構築を前提とするため、下記のようになります。
- 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を処理します。
実際のディレクトリ構造
ディレクトリとファイルの構造は、以下のようになります。ファイルが入っていないディレクトリは、今回は利用していませんが、Best Practiceに記載されているものです。今後の追加開発等で利用する可能性があるため、予め作成しておきます。
. │ 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というファイルと連携させることが可能となります。
[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」としています。
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を読みこむ形としています。
- include: webservers.yml - include: dbservers.yml
webservers.yml
webservers.ymlでは、下記4つのRoleを読み込みます。この中でcommon Roleはdbserversにも利用しており、本環境内で共通となる設定を記述しています。
- common
- httpd
- php
- wordpress
- 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
- 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の共通設定を記述しています。
- 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
- 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
- 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の値を利用しています。
- 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を利用して、データベース作成とユーザの作成を行っています。
- 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の実行方法及び、実行結果は以下のようになります。
$ 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回と同じ作業となりますが、今回の環境に合わせてデータベース関係の設定値を変更します。
まとめと次回予告
今回はAnsible Best Practiceに従い、第2、3回で作成したPlaybookを改良しました。改良箇所は主に以下の2点となります。
- Roles機能を活用したPlaybookの分割
- Inventory fileによる管理対象の指定
Roles機能を使うことで、Playbookを役割単位に分割し管理できるようになりました。各々のPlaybookを疎結合に作成することが可能となります。これにより、Playbookの可読性や再利用性が向上し、複数メンバーによる開発も効率的に行えるようになりました。
Inventory fileを使用することで管理対象を環境によって切り替えたり、グループ化して複数対象に同じ処理を実行させられるようになりました。
このような改良によって、Playbookの管理性を向上させられることを理解いただけたかと思います。
次回は、実環境で使う際に出てくるTipsをご紹介致します。