開発チームの環境を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を含むディレクトリの構造

01.
02├── README.md
03
04├── hosts
05
06├── site.yml
07├── common.yml
08├── gitlab.yml
09├── jenkins.yml
10├── redmine.yml
11├── rocketchat.yml
12
13├── group_vars
14│  └── all
15
16└── roles
17    ├── common
18    │  ├── spec
19    │  │  └── common_spec.rb
20    │  └── tasks
21    │      └── main.yml
22    ├── gitlab
23    │  ├── README.md
24    │  ├── spec
25    │  │  └── gitlab_spec.rb
26    │  └── tasks
27    │      └── main.yml
28    ├── jenkins
29    │  ├── README.md
30    │  ├── handlers
31    │  │  └── main.yml
32    │  ├── spec
33    │  │  └── jenkins_spec.rb
34    │  ├── tasks
35    │  │  ├── deploy.yml
36    │  │  ├── main.yml
37    │  │  └── plugin.yml
38    │  └── vars
39    │      └── main.yml
40    ├── redmine
41    │  ├── README.md
42    │  ├── files
43    │  │  ├── configuration.yml
44    │  │  └── database.yml
45    │  ├── spec
46    │  │  └── redmine_spec.rb
47    │  ├── tasks
48    │  │  └── main.yml
49    │  ├── templates
50    │  │  ├── configuration.yml
51    │  │  ├── database.yml
52    │  │  ├── pg_hba.conf
53    │  │  └── redmine.conf
54    │  └── vars
55    │      └── main.yml
56    └── rocketchat
57        ├── README.md
58        ├── files
59        │  └── meteor-install.sh
60        ├── handlers
61        │  └── main.yml
62        ├── spec
63        │  └── rocketchat_spec.rb
64        ├── tasks
65        │  ├── main.yml
66        │  ├── node_js.yml
67        │  └── rocketchat.yml
68        ├── templates
69        │  ├── initiate.js.j2
70        │  ├── mongodb.repo.j2
71        │  └── pm2-rocket-chat.json.j2
72        └── vars
73            └── main.yml

Playbookの詳細

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

README.md

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

hosts

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

リスト2:hosts

1[gitlab]
2gitlab
3[jenkins]
4jenkins
5[redmine]
6redmine
7[rocketchat]
8rocketchat

site.yml

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

リスト3:site.yml

1- include: common.yml
2- include: gitlab.yml
3- include: jenkins.yml
4- include: redmine.yml
5- include: rocketchat.yml

group_vars/all

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

リスト4:group_vars_all

1user: "root"
2proxy_env:
3  http_proxy: ""
4  https_proxy: ""

Playbookの実行

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

実行環境

実行環境

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

Ansible環境の準備とPlaybookの取得

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

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

1$ sudo yum install epel-release
2$ sudo yum install ansible
3 
4$ ansible --version
5ansible 2.0.1.0
6  config file = /etc/ansible/ansible.cfg
7  configured module search path = Default w/o overrides

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

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

1$ sudo yum install git
3$ cd ansible_wg

hostsの設定

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

リスト7:hostsの設定

1$ vi hosts
2[gitlab]
310.0.0.2
4[jenkins]
510.0.0.3
6[redmine]
710.0.0.4
8[rocketchat]
910.0.0.5

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

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

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

01$ ansible all -i hosts -m ping
0210.0.0.3 | SUCCESS => {
03    "changed": false,
04    "ping": "pong"
05}
0610.0.0.2 | SUCCESS => {
07    "changed": false,
08    "ping": "pong"
09}
1010.0.0.4 | SUCCESS => {
11    "changed": false,
12    "ping": "pong"
13}
1410.0.0.5 | SUCCESS => {
15    "changed": false,
16    "ping": "pong"
17}

varsの設定

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

リスト9:変数の設定

1$ vi group_vars/all
2user: "centos"
3proxy_env:
4  http_proxy: ""
5  https_proxy: ""

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

リスト10:Rocketchat用のvars file

