ApplibotのBlue-Green Deployment(GCP編)

こんにちは。アプリボットのsysopチームです。
前回のAWSでの「Blue-Green Deployment」に続いて、GCPでも同じ構成で構築してみました。
GCPのBlue-Greenについて紹介させて頂きます。

GCPでのBlue-Green Deployment詳細

手順についてgcloudを使用した例と共に解説させていただきます。
以下の設定、サービスを使用しています。

構成要素

サービス名 役割 必要数 備考
HTTP(S)LoadBalancer ロードバランサ 2台 本番・確認用の2つが存在、到達先はBackendを指定
BackendService リクエストを受け取る 2グループ ロードバランサとの紐付けは固定
InstanceGroup サーバ(GCE)の起動管理 2グループ どのbackendServiceに属するかを指定
GCE サーバ n台(アプリによる) 起動時に最新のソースが展開されている状態となるよう設定済み

概要

BlueGreen概要.png

図の通り、実際に入れ替え操作を行なっているのはBackendserviceに設定するInstanceGroupの登録先のみになります。

実行手順

1.GCPのgcloudコマンドをインストールする

https://cloud.google.com/sdk/downloads?hl=ja

2. Standby BackendServiceに紐付くInstanceGroupでサーバ起動

BlueGreen1.png

新バージョンのコードがデプロイされたサーバをStandby BackendService経由でアクセスできるようにする。

スクリプト内で使用する変数
ACTIVE_BACKEND_NAME              (BackendServiceのActive用)
STANDBY_BACKEND_NAME             (BackendServiceのStandby用)
IG_NAME_BLUE                     (インスタンスグループのBlue用)
IG_NAME_GREEN                    (インスタンスグループのGreen用)
ZONE                             (ゾーン)
PROJECT_ID                       (GCPのプロジェクトID)
NUM                              (起動台数)
deploy_standby_httplb.sh
#!/bin/bash
NUM="起動台数"
# Standby側のbackendに紐付くインスタンスグループ名を取得    
STANDBY_IG_NAME=$(basename `gcloud compute backend-services get-health ${STANDBY_BACKEND_NAME} \
    --global | grep backend: | awk '{print $2}'`)
# Standby側のインスタンスグループでGCEを起動
gcloud compute instance-groups managed resize ${STANDBY_IG_NAME} \
    --size=${NUM} \
    --zone=${ZONE} \
    --project ${PROJECT_ID}

3. 起動後、確認用環境へアクセスチェック

テスト用端末から、Standby HTTP(S)LBへアクセスし、新規追加部分での不具合がないか最終確認。

4. Standby側⇄Active側のサーバ切り替え

BlueGreen2.png

ここでBlueとGreenを切り替えます。
Rollbackの際は再度この部分を実行するだけです。

注意点
この時、ダウンタイムが発生しないよう新旧のバージョンが1分程混ざることを許容しています。

deploy_active_httplb.sh
#!/bin/bash
# Active側のbackendに紐付くインスタンスグループ名を取得    (図 InstanceGroup [Blue])
ACTIVE_IG_NAME=$(basename `gcloud compute backend-services get-health ${ACTIVE_BACKEND_NAME} \
    --global | grep backend: | awk '{print $2}'`)
# Standby側のbackendに紐付くインスタンスグループ名を取得   (図 InstanceGroup [Green])  
STANDBY_IG_NAME=$(basename `gcloud compute backend-services get-health ${STANDBY_BACKEND_NAME} \
    --global | grep backend: | awk '{print $2}'`)
## backendの入れ替えを実施
# [1] Active BackendServiceからInstanceGroupに追加する。
gcloud compute backend-services add-backend ${ACTIVE_BACKEND_NAME} \
    --instance-group=${STANDBY_IG_NAME} \
    --global \
    --instance-group-zone=${ZONE} \
    --project ${PROJECT_ID}
# [2] Active BackendServiceからInstanceGroupを外す。
gcloud compute backend-services remove-backend ${ACTIVE_BACKEND_NAME} \
    --instance-group=${ACTIVE_ASG_NAME} \
    --global \
    --instance-group-zone=${ZONE} \
    --project ${PROJECT_ID}

sleep 60
# [3] Standby BackendServiceからInstanceGroupに追加する。
gcloud compute backend-services add-backend ${STANDBY_BACKEND_NAME} \
    --instance-group=${ACTIVE_IG_NAME} \
    --global \
    --instance-group-zone=${ZONE} \
    --project ${PROJECT_ID}
# [4] standby backendServiceからInstanceGroupを外す。
gcloud compute backend-services remove-backend ${STANDBY_BACKEND_NAME} \
    --instance-group=${STANDBY_IG_NAME} \
    --global \
    --instance-group-zone=${ZONE} \
    --project ${PROJECT_ID}

5. 旧バージョンのGCEインスタンスを削除

BlueGreen3.png

delete_standby_asg.sh
#!/bin/bash
# 削除の為、台数は0台に設定
NUM="0"
# Standby側のbackendに紐付くインスタンスグループ名を取得    
STANDBY_IG_NAME=$(basename `gcloud compute backend-services get-health ${STANDBY_BACKEND_NAME} \
    --global | grep backend: | awk '{print $2}'`)
# instance台数変更
gcloud compute instance-groups managed resize ${STANDBY_IG_NAME} \
    --size=${NUM} \
    --zone=${ZONE}  \
    --project ${PROJECT_ID}

6.RollBack

サービスインした時に問題が発生してしまっても、
素早く戻せるのがBlueGreenのいいとこです。
4.で記載した通り、4の手順のコマンドを実行する事で戻すことができます。

AWSとGCPの役割を比較

役割 AWS GCP
ロードバランサ ApplicationLoadBalancer HTTP(S)LoadBalancer
リクエストを受ける TargetGroup BackendService(★)
サーバ起動管理 AutoScalingGroup(★) InstanceGroup
サーバ EC2 GCE

★接続先切り替えポイント

GCPでハマった部分になりますが、AWSとGCPのBlue-Greenの切り替えポイント
が異なる点でした。

AWSではAutoscalingGroup側で接続先(TargetGroup)を切り替えているのに対して、
GCPではInstanceGroup自体に接続先設定を持っていませんでした。
Backendservice側で接続先(InstanceGroup)を切り替えていました。

環境構築自体はそれほど、難しくはなかったのですが、
GCPコンソール上(GUI)とgcloudコマンド(CUI)の役割と設定箇所が異なっていて、
公式ページやgcloudコマンドのリファレンスなどを調査するのに時間がかかってしまいました。

例) GCPコンソール上では負荷分散(ロードバランサ)からbackendServiceを設定できますが、
・gcloudコマンド上ではロードバランサ自体の項目がどこにも見当たらなく。
・BackendServiceとロードバランサが固定で紐づいていることに気づきました。
・gcloudコマンド上は、ロードバランサを意識する必要がないようです。
結果的にBackendServiceでInstanceGroupを設定することができて、問題解消となりました。

まとめ

今回、AWSで行なっていることをそのままGCPでやろうとした時に、
なんとなく同じようなこのサービスでいけるんじゃないか、
と思い検証してみましたが、改めて違いを感じることができました。

今後はコンテナで構成するプロジェクトもあり、そちらも検証中です。
AWSでもEKS/Fargateが発表され盛り上がっていますが、
それぞれのサービスを比較、検証し理解して使用していきたいと思います。

アプリボットのインフラチームではAWS/GCP環境でアプリケーション構築、
コンテナ、自動化、モニタリング等に興味がある方を募集しています!
興味がある方は是非連絡を下さい。