GCPの負荷分散を使ってWebアプリの冗長構成を作ってみた

タイトル通り。
この記事で作成する環境の全体図は以下の通り。

GCE (Google Compute Engine)を2つ立てる

VMを作成する。設定は以下の図の通り。

このVMをもう一つ立てる。「VMインスタンス」ページで確認するとこんな感じ。

簡単なWebアプリケーションをデプロイ

以前作ったシンプルなWebアプリケーションを使う。
GitHubにソースコード載せてる。

参考程度に必要なコマンドを載せとく。

# yum -y install docker git
# systemctl start docker
# systemctl enable docker
# curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
# git clone https://github.com/tetsis/nginx-gunicorn-django-postgres.git
# cd nginx-gunicorn-django-postgres/
# sed -i -e "s/443:443/80:80/" docker-compose.yml (外部公開するポートをHTTPの80に変更する)
# docker-compose build
# docker-compose up -d
# docker-compose ps

インスタンスグループを作る

インスタンスグループを作成する。

  • ロケーション:「シングルゾーン」
  • グループタイプ:「非マネージドインスタンスグループ」
  • VMインスタンス:さっき作った2つのVMを追加する

(本当は障害耐性を上げるためマルチゾーンでやりたかったけど、マルチゾーンかつ非マネージドでやる方法が見つからなかった)

作成後の「インスタンスグループ」ページ。

HTTP(S)負荷分散(ロードバランサ)を作る

「負荷分散」からロードバランサを作成する。
HTTP(S)負荷分散の「設定を開始」をクリック。

バックエンドの設定

「バックエンドの設定」->「バックエンドサービスとバックエンドバケットの作成または選択」->「バックエンドサービス」->「バックエンドサービスを作成」
バックエンドサービスの設定項目はこんな感じ。

途中ヘルスチェックを作成する。

作成完了するとこんな感じ。

ホストとパスのルール

ここは特に設定しなくてOK。URLパスに応じてバックエンドを変えたい場合に設定するんだろう。

フロントエンドの設定

「フロントエンドの設定」はこんな感じ。

途中、証明書を設定する。
「証明書を選択してください」->「新しい証明書の作成」で公開鍵証明書、証明書チェーン(あれば)、秘密鍵を入力する。

作成完了

詳細ページ。

ロードバランサ経由でWebアプリケーションにアクセスする

ロードバランサのフロントエンドにつけられたグローバルIPアドレスにブラウザでアクセスする。

いい感じ。

GCP Cloud SQLでフェイルオーバーを試してみた

GCPの無料トライアル期間が終わりそうなので、クーポンが残ってるうちにいろいろ試してみようと思い立ち、ずっと気になっていたクラウドサービスのRDB (Relational Database)を使ってみた。
特にサーバで障害が発生した際のサーバ切替(フェイルオーバー)がどんな感じで使えるか試してみた。
ちなみにデータベースはPosgtreSQLを使用。

以下の流れで実験してみた

  1. Cloud SQLインスタンスを作成
  2. SQLインスタンスのPostgreSQLユーザとデータベースを作成
  3. Compute Engineインスタンスを作成
  4. Compute Engineにデータベースを使った簡単なWebアプリケーションをデプロイ
  5. フェイルオーバーを実施

Cloud SQLインスタンスを作成

GCPのコンソールから「SQL」->「インスタンスを作成」でDBサーバのインスタンスを作成する。
今回はPostgreSQLを選択。

設定内容は以下の図を参照。
特筆する点は、1. 「接続の設定」で「プライベートIP」を追加、2. 「自動バックアップと高可用性の有効化」で「高可用性」をチェックすること。

プライベートIPにチェックを入れる
高可用性(リージョン)にチェックを入れる

作成が完了するとSQLインスタンス一覧に表示される。

VMと繋ぐためのIPアドレス情報はインスタンス名をクリックし、「インスタンスの詳細」ページで確認できる。

パブリックIPアドレスもついているが、今回はプライベートIPアドレスを利用する。(パブリックのほうは無効にしてインスタンス作ったほうが良かったかも)

SQLインスタンスのPostgreSQLユーザとデータベースを作成

ユーザ作成

「インスタンスの詳細」->「ユーザ」->「ユーザアカウントを作成」でPostgreSQLユーザを新たに作成する。

「ユーザ名」と「パスワード」を設定する。
(今回はユーザ名:django、パスワード:djangoでやってます)

今作成したユーザが表示される。

データベース作成

「インスタンスの詳細」->「データベース」->「データベースを作成」でデータベースを新たに作成する。

「データベース名」を設定する。

今作成したデータベースが表示される。

Compute Engineインスタンスを作成

GCPのコンソールから「Compute Engine」->「VMインスタンス」->「VMインスタンスを作成」でインスタンスを作成する。
設定内容は以下の図を参照。

作成が完了するとVMインスタンス一覧に表示される。

Compute Engineにデータベースを使った簡単なWebアプリケーションをデプロイ

VMインスタンスのほうにログインして、必要な設定をする。最低限Git, Docker, Docker Composeはインストールすること。

Webアプリケーションをインストール

今回はテスト用に自作したシンプルアプリケーションを利用する。

# git clone https://github.com/tetsis/nginx-gunicorn-django-postgres.git
# cd nginx-gunicorn-django-postgres/

docker-compose-without-postgres.ymlを編集し、接続先データベースのIPアドレスをさっき作ったSQLインスタンスのものに変更する。

version: '3'
services:
nginx:
image: nginx:1.12.2-alpine
ports:
- "80:80"
- "443:443"
depends_on:
- django
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/certs:/etc/pki/nginx/certs
- ./src/static:/var/www/static
django:
build: ./django
env_file: ./django/.django_env
environment:
DATABASE_HOST: "10.122.0.2" # ここをSQLインスタンスのプライベートIPアドレスに変更する
volumes:
- ./src:/usr/src/django
command: gunicorn app.wsgi -b 0.0.0.0:8080

Webアプリケーションの実行と動作確認

Docker Composeでアプリケーション実行する。

# docker-compose -f docker-compose-without-postgres.yml up -d

docker-compose psコマンドで正常起動しているか確認

# docker-compose ps
Name                                Command               State                    Ports
---------------------------------------------------------------------------------------------------------------------------
nginx-gunicorn-django-postgres_django_1   gunicorn app.wsgi -b 0.0.0 ...   Up
nginx-gunicorn-django-postgres_nginx_1    nginx -g daemon off;             Up      0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp

データベース初期化

以下のコマンドでデータベースを初期化する。
自作スクリプトだけど中身はdjangoのmigrateしてるだけ。

# docker exec nginx-gunicorn-django-postgres_django_1 ./init.sh

アプリケーションにアクセス

ブラウザで「https://(Compute Engineの外部IPアドレス)/」にアクセスする。
すると以下のような画面が表示される。

「Save」をクリックすると、その時間をDBに保存して画面に表示するだけのシンプルなもの。

フェイルオーバーを実施

今回メインテーマのフェイルオーバー。
本来はメインのサーバ(マスター)が障害等でシャットダウンした際に発生するものだが、Cloud SQLには手動でフェイルオーバーする機能がついているので、今回はその機能を使ってサービス断時間を計ってみる。
「インスタンスの詳細」画面の右上にある「フェイルオーバー」から手動でフェイルオーバーを実行する。

Webアプリケーションの時間記録の機能を使って、サービス断時間を計ってみた。

正確なDBサービス断時間ではないがアプリケーションからみた断時間は38秒間だった。
結構いい感じ。