開発チームの環境をAnsibleで一括構築しよう

2016年8月24日(水)
冨永 善視(とみなが よしみ)
連載の最終回として、これまで学んだ内容を元に、開発環境をAnsibleで一括構築する手順を紹介する。

本連載ではこれまで、Ansibleの使い方から実際にPlaybookを書く際に役立つTips、テストの考え方などをご紹介してきました。最終回となる今回は、サンプルのPlaybookを使って開発チームのための環境を構築してみたいと思います。今回利用するPlaybookはこちらです。

https://github.com/OSSConsCloud/ansible_wg

Playbookの紹介

今回利用するPlaybookは、本連載の第2回から第7回までの著者らが参加しているOSSコンソーシアム クラウド部会の活動で作成したものです。MITライセンスで公開していますので、どなたでも自由に利用することができます。

このPlaybookでは、以下のOSSツールの環境構築を行うことが可能です。

  • GitLab (バージョン管理ツール)
  • Jenkins (CIツール)
  • Redmine (プロジェクト管理ツール)
  • RocketChat (チャットツール)

Playbookの構成

Playbookは第4回でご紹介したAnsibleのベストプラクティスを参考に、以下のような構成になっています。各ツールごとにRoleを分割しており、すべてのRoleで実行する共通設定はcommonというRoleに抜き出しています。また、各Roleには第6回でご紹介したansiblespecのテストコードも含まれています。

リスト1:Playbookを含むディレクトリの構造

.
├── README.md
│
├── hosts
│
├── site.yml
├── common.yml
├── gitlab.yml
├── jenkins.yml
├── redmine.yml
├── rocketchat.yml
│
├── group_vars
│  └── all
│
└── roles
    ├── common
    │  ├── spec
    │  │  └── common_spec.rb
    │  └── tasks
    │      └── main.yml
    ├── gitlab
    │  ├── README.md
    │  ├── spec
    │  │  └── gitlab_spec.rb
    │  └── tasks
    │      └── main.yml
    ├── jenkins
    │  ├── README.md
    │  ├── handlers
    │  │  └── main.yml
    │  ├── spec
    │  │  └── jenkins_spec.rb
    │  ├── tasks
    │  │  ├── deploy.yml
    │  │  ├── main.yml
    │  │  └── plugin.yml
    │  └── vars
    │      └── main.yml
    ├── redmine
    │  ├── README.md
    │  ├── files
    │  │  ├── configuration.yml
    │  │  └── database.yml
    │  ├── spec
    │  │  └── redmine_spec.rb
    │  ├── tasks
    │  │  └── main.yml
    │  ├── templates
    │  │  ├── configuration.yml
    │  │  ├── database.yml
    │  │  ├── pg_hba.conf
    │  │  └── redmine.conf
    │  └── vars
    │      └── main.yml
    └── rocketchat
        ├── README.md
        ├── files
        │  └── meteor-install.sh
        ├── handlers
        │  └── main.yml
        ├── spec
        │  └── rocketchat_spec.rb
        ├── tasks
        │  ├── main.yml
        │  ├── node_js.yml
        │  └── rocketchat.yml
        ├── templates
        │  ├── initiate.js.j2
        │  ├── mongodb.repo.j2
        │  └── pm2-rocket-chat.json.j2
        └── vars
            └── main.yml

Playbookの詳細

Playbookの実行前に、確認しておきたいファイルについて解説します。

README.md

Playbookの説明と設定可能なvarsの一覧が記載されています。各ツールの個別設定は、RoleごとのREADME.mdを参照してください。

hosts

Playbookの実行対象を記述するInventory fileです。このファイルに、実行対象のサーバーのIPアドレスを記述します。

リスト2:hosts

[gitlab]
gitlab
[jenkins]
jenkins
[redmine]
redmine
[rocketchat]
rocketchat

site.yml

システム全体で利用するPlaybookを記述したファイルです。各RoleのPlaybookを順番に呼び出すように書かれており、Ansible実行時にこのPlaybookを指定するだけで全ての環境を一括構築することができます。

リスト3:site.yml

