Gitbucket + Jenkins + Vagrant + DigitalOcean + Ansible + Serverspec + Slack を連携したインフラCIを試す

 

20150130003236jenkins_logovagrant-7c50437elogo-3b02463bansible_logo_black_square3970679CzlsZP3xUHeX3HAGdZ2rL9mK6_C-6T1-YWeBeM8nB3ilmfPSBHCFx4-UbQr8MnQms3d9=w300

 

 

はじめに

ネットワークソリューション部の山田です。
インフラエンジニアとして日々業務に励んでおります。
今回は、自社で運用しているサーバを使用して、インフラ CI な環境を作って試してみた結果を本ブログにて公開いたします。
今更感は否めませんが、GitBucket から始まって、IaaS は DigitalOcean で プロビジョニングは Ansible で、という組み合わせは余り情報がなかったため、試してみた次第です。
インフラCIを試す際の参考となれば幸いです。

やりたいこと

GitBucket のリポジトリへ git push したら、インフラ構築/テストまで自動的に実行されるようにしたい。

登場人物と役割

GitBucket

GitHub クローンのバージョン管理ツール。
今回のインフラ CI では、各ソースコードをバージョン管理し、かつ Jenkins に対し API プッシュ(web hook)を行う。

Jenkins

CI ツール。今回のインフラ CI では、GitBucket の webhook を受けて、任意のシェルを叩く役割。
バージョン管理と仮想環境との仲介役、かつ Slack へジョブ結果の通知も行う。

Vagrant

仮想環境のフロントエンドツール。今回のインフラ CI では、DigitalOcean に対し仮想マシンを立ち上げたり削除したり、を担う役割。

DigitalOcean

海外製 IaaS。今回のインフラ CI では、仮想マシンを立ち上げる仮想基盤の役割。

Ansible

Python ベースの構成管理ツール。
今回のインフラ CI では、仮想マシン起動後のサーバプロビジョニングを行う役割。

Serverspec

サーバの状態をテストするフレームワーク。
今回のインフラ CI では、Ansible にてプロビジョニングされたサーバの Config 内容、プロセス起動状況などが正しい状態であるかどうかをテストするための役割。

Slack

Web コミュニケーションツール。
今回のインフラ CI では、Jenkins ジョブによるインフラ CI の開始、および Serverspec まで実行した一連のジョブの結果通知を受ける役割。

インフラ CI の流れ

大まかな一連の流れになります。

  1. GitBucket 上のリポジトリに、インフラ CI を構成する設定ファイル、およびソースコードをすべて commit する
  2. 1 のリポジトリに対し、git push
  3. git push を受けて GitBucket が Jenkins のジョブを webhook
  4. Jenkins ジョブが開始したことを Slack に通知
  5. Jenkins のジョブにて、Vagrant を通じて DigitalOcean の上で仮想マシンを新規に作成/起動するシェルスクリプトを実行
  6. DigitalOcean 上で仮想マシン起動後、Ansible を実行しサーバプロビジョニング
  7. プロビジョニング後、Serverspec にてサーバの状態をテスト
  8. ジョブ結果を Slack に通知

各バージョン等

  • OS(CIサーバ): CentOS 6.6 32bit
  • OS(仮想マシン): CentOS 6.5 64bit
  • GitBucket: 3.1
  • Jenkins: 1.613-1.1
  • Vagrant: 1.7.2-1
  • Ansible: 1.9.1-1
  • Serverspec: 2.17.0

環境セットアップ

各コンポーネントごとに、環境のセットアップ内容を記載します。
なお、各コンポーネント(GitBucket、Jenkins 等)の導入方法については省略し、インフラ CI を行う上でのセットアップ内容に限定し記載します。

GitBucket

GitBucket のセットアップについて記載します。
なお、GitBucket は公式の war ファイルを展開し、すでに Web アクセスできている状態とします。

GitBucket – webhook

webhook を設定します。
任意のリポジトリにアクセスし、[Settings]→[Service Hooks]に Jenkins ジョブの URL を登録。

WS000221

Jenkins

以下のプラグインを導入。

  • GIT client plugin
  • GIT plugin
  • Git server plugin
  • GitBucket Plugin
  • Slack Notification Plugin

インフラ CI 用のジョブを作成し、以下の要領で設定。

GitBucket リポジトリ URL

WS000202

Slack 通知

WS000203

ソースコード管理

WS000207

ビルド設定

WS000222

キックスクリプト

FileName: jenkins_digitalocean-ci.sh

スクリプトの補足。

  • vagrant up 前に必要なプラグインがインストールされているかどうか確認、無ければインストール
  • vagrant ssh-config で、仮想マシンへの ssh 情報を出力
  • Ansible インベントリファイルである hosts に、ssh-config に記載されている DigitalOcean 仮想マシンのグローバルアドレスを挿入置換
  • Serverspec の実行(rake spec)前に bundle install
  • 最後に vagrant destroy で仮想マシン削除/破棄
  • 途中の処理でリターンコードが 0 以外の場合には、その時点で vagrant destroy を実行
  • しかしながら、予測しない箇所でスクリプトが終了し、仮想マシンを破棄しないまま課金され続ける可能性もあるため、注意が必要

