実践!Ansibleベストプラクティス(後編)

ansible_best_practices

前回はAnsibleのベストプラクティスに沿ったやり方でユーザ追加から基本的なセキュリティの設定を行いました。今回はいよいよWordPressが動くようにセットアップを行っていきます。

webservers.ymlの修正

webservers.ymlを修正し、ロールにこれから作成するwebtierを追加します。

webservers.yml

---
- hosts: webservers
  roles:
    - common
    - webtier

webtierロールの作成

WordPressを動かすために必要なウェブサーバの設定を行うロールとして作成していきます。

httpdの追加

commonロールと同じ要領で作っていきましょう。

roles/webtier/tasks/main.yml

yumでApacheをインストールし起動します。

---
# httpd
- name: httpd is installed
  yum: pkg=httpd state=installed
  tags: httpd

- name: httpd is runnning and enabled
  service: name=httpd state=running enabled=yes
  tags: httpd

serviceモジュールのenabled=yesによって自動起動も有効となります。

httpd.confなどの設定は行わずデフォルトのままで動作させます。

roles/webtier/handlers/main.yml

今回httpdの設定変更は特に行いませんが、PHPをインストールした際にhttpdを再起動する必要があるので、httpdを再起動するハンドラも作っておきます。

---
- name: restart httpd
  service: name=httpd state=restarted

PHPの追加

roles/webtier/tasks/main.yml

例によってhttpd関連の記述の後に追加してください。

# php
- name: php is installed
  yum: pkg=php state=installed
  notify:
    - restart httpd
  tags: httpd

- name: php-mbstring is installed
  yum: pkg=php-mbstring state=installed
  notify:
    - restart httpd
  tags: httpd

- name: php-mysql is installed
  yum: pkg=php-mysql state=installed
  notify:
    - restart httpd
  tags: httpd

- name: php is configured
  notify:
    - restart httpd
  lineinfile: dest="/etc/php.ini" state=present regexp="^\;date.timezone =$" line="date.timezone = Asia/Tokyo" backrefs=yes
  tags: httpd

前回のsshdやsudoの設定とは違い、php.iniの編集にlineinfileモジュールを使ってみました。
一行ないし数行の変更で済む場合はこちらの方がいいかもしれません。

ただし正規表現の指定を間違えると意図せぬ結果を招くので、適用後の確認は入念に行うことをおすすめします。

WordPressの導入

さて、あとはいよいよWordPressの導入です。

group_vers/all

WordPressの設定を変数として追加します。

wordpress: {
    web_server: "xxx.xxx.xxx.xxx",
    db_name: "try_ansible_bp",
    db_user: "ansibler",
    db_password: "badpassword",
    db_host: "yyy.yyy.yyy.yyy"
}

これらの変数はウェブサーバおよびDBサーバの両方で使いますので、allに定義します。

roles/webtier/tasks/main.yml

ローカルからWordPressのソースをアップロードしてwp-config.phpで設定を行う一連のタスクを書いていきます。

PHPの設定の後に追記してください。

# wordpress
- name: wordpress source files are deployed
  unarchive: src="wordpress-4.2.4-ja.zip" dest="/var/www/html" owner=apache group=apache mode=0755
  args:
    creates: /var/www/html/wordpress
  tags: wordpress

- name: wordpress is configured
  template: src="wp-config.php.j2" dest="/var/www/html/wordpress/wp-config.php" owner=apache group=apache mode=0644
  tags: wordpress

- name: apache is wordpress directory owner
  file: path=/var/www/html/wordpress owner=apache group=apache recurse=yes
  tags: wordpress

これによりウェブサーバ上の/var/www/html/wordpressにWordPressのファイル一式が展開されます。

そして管理画面上からWordPressのアップデートやプラグインの導入が行えるようにディレクトリのオーナーをapacheにしています。

roles/webtier/files/wordpress–4.2.4-ja.zip

WordPress 日本語ローカルサイトから日本語版のWordPressの最新版を入手してroles/webtier/files以下に置いておきます。

roles/webtier/templates/wp-config.php.j2

wp-config.phpのテンプレートを用意します。

<?php
define('DB_NAME', '{{ wordpress.db_name }}');
define('DB_USER', '{{ wordpress.db_user }}');
define('DB_PASSWORD', '{{ wordpress.db_password }}');
define('DB_HOST', '{{ wordpress.db_host }}');
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

define('AUTH_KEY',         'GqKh}9$|SnXM!Kg|p/sIz!A2Y1L]=2l+QoF%CdFF8b1L`(O.B9Leu.PA2kMh2V ]');
define('SECURE_AUTH_KEY',  'B]n6!M=bZNy-f+#jA9lItVq`|Y*2A95Dz4!5Oifi1|CQ.$/]y6XD5McF/8:IAQaw');
define('LOGGED_IN_KEY',    ';(`p+nrEP2R23E9V{I(DkC#SNl4b=^+*vV7:Vv|YuzY>mi>viRi+K$ v:/B]!6^|');
define('NONCE_KEY',        'q:nH_Pm=qk|d+D%.fcdS/u?`%+:eg|2K#>+rRA()|^L&m,|kSuqz$BM_H40>O/l?');
define('AUTH_SALT',        '=BX7<|T];#_me-anahO;HWf;%!8T=_K~Vcg7DNDZ3O|!u5zGH(R=4HED);;ALI8&');
define('SECURE_AUTH_SALT', '/7hmWMHQVl+[mqUWR@xDJPphI+MPF[M+qTzAIDi2/7cm6dJ*:Ih k#csp&GY=+9L');
define('LOGGED_IN_SALT',   'x.E|8[W<fiySM-;D`Q4JuMm(zKU=wSc[@?Sq}zN,OOe.9m`-hucf0=QI0Zso7d(A');
define('NONCE_SALT',       'MBtG.V)kX0jdd*)JT5K_R-x{FXe4bh)s,P-D=Soi0nsz+f;=c#{o*^~d/<|AD)y[');

