torutkのブログ

ソフトウェア・エンジニアのブログ

AndibleでRedmineを構築する例を詳しくみてみる

1日ほどAnsibleとたわむれて(RedmineサーバーをAnsibleで構築に向けて) - torutkのブログ で言及した、Redmine.jpでおなじみの前田さんがGitHubで公開しているAnsibleでCentOS 7にRedmine 3.1を構築する設定を詳しく調べてみます。
https://github.com/farend/redmine-centos7-mariadb-ansible

使い方は、上述URLのREADME.md に分かりやすく記載されていますので、そのとおり進めれば「コマンド5個実行するだけ」です。

Ansible設定のディレクトリ・ファイル構成

上述Redmine構築のAnsible設定の構成を見ていきます。ディレクトリ構成は次のようになっています。

redmine-centos7-mariadb-ansible
  +-- group_vars/
  |     +-- redmine-servers
  +-- roles/
  |     +-- apache/
  |     |     +-- tasks/
  |     |     |     +-- main.yml
  |     |     +-- templates/
  |     |           +-- redmine.conf
  |     +-- mariadb/
  |     |     +-- tasks/
  |     |     |     +-- main.yml
  |     |     +-- templates/
  |     |           +-- my.cnf
  |     :(中略)
  |     +-- system/
  |           +-- tasks/
  |                 +-- main.yml
  +-- hosts
  +-- site.yml

この構造は、Ansibleの「ベストプラクティス」と呼ばれています。

group_varsディレクトリは、設定対象ホストのグループ毎に適用する変数を定義したファイルを置きます。ファイル名(ここではredmine-servers)は後述のinventoryファイル(hosts)に定義したグループ名に合わせます。

rolesディレクトリは、taskを共有するための仕組みであるroleを置きます。ディレクトリ名は必ずrolesとします。この下に、role名のディレクトリを置き(commonという共通roleをまとめるディレクトリを置くこともあり)ます。roleディレクトリはその下にtask、files、templatesなどの所定のディレクトリを必要なものだけ設けます。最低taskが必要です。
taskディレクトリには、main.ymlのファイル名で設定を記述します。

hostsは、Ansibleで設定する対象のホストを定義したファイルです。ホスト名と、グループ定義、などを定義します。

site.ymlは、全体のplaybookファイルで、通常これをAnsibleで実行します。

hosts

[redmine-servers]
localhost ansible_connection=local

と、グループ名定義([redmine-servers])、ホスト名定義(localhost ...)があります。
このplaybookは、自分自身に対して適用する想定になっています。
通常は、リモートのホストを設定することが多いので、そのときはここにホスト名を追加します。

site.yml

- hosts: redmine-servers

  roles:
    - system
    - mariadb
    - ruby
    - redmine
    - apache

  post_tasks:
    - name: 完了
      debug:
        msg='インストールが完了しました。 http://IPアドレス/ にアクセスしてください。'

最初は馴染めない記述ですが(yamlに馴れていないだけかも)、適用対象ホストの指定、実行するロールの指定、終了後の処理(メッセージ表示)が記述されています。

systemロール

最初に実行されるsystemのロールを見てみます。

roles/system/tasks/main.yml

- name: SELinuxの状態確認
  command:
    /usr/sbin/selinuxenabled
  register:
    result
  changed_when: false
  failed_when: result.rc not in [0, 1]

- name: 起動時にSELinux無効化 (/etc/sysconfig/selinux)
  sudo: yes
  selinux: state=disabled
  when: result.rc == 0

- name: SELinux無効化 (setenforce)
  sudo: yes
  command: setenforce 0
  when: result.rc == 0

- name: firewalldでHTTPを許可
  sudo: yes
  command: firewall-cmd --zone=public --add-service=http --permanent

- name: firewalldのポリシーをリロード
  sudo: yes
  command: firewall-cmd --reload

- name: 開発ツールのインストール
  sudo: yes
  yum: name='@Development Tools'

サーバー環境構築で実行するコマンド(処理)1つごとに、シーケンス定義(行頭に'-'が付いた記述)をしています。
最初のシーケンスは、高度な定義(register, when)を使っているのでスキップして、簡単な例を1つ見てみます。

- name: firewalldでHTTPを許可
  sudo: yes
  command: firewall-cmd --zone=public --add-service=http --permanent

これは、Linuxのコマンドを1つ、sudoで実行する定義です。これなら分かりやすいです。

次に、yumでパッケージをインストールする例を見てみます。

- name: 開発ツールのインストール
  sudo: yes
  yum: name='@Development Tools'

これは、~$ sudo yum groupinstall "Development Tools" を実行するのと同じです。

command: 定義でも実行できますが、Ansibleではあらかじめモジュールが用意されていて、それを使うと簡単に定義できます。実は最初の例のcommand: もモジュールの1つです。
代表的なモジュールに、file, template, git, copy, get_url, user, group, serviceなどがあります。

redmineのtemplate(database.yml)

roles/redmine/templates/database.yml

production:
  adapter: mysql2
  database: db_redmine
  host: localhost
  username: user_redmine
  password: "{{ db_passwd_redmine }}"
  encoding: utf8

Redmineの設定ファイルの雛形が置かれています。

これをredmineのタスク(roles/redmine/tasks/main.yml)の中で次のシーケンスで実施しています。

- name: database.ymlの作成
  sudo: yes
  template:
    src=database.yml
    dest={{ redmine_dir }}/config/database.yml

temlateモジュールのsrcは、そのロールのtemplatesディレクトリにある指定のファイルを、destは設定対象ホストの置き場所を指定します。
templateのファイルには変数を記述することができ、templateシーケンス実行時に置き換えるようになっています。

ここで、redmine_dirと、db_passwd_redmineの2つの変数は、group_vars/redmine-serversに定義されています。抜粋を次に示します。

# user_redmine (RedmineからMariaDBに接続するときのユーザー)
db_passwd_redmine: Must_be_changed!

# Redmineのデプロイ先URL
redmine_dir: /var/lib/redmine

まとめ

おおよそAnsibleの設定の書き方のイメージがつかめてきました。