- include: common.yml
- include: gitlab.yml
- include: jenkins.yml
- include: redmine.yml
- include: rocketchat.yml

group_vars/all

group_vars/allに設定された変数は、デフォルト値として扱われます(公式サイト参照)。今回のPlaybookでは、SSHでログインする際のユーザー名とプロキシの設定が記述できるようになっており、各RoleのPlaybookで共通の値が呼び出されます。

リスト4:group_vars_all

user: "root"
proxy_env:
  http_proxy: ""
  https_proxy: ""

Playbookの実行

今回は、OpenStack上に以下のような環境を用意して、Playbookを実行します。

実行環境

実行環境

Playbook実行までの手順は、以下のとおりです。

Ansible環境の準備とPlaybookの取得

まず、Ansibleをインストールします。

リスト5:Ansibleのインストール

$ sudo yum install epel-release
$ sudo yum install ansible

$ ansible --version
ansible 2.0.1.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides

今回利用するPlaybookは、Githubから取得します。

リスト6:PlaybookをGithubから取得

$ sudo yum install git
$ git clone https://github.com/OSSConsCloud/ansible_wg.git
$ cd ansible_wg

hostsの設定

Invenotry fileに対象サーバーのIPアドレスを記述します。

リスト7:hostsの設定

$ vi hosts
[gitlab]
10.0.0.2
[jenkins]
10.0.0.3
[redmine]
10.0.0.4
[rocketchat]
10.0.0.5

パスワード認証なしでSSH接続できるよう、ssh-copy-idコマンドなどを利用して、あらかじめ対象サーバーとAnsible実行サーバーで鍵交換を行っておきます。

以下のコマンドを実行してSUCCESSと表示されれば、Ansible実行サーバーと対象サーバーは疎通できています。

リスト8:サーバー間の疎通確認

$ ansible all -i hosts -m ping
10.0.0.3 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.4 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.5 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

varsの設定

Ansibleを実行する前に、変数の設定を行います。前述のように、group_vars/allに対象サーバーにSSHでログインするユーザー名とプロキシを指定できます。今回はcentosユーザーを使用するので、userにcentosを指定しています。また、プロキシが必要な場合は、適宜設定します。

リスト9:変数の設定

$ vi group_vars/all
user: "centos"
proxy_env:
  http_proxy: ""
  https_proxy: ""

Rocketchatのvars fileには、RocketChatサーバーのホスト名を指定します。今回はrocketchatというホスト名になっているため、設定は以下のようになります。

リスト10:Rocketchat用のvars file

$ ssh 10.0.0.5 hostname
rocketchat

$ vi roles/rocketchat/vars/main.yml
host: rocketchat

Playbook実行

ここまででPlaybookの実行準備が整いましたので、Top LevelのPlaybookであるsite.ymlを引数に指定して、Ansibleを実行します。Inventory fileは「-i」オプションで指定します。

Playbookを実行すると、まず最初にcommonの処理が実行され、その後、順次Roleごとの処理が実行されていきます。

以下のように、エラーなく実行が終了すれば環境構築完了です。

リスト11:Playbook実行のようす

$ ansible-playbook -i hosts site.yml

PLAY [common] ******************************************************************

TASK [setup] *******************************************************************
ok: [10.0.0.5]
ok: [10.0.0.4]
ok: [10.0.0.2]
ok: [10.0.0.3]

(中略)

PLAY [gitlab] ******************************************************************

TASK [setup] *******************************************************************
ok: [10.0.0.2]

(中略)

PLAY [jenkins] *****************************************************************

TASK [setup] *******************************************************************
ok: [10.0.0.3]

(中略)

PLAY [common] ******************************************************************

TASK [setup] *******************************************************************
ok: [10.0.0.4]

(中略)

PLAY [rocketchat] **************************************************************

TASK [setup] *******************************************************************
ok: [10.0.0.5]

(中略)

PLAY RECAP *********************************************************************
10.0.0.2                   : ok=17   changed=9    unreachable=0    failed=0
10.0.0.3                   : ok=18   changed=11   unreachable=0    failed=0
10.0.0.4                   : ok=41   changed=32   unreachable=0    failed=0
10.0.0.5                   : ok=35   changed=28   unreachable=0    failed=0