$table_prefix  = 'wp_';

define('WP_DEBUG', false);

if ( !defined('ABSPATH') )
        define('ABSPATH', dirname(__FILE__) . '/');

require_once(ABSPATH . 'wp-settings.php');

KEYとSALTはhttps://api.wordpress.org/secret-key/1.1/salt/にアクセスして表示されたものを利用します。WordPressのセキュリティのため、必ず自分で生成したものを利用する必要があります。

適用

site.ymlではなくwebservers.ymlをプレイブックとして指定してansible-playbookを実行します。

ansible-playbook -i development webservers.yml -u root --private-key=~/.ssh/id_rsa_for_ansible_bp_root

問題なく通ればウェブサーバ側の設定は完了です。

ansible-playbookの実行時に何かエラーが表示された場合はエラーメッセージをよく読んで問題のあるファイルを修正してください。

動作確認

さて、ここまでできたらセットアップしたウェブサーバのwordpressディレクトリにアクセスしてみてください。

http://xxx.xxx.xxx.xxx/wordpress/

そうすると以下のように表示されるはずです。

データベース接続確立エラー

おっとエラーです。しかし慌てないでください。これはWordPressが動作していると言うことなので、単にDBをまだセットアップしていないというだけです。

では、続いてDBサーバをセットアップしましょう。

dbservers.ymlの修正

dbservers.ymlを修正し、ロールにmysql_serverを追加します。

---
- hosts: dbservers
  roles:
    - common
    - mysql_server

mysql_serverロールの作成

MySQLを動かすためのロールを作っていきます。

roles/mysql_server/tasks/main.yml

yumでMySQLサーバーをインストールし起動します。そしてWordPressのためのDBとDBユーザを作成します。

---
- name: mysqld is installed
  yum: pkg=mysql-server state=installed
  tags: mysqld

- name: MySQL-python is installed
  yum: pkg=MySQL-python state=installed
  tags: mysqld

- name: mysqld is runnning and enabled
  service: name=mysqld state=running enabled=yes
  tags: mysqld

- name: database for wordpress is created
  mysql_db: db={{ wordpress.db_name }} state=present encoding=utf8
  tags: mysqld

- name:  wordpress database user is created
  mysql_user: name={{ wordpress.db_user }} password={{ wordpress.db_password }} priv={{ wordpress.db_name }}.*:ALL state=present host={{ wordpress.web_server }}
  tags: mysqld

とりあえずmy.cnfなどのカスタマイズはしません。

MySQL-pythonはmysql_dbモジュールやmysql_userモジュールに必要なためにインストールしています。

適用

今度はdbservers.ymlをプレイブックとして指定してansible-playbookを実行します。

ansible-playbook -i development dbservers.yml -u root --private-key=~/.ssh/id_rsa_for_ansible_bp_root

動作確認

再度セットアップしたウェブサーバのwordpressディレクトリにアクセスしてみてください。

http://xxx.xxx.xxx.xxx/wordpress/

WordPressの初期設定画面が表示されればOKです。

データベース接続エラーのままの場合は、iptablesの設定やMySQLのユーザーが正しく追加されているかなどを確認してみてください。

作業の終わりに

通しで適用してみましょう。

ansible-playbook -i development site.yml -u root --private-key=~/.ssh/id_rsa_for_ansible_bp_root

個別のグループへの適用やタグによる特定のタスクの実行がうまくいっても全体を通して実行すると問題が発生するケースがあります。

調整が終わったら必ず通しで実行しておいた方がいいでしょう。

現時点のファイル構成

try-ansible-best-practices
├── development
├── site.yml
├── dbservers.yml
├── webservers.yml
├── group_vars
│   ├── all
│   ├── dbservers
│   └── webservers
└── roles
    ├── common
    │   ├── files
    │   │   ├── authorized_keys_for_moongift
    │   │   ├── sshd_config
    │   │   └── sudoers
    │   ├── handlers
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   ├── templates
    │   │   └── iptables.j2
    ├── mysql_server
    │   └── tasks
    │       └── main.yml
    └── webtier
        ├── files
        │   └── wordpress-4.1-ja.zip
        ├── handlers
        │   └── main.yml
        ├── tasks
        │   └── main.yml
        └── templates
            └── wp-config.php.j2

終わりに

いかがでしょうか。やや駆け足気味でしたがベストプラクティスのイメージがつかめたでしょうか?

慣れてきた方はhttpd.confやmy.cnfのカスタマイズ、バーチャルホストの設定追加なども試してさらに感触を確かめてみてください。

もちろん実際に本格的な運用を開始するとこのベストプラクティスに従っていても悩む部分も出てくると思います。例えばロールの適切な切り分け方や名前の付け方など、そうした面では試行錯誤が必要でしょう。

しかし運用を開始するにあたっての足がかりとしては十分で、非常に参考になります。

また、このチュートリアルでは取り上げ切れていない部分もありますので、ぜひAnsibleのベストプラクティスを一読することを強くお勧めします。

それでは、素敵なAnsibleライフをお送りください!