White Box技術部

WEB開発のあれこれ(と何か)

【Shansible】VagrantとAnsibleでのShangriLa開発環境構築

Shansible

Shansibleは、秋葉原IT戦略研究所Project ShangriLaでAnime APIが動作するサーバ群を構築するためのプロジェクトです。

Shansibleを利用することにより、VagrantとAnsibleを使って簡単にローカルでAnime APIの動作を確認する環境を作ることができます。

利用方法

基本的にはshansibleをgit cloneしてvagrant upするだけです。

ですが、環境によってはVagrantやAnsibleの不具合に対する対処がいくつか必要になる場合があります。 READMEに判明している不具合への対処方法を記載していますので、上手くいかない場合はご確認ください。

READMEに記載した、利用するVagrantのバージョンが現時点の最新である1.8.5でないのは、1.8.5にはSSHに関する不具合があり、素の設定ではまともに起動しないためです。(一応対処方法は本家のIssueに上がっています)

Ansible

ミドルウェアのインストールにはAnsibleを使っているのですが、本Playbookに記載している以下のミドルウェアについては まだ他にもそんなに例がないと思いますので、結構いい参考になるのではないでしょうか!

  • MySQL 5.7
  • Jenkins 2
  • Ant

とくにMySQL 5.7のrootパスワード設定は苦労したので、使ってもらえると嬉しいです。(べったり貼っておきます)

- name: download
  get_url: url=http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm dest={{ src_dir }}/
  tags: mysql

- name: local install
  yum: name={{ src_dir }}/mysql57-community-release-el7-7.noarch.rpm state=present
  tags: mysql

- name: install
  yum: name=mysql-community-server state=present
  tags: mysql

- name: create log directory
  file: path={{ mysql_log_dir }} state=directory owner=mysql group=mysql mode=0764
  tags: mysql

- name: replace my.cnf
  template: src=my.cnf.j2 dest=/etc/my.cnf mode=0644
  tags: mysql

- name: start MySQL service
  service: name=mysqld enabled=yes state=started
  tags: mysql

- name: get temporary root password
  shell: cat {{ mysql_log_dir }}/mysqld.log | grep 'password is generated' | awk '{print $11}'
  register: mysql_default_password
  tags: mysql

- name: install MySQL-python module for ansible
  yum: name=MySQL-python state=present
  tags: mysql

- name: check .my.cnf exists
  stat: path=/root/.my.cnf
  register: mycnf_file
  tags: mysql

- name: deploy my.cnf for root user
  template: src=root.my.cnf.j2 dest=/root/.my.cnf mode=0600
  when: not mycnf_file.stat.exists
  tags: mysql

- name: change password validation to the easy way
  shell: |
    mysql -u root -p'{{ mysql_default_password.stdout }}' --connect-expired-password -e "SET GLOBAL validate_password_length=4;"
    mysql -u root -p'{{ mysql_default_password.stdout }}' --connect-expired-password -e "SET GLOBAL validate_password_policy=LOW;"
  when: not mycnf_file.stat.exists and stage == "development"
  tags: mysql

- name: change root user password
  shell: |
    mysql -u root -p'{{ mysql_default_password.stdout }}' --connect-expired-password -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '{{ mysql_root_password }}';"
  when: not mycnf_file.stat.exists
  tags: mysql

Ansibleの作成方針

以前、Ansible Meetupで「もっとシンプルに」とか話した手前、Ansibleの構成はシンプルになるように心がけました。 基本は公式のベストプラクティスを踏襲しています。

  • 利用者が変更する可能性のある変数はgroup_vars/all.ymlに集約
  • サーバ個別にPlaybookを作成するのではなく、site.ymlにまとめて記載し、インベントリファイルでchildrenを使って、ローカル・開発・STG・本番毎に構成を作れるようにした
  • 環境毎に変数を切り替えたい場合は、group_varsに環境毎のファイルを作成して設定する(local/development/staging/productionのような単位)

これにより、利用者は環境毎のインベントリファイルとsite.yml、group_varsを見るくらいになり、変数を変えたい場合も基本はall.ymlを編集すればよくなります。

注意する点としては、この方法では環境毎にサーバで実行するroleを変えることが、実行時パラメータでも使わないとできないというところです。 これについてはroleを変えるのではなく、whenでstage変数を見て、実行を分けるようにしています。 (例えば、MySQLのパスワードのバリデーションレベルの設定タスク:change password validation to the easy way)

こうすることで1ファイルの複雑度は増しますが、管理するファイルは1つであり、コードの重複も抑えられるため、結果的に見通しが良くなると思います。

雑記

疲れました・・・

いつも実際の開発よりこういう環境周りとかビルドツールとかで詰まる時間の方が長いので、 結果すっかりVagrant/Ansibleおじさんになってしまった感じがありますが、アプリ開発おじさんになれるよう巻き返していこうと思います。