Playbookのデバッグ方法

Ansibleの実行結果がエラーになった場合は、以下の方法を利用することでデバッグしやすくなります。

デバッグオプション

Ansibleの実行コマンドに「-vvv」オプションをつけることで、出力結果をより詳細にして、問題点を見つけやすくなります。

リスト12:デバッグ時には-vvvオプションが有用

$ ansible-playbook -i hosts site.yml -vvv

対象ホストを限定して実行

Ansibleの実行コマンドに「--limit <role_name>」をつけることで、特定のRoleに属しているホストにのみPlaybookを実行することができます。例えば以下のコマンドでは、Inventory fileでgitlabに属するホストにのみPlaybookが適用されます。実行対象のホストが絞り込まれるだけなので、Playbookはcommon、gitlabの両方が適用されます。

リスト13:対象ホストを限定する--limitオプション

$ ansible-playbook -i hosts site.yml --limit gitlab

既知の不具合

以下の不具合がGithubのIssueに報告されています。もし同様のエラーが発生した場合は、参照してください。

TASK [setup]のSSH Error

TASK [setup]で以下のエラーが出る場合は、環境変数に「ANSIBLE_SCP_IF_SSH=y」を指定してAnsibleを実行してみてください(issue)。

リスト14:既知の不具合その1

SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh

firewalldの設定変更がALREADY_ENABLEDとなる

firewalldのポートを開閉するタスクが実行される際、すでに同一のルールが有効であった場合、エラーが発生することがあります(issue)。firewalldの設定変更を含むPlaybookを何度も実行する場合は、一度firewalldのルールを初期化してから実行するか、タスクのエラーを無視するよう設定してください。タスクでエラーが発生した際、それを無視して次のタスクを実行するには「ignore_errors: yes」を指定します。

リスト15:タスクのエラーを無視する設定

- name: be sure http service port is open
  firewalld: permanent=True service=http state=enabled immediate=true
  ignore_errors: yes

動作確認

Ansibleの実行が完了したら、実際に構築した環境にアクセスしてみます。

Gitlab

http://10.0.0.2にアクセスすると、gitlabの画面が表示されます。最初にrootアカウントのパスワード初期化画面が表示されるので、任意のパスワードを入力します。その後サインイン画面が表示されるので、rootと先ほど設定したパスワードを入力するとgitlabにログインできます。

Gitlabのログイン画面

Gitlabのログイン画面

Gitlabのダッシュボード画面

Gitlabのダッシュボード画面

Jenkins

http://10.0.0.3:8080にアクセスすると、jenkinsの画面を確認することができます。また、今回のPlaybookを利用すると、すでにGitプラグインがインストールされた状態になっています。

Jenkinsのダッシュボード画面

Jenkinsのダッシュボード画面

Jenkinsのプラグイン

Jenkinsのプラグイン

Redmine

http://10.0.0.4/redmine/にアクセスすると、Redmineの画面が表示されます。画面右上の「ログイン」を選択して、管理者アカウントのログインIDとパスワード(どちらも「admin」です)を入力します。

Redmineのログイン画面

Redmineのログイン画面

管理者アカウントでログインするとRedmineを利用できます。

Redmineのダッシュボード画面

Redmineのダッシュボード画面

Rocketchat

http://10.0.0.5:3000にアクセスすると、ログイン画面が表示されます。「新しいアカウントを登録」を選択してアカウント情報を入力し、送信ボタンを押します。

Rocketchatのサインイン画面

Rocketchatのサインイン画面

すると再度ログイン画面が表示されるので、作成したアカウント情報を入力してログインします。

Rocketchatのダッシュボード画面

Rocketchatのダッシュボード画面

構築した環境のテスト

今回のPlaybookには、serverspecのテストコードが同梱されています。例えば、role/jenkins/spec/jenkins_spec.rbは以下のような内容になっており、(1)jenkinsが起動していること、(2)8080番ポートをListenしていることの2点がテストされています。

リスト16:Jenkins用のserverspecテストコード

