開発チームの環境を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のテストコードも含まれています。
. ├── 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アドレスを記述します。
[gitlab] gitlab [jenkins] jenkins [redmine] redmine [rocketchat] rocketchat
site.yml
システム全体で利用するPlaybookを記述したファイルです。各RoleのPlaybookを順番に呼び出すように書かれており、Ansible実行時にこのPlaybookを指定するだけで全ての環境を一括構築することができます。
- 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で共通の値が呼び出されます。
user: "root" proxy_env: http_proxy: "" https_proxy: ""
Playbookの実行
今回は、OpenStack上に以下のような環境を用意して、Playbookを実行します。
Playbook実行までの手順は、以下のとおりです。
Ansible環境の準備とPlaybookの取得
まず、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から取得します。
$ sudo yum install git $ git clone https://github.com/OSSConsCloud/ansible_wg.git $ cd ansible_wg
hostsの設定
Invenotry fileに対象サーバーのIPアドレスを記述します。
$ 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実行サーバーと対象サーバーは疎通できています。
$ 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を指定しています。また、プロキシが必要な場合は、適宜設定します。
$ vi group_vars/all user: "centos" proxy_env: http_proxy: "" https_proxy: ""
Rocketchatのvars fileには、RocketChatサーバーのホスト名を指定します。今回はrocketchatというホスト名になっているため、設定は以下のようになります。
$ 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ごとの処理が実行されていきます。
以下のように、エラーなく実行が終了すれば環境構築完了です。
$ 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」オプションをつけることで、出力結果をより詳細にして、問題点を見つけやすくなります。
$ ansible-playbook -i hosts site.yml -vvv
対象ホストを限定して実行
Ansibleの実行コマンドに「--limit <role_name>」をつけることで、特定のRoleに属しているホストにのみPlaybookを実行することができます。例えば以下のコマンドでは、Inventory fileでgitlabに属するホストにのみPlaybookが適用されます。実行対象のホストが絞り込まれるだけなので、Playbookはcommon、gitlabの両方が適用されます。
$ ansible-playbook -i hosts site.yml --limit gitlab
既知の不具合
以下の不具合がGithubのIssueに報告されています。もし同様のエラーが発生した場合は、参照してください。
TASK [setup]のSSH Error
TASK [setup]で以下のエラーが出る場合は、環境変数に「ANSIBLE_SCP_IF_SSH=y」を指定してAnsibleを実行してみてください(issue)。
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」を指定します。
- 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にログインできます。
Jenkins
http://10.0.0.3:8080にアクセスすると、jenkinsの画面を確認することができます。また、今回のPlaybookを利用すると、すでにGitプラグインがインストールされた状態になっています。
Redmine
http://10.0.0.4/redmine/にアクセスすると、Redmineの画面が表示されます。画面右上の「ログイン」を選択して、管理者アカウントのログインIDとパスワード(どちらも「admin」です)を入力します。
管理者アカウントでログインするとRedmineを利用できます。
Rocketchat
http://10.0.0.5:3000にアクセスすると、ログイン画面が表示されます。「新しいアカウントを登録」を選択してアカウント情報を入力し、送信ボタンを押します。
すると再度ログイン画面が表示されるので、作成したアカウント情報を入力してログインします。
構築した環境のテスト
今回のPlaybookには、serverspecのテストコードが同梱されています。例えば、role/jenkins/spec/jenkins_spec.rbは以下のような内容になっており、(1)jenkinsが起動していること、(2)8080番ポートをListenしていることの2点がテストされています。
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をインストールします。
$ sudo yum install gem ruby-devel gcc $ gem install ansible_spec rake $ gem list ansible_spec *** LOCAL GEMS *** ansible_spec (0.2.11)
テストの実行
用意されているテストの一覧を確認するためには、以下のコマンドを用います。
$ 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
一覧に表示されたコマンドを実行すると、対応するテストを実施できます。各テストの実行のようすを、以下に示します。
$ 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
$ 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
$ 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
$ 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
$ 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を使って環境構築の効率化を実現してみてください。