1$ ssh 10.0.0.5 hostname
2rocketchat
3 
4$ vi roles/rocketchat/vars/main.yml
5host: rocketchat

Playbook実行

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

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

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

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

01$ ansible-playbook -i hosts site.yml
02 
03PLAY [common] ******************************************************************
04 
05TASK [setup] *******************************************************************
06ok: [10.0.0.5]
07ok: [10.0.0.4]
08ok: [10.0.0.2]
09ok: [10.0.0.3]
10 
11(中略)
12 
13PLAY [gitlab] ******************************************************************
14 
15TASK [setup] *******************************************************************
16ok: [10.0.0.2]
17 
18(中略)
19 
20PLAY [jenkins] *****************************************************************
21 
22TASK [setup] *******************************************************************
23ok: [10.0.0.3]
24 
25(中略)
26 
27PLAY [common] ******************************************************************
28 
29TASK [setup] *******************************************************************
30ok: [10.0.0.4]
31 
32(中略)
33 
34PLAY [rocketchat] **************************************************************
35 
36TASK [setup] *******************************************************************
37ok: [10.0.0.5]
38 
39(中略)
40 
41PLAY RECAP *********************************************************************
4210.0.0.2                   : ok=17   changed=9    unreachable=0    failed=0
4310.0.0.3                   : ok=18   changed=11   unreachable=0    failed=0
4410.0.0.4                   : ok=41   changed=32   unreachable=0    failed=0
4510.0.0.5                   : ok=35   changed=28   unreachable=0    failed=0

Playbookのデバッグ方法

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

デバッグオプション

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

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

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

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

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

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

1$ 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

1SSH 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:タスクのエラーを無視する設定

1- name: be sure http service port is open
2  firewalld: permanent=True service=http state=enabled immediate=true
3  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テストコード

1describe service('jenkins') do
2  it { should be_enabled }
3  it { should be_running }
4end
5 
6describe port(8080) do
7  it { should be_listening }
8end

ansible_specのインストール

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

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

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

1$ sudo yum install gem ruby-devel gcc
2$ gem install ansible_spec rake
3 
4$ gem list ansible_spec
5*** LOCAL GEMS ***
6ansible_spec (0.2.11)

テストの実行

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

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

1$ rake -T
2rake serverspec:common      # Run serverspec for common
3rake serverspec:gitlab      # Run serverspec for gitlab
4rake serverspec:jenkins     # Run serverspec for jenkins
5rake serverspec:redmine     # Run serverspec for redmine
6rake serverspec:rocketchat  # Run serverspec for rocketchat

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

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

1$ rake serverspec:common
2Run serverspec for common to {"name"=>"10.0.0.2", "port"=>22, "uri"=>"10.0.0.2"}
3.......
4 
5Finished in 0.405 seconds (files took 0.21447 seconds to load)
67 examples, 0 failures

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

1$ rake serverspec:gitlab
2Run serverspec for gitlab to {"name"=>"10.0.0.2", "port"=>22, "uri"=>"10.0.0.2"}
3.....
4 
5Finished in 0.43535 seconds (files took 0.21471 seconds to load)
65 examples, 0 failures

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

1$ rake serverspec:jenkins
2Run serverspec for jenkins to {"name"=>"10.0.0.3", "port"=>22, "uri"=>"10.0.0.3"}
3...
4 
5Finished in 0.41946 seconds (files took 0.21628 seconds to load)
63 examples, 0 failures

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

1$ rake serverspec:redmine
2Run serverspec for redmine to {"name"=>"10.0.0.4", "port"=>22, "uri"=>"10.0.0.4"}
3.............
4 
5Finished in 0.35985 seconds (files took 0.52526 seconds to load)
613 examples, 0 failures

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

1$ rake serverspec:rocketchat
2Run serverspec for rocketchat to {"name"=>"10.0.0.5", "port"=>22, "uri"=>"10.0.0.5"}
3...
4 
5Finished in 0.35099 seconds (files took 0.21446 seconds to load)
63 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メルマガ会員のサービス内容を見る

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