describe service('jenkins') do
  it { should be_enabled }
  it { should be_running }
end

describe port(8080) do
  it { should be_listening }
end

ansible_specのインストール

ansible_specを利用することで、AnsibleのInventory fileの内容をもとにSSH経由でserverspecのテストを実行することができます。

まずはAnsible実行サーバーで以下のコマンドを実行し、ansible_specをインストールします。

リスト17:ansible_specのインストール

$ sudo yum install gem ruby-devel gcc
$ gem install ansible_spec rake

$ gem list ansible_spec
*** LOCAL GEMS ***
ansible_spec (0.2.11)

テストの実行

用意されているテストの一覧を確認するためには、以下のコマンドを用います。

リスト18:用意されているテストの確認

$ rake -T
rake serverspec:common      # Run serverspec for common
rake serverspec:gitlab      # Run serverspec for gitlab
rake serverspec:jenkins     # Run serverspec for jenkins
rake serverspec:redmine     # Run serverspec for redmine
rake serverspec:rocketchat  # Run serverspec for rocketchat

一覧に表示されたコマンドを実行すると、対応するテストを実施できます。各テストの実行のようすを、以下に示します。

リスト19:commonのテスト実行

$ rake serverspec:common
Run serverspec for common to {"name"=>"10.0.0.2", "port"=>22, "uri"=>"10.0.0.2"}
.......

Finished in 0.405 seconds (files took 0.21447 seconds to load)
7 examples, 0 failures

リスト20:gitlabのテスト実行

$ rake serverspec:gitlab
Run serverspec for gitlab to {"name"=>"10.0.0.2", "port"=>22, "uri"=>"10.0.0.2"}
.....

Finished in 0.43535 seconds (files took 0.21471 seconds to load)
5 examples, 0 failures

リスト21:jenkinsのテスト実行

$ rake serverspec:jenkins
Run serverspec for jenkins to {"name"=>"10.0.0.3", "port"=>22, "uri"=>"10.0.0.3"}
...

Finished in 0.41946 seconds (files took 0.21628 seconds to load)
3 examples, 0 failures

リスト22:redmineのテスト実行

$ rake serverspec:redmine
Run serverspec for redmine to {"name"=>"10.0.0.4", "port"=>22, "uri"=>"10.0.0.4"}
.............

Finished in 0.35985 seconds (files took 0.52526 seconds to load)
13 examples, 0 failures

リスト23:rocektchatのテスト実行

$ rake serverspec:rocketchat
Run serverspec for rocketchat to {"name"=>"10.0.0.5", "port"=>22, "uri"=>"10.0.0.5"}
...

Finished in 0.35099 seconds (files took 0.21446 seconds to load)
3 examples, 0 failures

まとめ

今回は開発チームの環境をAnsibleで構築するというテーマで、Playbookの実例をご紹介しました。Playbookが用意されていることで簡単に環境構築ができ、必要なときにすぐに使い始めることができます。みなさんも、Ansibleを使って環境構築の効率化を実現してみてください。

著者
冨永 善視(とみなが よしみ)
TIS株式会社

戦略技術センター
デザイン指向クラウドオーケストレーションソフトウェア「CloudConductor」の開発、およびクラウド関連技術の調査・検証に従事。OpenStackやZabbixといったOSSの調査・検証を行う他、プロジェクトチームの開発環境の構築・管理を担当している。
>TIS株式会社

連載バックナンバー

運用・管理技術解説
第10回

Ansible Towerのクラウド連携機能による効率化を目指す

2017/9/26
Ansible Towerが備えるクラウド連携機能を用いることで、Playbookやユーザーの管理を効率良く行えることを紹介する。
運用・管理技術解説
第9回

Ansible Towerによる権限の管理

2017/7/27
複数のユーザーによる使用を前提としたAnsible Towerでの権限管理の方法を紹介する。
運用・管理
第8回

Ansibleの機能を拡張するAnsible Tower

2017/4/18
好評の連載「注目の構成管理ツールAnsibleを徹底活用する」の追加コンテンツとして、Ansible Towerを取り上げる。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています