EatSmartシステム部ブログ

ウェブサイトの開発や運営に関する情報です。

もぐナビで行ったデプロイの改善

昨年までもぐナビで行ったデプロイの改善を書きたいと思います。

これまでのデプロイには手作業が含まれるためいくつか問題点がありました。
これを、Jenkins/Balancer Managerを利用しすることで、安全かつサービスが停止することなくデプロイを行えるようにしました。

これまでのデプロイ

もぐナビはJavaをベースに各種ライブラリ、独自フレームワークを利用して構築されています。
リバースプロキシにApacheを、バックエンドにTomcatを利用しています。
これまでは、以下の手順でデプロイを行っていました。

  1. 各バックエンドサーバにsshでログインを行う
  2. svnから最新のファイルをチェックアウト
  3. antでjavaをビルド
  4. Tomcatのリスタート

この方法には、以下の様な問題点がありました。

  1. 全て手作業のため、人為的ミスが発生する可能性がある
  2. デプロイ中に503エラーが発生する
  3. デプロイに失敗した場合にサービスが停止してしまう

最初の改善:Jenkinsの導入

最初の改善として、Jenkinsの導入を行い手作業で行っている箇所を自動化することにしました。
合わせてビルドを各サーバで行うのではなく、Jenkinsで行う用にします。
これにより、デプロイごとの成果物を管理することができるため、切り戻しや障害発生時の調査が行えるようになりました。

Jenkinsのジョブで以下の処理をシェルスクリプトで実行するようにしました。

  1. Jenkinsでsvnから最新のファイルをチェックアウト
  2. Jenkinsでantでjavaをビルド
  3. サーバAへデプロイ
  4. サーバBへデプロイ
  5. 以下同様

これにより、デプロイはボタンひとつで安全に行う事ができるようになり、問題点の1が解決しました。

またこれとは別に、Jenkinsで定期的なテストも実行しています。
これにより、不完全な状態でコミットされた場合もリリース前に検知出来るようになりました。

次の改善:Balancer Managerの利用

デプロイは安全に出来るようになりましたが、引き続き問題点の2,3が残っています。
特に問題点の2はサービスを快適に利用してもらう上で解決しなければならないものです。
これを解決するため、ApacheにBalancer Managerを導入し、デプロイ中のサーバにリクエストを振り分けを行わないようにします。

Balancer Managerの導入

httpd.confの以下の行のコメントを解除します。

LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

アクセスするための設定を追加します。
今回は社内とJenkinsからのみアクセス出来るようにしました。

ProxyPass /balancer-manager !
<Location /balancer-manager>
  SetHandler balancer-manager
  Order deny,allow
  Deny from all
  Allow from xxx.xxx.xxx.xxx
</Location>

/balancer-managerへ接続すると、管理画面にアクセスすることが出来るようになります。

デプロイへの組み込み

Jenkinsのジョブを以下のように変更しました。
デプロイを行う前にリクエストの振り分けを停止し、起動を確認してから再開するようにしました。

  1. Jenkinsでsvnから最新のファイルをチェックアウト
  2. Jenkinsでantでjavaをビルド
  3. サーバAへリクエストの振り分けを停止
  4. サーバAへデプロイ
  5. サーバAの起動を確認
  6. サーバAへリクエストの振り分けを再開
  7. サーバBへリクエストの振り分けを停止
  8. 以下同様

これにより、問題点の2を解決することが出来ました。

リクエストの振り分けを再開する前に正常にデプロイが行えたかを確認し、万が一失敗した場合は以降の処理を停止するようにしました。
これにより、問題点の3を解決することが出来ました。

リクエストの振り分けの停止・再開には以下のようなスクリプトを用意して行っています。

#!/bin/bash

# 1:balancer_managerのURL
# 2:balancer名(balancer://xxxxのxxxx)
# 3:enable/disable
# 4:Worker URL

set -e

print_usage()
{
 echo "Usage: $0 http://balancer-manager-url balancer-name enable|disable http://worker-url"
}

WORKER_URL=$4
ACTION=$3

if [ "${WORKER_URL}" == "" ]; then
  print_usage
  exit 1
fi
if [ "${ACTION}" == "" ]; then
  print_usage
  exit 1
fi

BALANCER_MANAGER_URL=$1
BALANCER_NAME=$2
BALANCER_NONSE=`curl -s ${BALANCER_MANAGER_URL}  | sed -n "/href=/s/.*href=\([^>]*\).*/\1/p" | tail -1 | sed -n "s/.*nonce=\(.*\)\"/\1/p"`

if [ "${BALANCER_NONSE}" == "" ]; then
  echo "Could not extract nonce from ${BALANCER_MANAGER_URL}"
  exit 1
fi

curl -s "${BALANCER_MANAGER_URL}?b=${BALANCER_NAME}&w=${WORKER_URL}&dw=${ACTION}&nonce=${BALANCER_NONSE}"

まとめ

以上で安全かつサービスが停止することなくデプロイを行えるようになりました。
リバースプロキシとしてApacheを利用している場合はBalancer Managerの導入は容易なので、同様の問題がある場合は手軽に改善出来ると思います。