Google Cloud Platform（GCP）の Cloud SQL がフェイルオーバー際の挙動

　この記事は、[オールアバウト Advent Calendar 2016](http://qiita.com/advent-calendar/2016/allabout)の17日目の記事です。
　今日は Google Cloud Platform （以下 GCP）のストレージサービスの Cloud SQL がフェイルオーバー際に、レプリカの挙動について、ちょっと話したいと思います。

# Cloud SQL とは
　皆さんはご存知だと思いますが、Cloud SQL は、Google が提供する使いやすいフルマネージドの MySQL データベースです。
　Cloud SQL は第1世代と第2世代ご提供されています。
　今日は第2世代について、話します。

# レプリカ
　第2世代の Cloud SQL レプリカは以下の二種類があります。
　・フェイルオーバーレプリカ
　・リードレプリカ

#### フェイルオーバーレプリカ
　名前の通り、マスターインスタンスは何か障害が発生する時、フェイルオーバーして、マスターを昇格するインスタンスです。必ずマスターインスタンスと同じマシンタイプです。

#### リードレプリカ
　リードレプリカは単純にマスターインスタンスとレプリケーションを組んでいるスレーブインスタンスです。フェイルオーバー機能は提供されません。マスターインスタンスと異なるマシンタイプでも大丈夫です。

# フェイルオーバー際の挙動
　フェイルオーバーする時に、フェイルオーバーレプリカとリードレプリカの挙動を確認するため、手動で発動します。

#### フェイルオーバー
　下記のコマンドを実行して、settingsVersion フィールドの値を取得します。

```bash
$ ACCESS_TOKEN="$(gcloud beta auth application-default print-access-token)"
$ curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
 --header 'Content-Type: application/json' \
 https://www.googleapis.com/sql/v1beta4/projects/[PROJECT-ID]/instances/[MASTER_INSTANCE_NAME] \
 -X GET
```
　*[PROJECT-ID]* と *[MASTER_INSTANCE_NAME]* は各自の環境に合わせて書き換えます。

　結果：

```
{
 "kind": "sql#instance",

 ......

 "state": "RUNNABLE",
 "backendType": "SECOND_GEN",
 "databaseVersion": "MYSQL_5_6",
 "region": "asia-northeast1",
 "settings": {
  "kind": "sql#settings",
  "settingsVersion": "12",           ← ここ
  "authorizedGaeApplications": [],
  "tier": "db-n1-standard-1",
  "backupConfiguration": {
   "kind": "sql#backupConfiguration",
   "startTime": "16:00",
   "enabled": true,
   "binaryLogEnabled": true
  },

 ......
```
　次は下記のコマンドでフェイルオーバーを実施します。

```bash
$ curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
 --header 'Content-Type: application/json' \
 --data '{"failoverContext":{"settingsVersion":"[SETTINGS_VERSION]"}}' \
 https://www.googleapis.com/sql/v1beta4/projects/[PROJECT-ID]/instances/[MASTER_INSTANCE_NAME]/failover \
      -X POST
```
　*[SETTINGS_VERSION]* は先程取得された値で書き換えます。
　*[PROJECT-ID]* と *[MASTER_INSTANCE_NAME]* は各自の環境に合わせて書き換えます。

#### レプリカの挙動
　1、フェイルオーバー開始
　フェイルオーバーコマンドを実行する直後、マスターインスタンスのアイコンが黄色い三角になりまして、フェイルオーバーレプリカのアイコンが回っていて、昇格している模様です。
![cloudsql1.jpg](https://qiita-image-store.s3.amazonaws.com/0/57618/a3ffe3db-5980-5244-56a1-2c4eeaefc734.jpeg)

　2、新しいフェイルオーバーレプリカを立ち上がる
　元のフェイルオーバーレプリカインスタンスがマスターインスタンスに昇格した後、新しいフェイルオーバーレプリカインスタンスを立ち上がります。
![cloudsql2.jpg](https://qiita-image-store.s3.amazonaws.com/0/57618/5dd31a41-7ec7-30f0-96c8-d73dfd6a96d4.jpeg)
　フェイルオーバー開始から終了まで、30秒ぐらい、ダウンタイムが発生します。この時点に、ブラウザでサービスへアクセスする場合、データベースが接続できないため、「MySQL server has gone away」ページが表示されます。

　3、リードレプリカを再作成
　ここの挙動が一番不思議です。マスターインスタンスが立ち上がって、新しいフェイルオーバーレプリカを作成する時に、リードレプリカはマスターインスタンスとのレプリケーションを再構築しなくて、インスタンス自体再作成されたんですね。
![cloudsql3.jpg](https://qiita-image-store.s3.amazonaws.com/0/57618/994bbb7d-b202-95e9-41fd-f61979820f73.jpeg)
　この挙動について、Google のサポートにも問い合わせしました。以下は Google サポートからの回答です。
> リードレプリカを再作成しますので、１分間位に接続することできません。
> 結論的に、フェイルオーバーが発生する時にリードレプリカのダウンタイムも発生します。
> ダウンタイムのタイミングについて、新マスタ交換後にリードレプリカを再作成されます。

　そうすると、参照系のアプリもフェイルオーバーする際にサービスダウンが発生しますね。:thinking:

　4、正常状態に戻る
　1分ぐらい立って、すべてのインスタンスが立ち上がりましたね。
![cloudsql4.jpg](https://qiita-image-store.s3.amazonaws.com/0/57618/86172a2e-56b4-1b01-1f84-1d1c43e25c39.jpeg)

# 結論
- フェイルオーバーする時、マスターインスタンスに接続するサービスは30秒ほどダウンタイムが発生します。
- フェイルオーバーする時、リードレプリカも再作成されます。
- リードレプリカが再作成されるため、リードレプリカに接続するサービスは1分ほどダウンタイムが発生します。