PR

開発チームの環境を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のWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスの概要とメリットをチェック

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