CodeDeployでELBヘルスチェックによるローリングアップデート
渡辺です。
AWS CodeDeployでは複数サーバにアプリケーションをデプロイできます。 この時、どの程度並列にデプロイするかを決めるのがデプロイ設定です。
デプロイ設定は、AllAtOnce
、HalfAtATime
、OneAtATime
から選択します。
AllAtOnce
は全サーバを並列にデプロイします。
一方、OneAtATime
は並列にデプロイを行わず、ひとつのサーバのデプロイ完了を待って次のサーバのデプロイを行います。
HalfAtATime
は半分ずつのグループにわけ、各グループが成功した後に残りのグループをデプロイします。
OneAtATime
を使えばローリングアップデートとなるわけですが、実際にはデプロイ後にELBのヘルスチェックが通るまでタイムラグがある点に注意しなければなりません。
リリース時のサービス断を発生させない
デプロイ(リリース)時のサービス断を発生させない有名な方法は、Blue/Greenデプロイメントです。 Blue/Greenデプロイメントでは、デプロイ環境を2セット用意します。 リリース(デプロイ)時には、利用していない環境にデプロイを行い、ELBの向き先をデプロイした新しいバージョンの環境に切り替えるなどして実現します。 しかし、Blue/Greenデプロイメントは手間がかかります。
もうひとつのサービス断を発生させない手法はローリングアップデートです。 ELBなどでサーバーが冗長化されているならば、1台づつ(もしくは半分づつ)のデプロイ(リリース)を行い、サービス断を回避する手法です。 一時的に新旧のアプリケーションが混在するタイミングが出来てしまいますが、そのデメリットが小さいならば有効な手法です。
今日はCodeDeployで確実なローリングアップデートを行う方法を紹介します。
ELBのヘルスチェックが通るまでデプロイを完了としない
CodeDeployでのローリングアップデートは、デプロイ設定でHalfAtATime
またはOneAtATime
を設定すれば良さそうです。
しかし、実際にはELBからのヘルスチェックが成功する前にデプロイが完了してしまいます。
それではエンドユーザからの視点ではサービスが一時的に利用できないことになります。
ELBのヘルスチェックが通までデプロイ完了を待機させなければなりません。
ValidateServiceフックでデプロイ完了まで待機する
通常、CodeDeployでデプロイを行う時、次のような手順で行います。
- ミドルウェアの停止(
ApplicationStop
) - アプリケーションのダウンロードと配置(
DownloadBundle
) - ミドルウェアの起動(
ApplicationStart
) - サービスの起動確認(
ValidateService
)
ValidateService
で、ELBのヘルスチェックが成功するまで待機させます。
validate.sh
次のスクリプトは、ValidateService
のサンプルです。
#!/bin/sh ELB_NAME="{{ elb_name }}" INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) while :; do stat=$(aws elb describe-instance-health --region ap-northeast-1 --load-balancer-name $ELB_NAME --instances $INSTANCE_ID --query InstanceStates[0].State) if [ `echo $stat | grep 'InService'` ] ; then exit 0 fi sleep 5 done
実行中のインスタンスIDを取得し、aws cliでELBにおけるステータスを取得しています。
appspec.yml
ValidateService
を指定したappspec.yml
です(抜粋)。
--- hooks: ApplicationStop: - location: hooks/stop.sh timeout: 30 runas: root ApplicationStart: - location: hooks/start.sh timeout: 15 runas: root ValidateService: - location: hooks/validate.sh timeout: 300 # 5min runas: root
タイムアウトはELBのヘルスチェックとアプリケーションの起動時間との兼ね合いで調整してください。
まとめ
ValidateService
でELBのヘルスチェックでInService
になったことを確認するまで待機すれば、サービス断は発生しません。
デプロイ時間は増えますが、確実なローリングアップデートが必要な場合は参考にしてください。