Vagrant

Vagrant で DigitalOcean を操作するためには、以下プラグインを導入する。

  • vagrant-digitalocean

また、Vagrant から DigitalOcean の API を叩く上で必要となる API-KEY/ACCESS-TOKEN などの情報を、Vagrantfile 内にハードコーディングすることを避けるため、dotenv も併せて導入する。

  • dotenv

Vagrantfile の内容は以下。

FileName: Vagrantfile

dotenv 定義ファイルの内容

※値は環境に応じて適宜変更

FileName: .env

DigitalOcean

DigitalOcean では、アカウントを作成し、前述に記載した .env に定義する各アクセス情報を取得する。

Ansible

今回はテストケースでの実施のため、Ansible で行うサーバプロビジョニングは最低限の内容としてます。

  • httpd インストール(RPM)
  • httpd 起動
  • httpd 自動起動有効化

Ansible PlayBook の内容は以下。

FileName: playbook.yaml

Ansible では、プロビジョニング対象サーバの ssh フィンガープリントが変更された場合、デフォルトでは PlayBook の実行が停止してしまう。
これを回避するため、Ansible の設定ファイルである ansible.cfg に設定を追加する。

FileName: ansible.cfg

Ansible のインベントリファイルも用意する。
インベントリファイルにはプロビジョニング対象サーバの宛先を指定する必要があるが、なんらかのクラウドサービスを利用する場合、仮想マシン作成/起動のたびに新たなグローバルアドレスが割り当てられる可能性がある。
このため、インベントリファイルである hosts の宛先は x.x.x.x とし、前述した Jenkins ジョブでキックするスクリプトにてこれをその都度置換する。

FileName: hosts

Serverspec

Serverspec では、Ansible でのサーバプロビジョニング後、サーバが正しい状態であるかをテストする。

  • httpd パッケージがインストールされているかどうか
  • httpd サービス/プロセスが起動しているかどうか
  • httpd サービス/プロセスの自動起動が有効となっているかどうか
  • TCP ポートの 80 番が Listen しているかどうか

FileName: httpd_spec.rb

本インフラ CI における Serverspec では、テストを行うサーバに対し ssh 経由でテストを実行する。
デフォルトでは Serverspec を実行するユーザの ~/.ssh/config にて秘密鍵等の情報を参照するが、クラウドサービスを利用する場合は都度情報が変わる可能性がある。(インスタンスを都度作成/破棄するため)
このため、上述したスクリプト内で vagrant ssh-config を出力した config を Serverspec から参照するよう、spec_helper.rb に手を加えている。
その一部を抜粋する。

FileName: spec_helper.rb

なお、Jenkins からキックするスクリプトでは、Serverspec 実行前に必要 gem をインストールするため bundle install を行っている。

FileName: Gemfile

Slack

Slack では、Jenkins ジョブの開始/終了を通知するために利用する。
前述した Jenkins ジョブ設定箇所を参考とし、プラグインの設定を行う。

Build

環境がひと通り揃ったところで、ビルドを行ってみる。
ビルドは Jenkins ジョブメニューの “ビルド実行” にて手動で試せるが、git push してビルドが走る流れが CI たる動きである。

↑が今回のインフラ CI にて利用しているリポジトリの内容。
ここに git push を行う。

git push を契機に、Jenkins ジョブが走る。

WS000211

Jenkins ジョブが開始されたこと、Slack に通知が飛ぶ。

WS000223

Jenkins ジョブのコンソール出力にて、スクリプトがキックされ Vagrant にて DigitalOcean の Droplet が作成される。

WS000224

実際に作成されたことを DigitalOcean のコントロールパネルからも確認。

WS000214

その後、Ansible の PlayBook が走っていることをコンソール出力にて確認。

failed なく完了した模様。

WS000225

続いて、bundle install されたのち、Serverspec も正常終了していることを確認。

WS000226

Slack へ Jenkins ジョブが Success の通知が飛ぶ。

WS000218

念のため DigitalOcean の Droplet が破棄されている確認。

WS000220

↑先ほど存在していた Droplet が消されている模様。

最後に

これまで全て手動で構築→テストをしていた身としては、大変新鮮な体験をした感覚でした。
1度インフラ CI の環境を作ってしまえば、構成変更に対して常に構築→テストを自動化できることになるため、”楽” で “確実” の一言に尽きます。
加えて、インフラ CI の環境づくりがそもそも楽しくて、すべてキレイに動いた時はさらに楽しかったです。
次なる個人研究の分野としては、何といっても “コンテナ”、そして Coreos を考えています。
コンテナ単位のサーバ実運用を見据え、アウトプットできればと考えてます。

以上です。

この記事を書いた人

アバター

山田 一道

管理職。元インフラエンジニアおよびスプラトゥーンエンジニアまたはApexLegendsエンジニア。