GCP - 複数リージョンに配置したGCEに負荷分散する

Assosiate Cloud Engineer 取得の勉強中にやった内容です。取得してしまうと、1ヶ月くらいで忘れてしまったので、残しておきます。

## Overview
構成のイメージです。
![無題のプレゼンテーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525959/37fd4659-ac14-f1b3-ce30-d3fa5e76e645.png)


## ToDo
- 構築手順
  - プロジェクトを作る。
  - GCEインスタンスを作る。
  - 作ったインスタンスのスナップショットを取得する。
  - スナップショットからイメージを作る。
  - インスタンステンプレートを作る。
  - インスタンスグループを作る。
  - 負荷分散する。
  - プロジェクトを削除する。

- 更新
  - インスタンステンプレートの更新
  - ローリングアップデート

- 確認
  - 負荷分散
  - 縮退
  - オートスケール

## Procedure
### Create a new project
あとですぐに消せるように、一時的なプロジェクトを作成します。

1. 画面の上にある [Select a project] を選択する。
2. [NEW PROJECT] を選択する。
3. 「Project Name」に任意の名前を入れる。<br>  グローバルで一意になるように、IDには数字が付与される。
4. [Create]を選択する。

### Create a VM instance
GCEインスタンスを作成します。

1. ハンバーガーから、「Compute Engine - VM instances」を選択する。
2. [Create]を選択する。
3. 任意で設定値を入れる(※今回の設定値は、下表)。

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|instance-1|←|任意の名前|
    |Labels|n/a|n/a||
    |Region|us-central1(Iowa)|←|Always Freeの範囲内で|
    |Zone|us-central1-a|←|同上|
    |Machine Family|General-purpose|←|同上|
    |Series|N1|←|同上|
    |Machine Type|f1-micro|←|同上|
    |Container|No|←|今回はコンテナは使わないので|
    |Boot Disk|Debian GNU/Linux 9 (strech)|←|とりあえずDebianで。|
    |Service Account|Compute Engine default service account|←|今回はデフォルト|
    |Access scope|Allow default access|←|同上|
    |Firewall|None|HTTP,HTTPS|HTTP(S)通信を許可|



4. [Create]を選択する。
4. 一覧に「instance-1」が表示されて、:white_check_mark:がついていれば、OK。


### Configure VM instance
GCEインスタンスの設定を行います。今回はnginxを入れて、HTTPリクエストに応答できるようにだけします。

1. ハンバーガーから、「Compute Engine」を選択する。

2. さっき作成したインスタンスの右にある[SSH]を選択する。

6. Stackdriver Monitoring Agent のインストール

    ```Shell:
    $ curl -sSO https://dl.google.com/cloudagents/install-monitoring-agent.sh
    $ sudo bash install-monitoring-agent.sh
    ```


7. Stackdriver Monitoring Agent の状態確認(active(running)ならOK)。

    ```Shell:
    $ sudo systemctl status stackdriver-agent
    ```

3. パッケージの最新化を行う。

    ```Shell:
    $ sudo apt update && sudo apt -y upgrade
    ```

4. nginxをインストールする。

    ```Shell:
    $ sudo apt -y install nginx
    ```

5. nginx の状態を確認する(active(running)ならOK)。

    ```Shell:
    $ sudo systemctl status nginx
    ```
6. HTMLファイルの書き換え

    ```Shell:
    $ echo "OK" | sudo tee /var/www/html/index.nginx-debian.html 
    ```

6. nginx 動作確認(OKと出ればOK)。

    ```Shell:
    $ curl http://localhost/
    OK
    ```

1. GCEインスタンスのシャットダウン

    ```Shell:
    $ sudo shutdown -h now
    ```

### Create a snapshot of VM instance
作ったGCEインスタンスのスナップショットを作成します。

1. ハンバーガーから、「Compute Engine - Snapshots」を選択する。

2. [Create snapshot]を選択する。

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|snapshot-1|←|任意の名前|
    |Description|n/a|←||
    |Source Disk|-|instance-1|さっき作ったGCEインスタンス|
    |Location|Multi-regional - us|←||

3. [Create]を選択する。
4. 一覧に「snapshot-1」が表示されて、:white_check_mark:がついていればOK。


### Create a VM Image
作ったGCEインスタンスのスナップショットから、VMのイメージを作成します。

1. ハンバーガーから、「Compute Engine - Image」を選択する。
2. [CREATE IMAGE]を選択する。
3. 以下の項目を入力する。

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|image-1|←|任意の名前|
    |Source|Disk|Snapshot||
    |Source snapshot|-|snapshot-1|さっき作ったスナップショット|
    |Location|Multi-regional - us|←||

4. [Create]を選択する。
5. 一覧に「image-1」が表示されて、:white_check_mark:がついていればOK。


### Create a VM instance template
インスタンステンプレートを作ります。

1. ハンバーガーから、「Compute Engine - Instance Template」を選択する。
2. [Create instance template]を選択する。
3. 以下の項目を入力する。

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|instance-template-1|←|任意の名前|
    |Machine Family|General-purpose|←|Always Freeの範囲内で|
    |Series|N1|←|同上|
    |Machine Type|f1-micro|←|同上|
    |Container|No|←|今回はコンテナは使わないので|
    |Boot disk|Debian GNU/Linux 9 (stretch)|**image-1**|さっき作ったイメージ|
    |Service Account|Compute Engine default service account|←|今回はデフォルト|
    |Access scope|Allow default access|←|同上|
    |Firewall|None|HTTP,HTTPS|HTTP(S)通信を許可|

4. [Create]を選択する。
5. 一覧に「instance-template-1」が表示されて、:white_check_mark:がついていればOK。


### Create a Instance group
インスタンスグループを作ります。

1. ハンバーガーから、「Compute Engine - Instance Group」を選択する。
2. [Create instance group]を選択する。
3. 以下の項目を入力する。

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|instance-group-1|←|任意の名前|
    |Description|-|←||
    |Location|Single Zone|←|今回は単一ゾーンで|
    |Region|us-central1 (Iowa)|←|今回はここで|
    |Zone|us-central1-a|←|同上|
    |Instance template|-|**instance-template1**|さっき作ったテンプレート|
    |Number of insrances|Based on autoscaling configration|←|オートスケールに依存|
    |Autoscalling mode|Autoscale|←||
    |Autoscalling metric|CPU utilization 60%|←|CPU60%でスケール。余裕を持った設定なので要件に応じて調整。|
    |Cool down period|60sec|←||
    |Minimum number of instances|1|←|ひとまず、1台から|
    |Maximum number of instances|10|**2**|動きが見られればよいので、2。|
    |Autohealing - health check|No health check|**http-check(TCP:80)**|TCPレベルでのヘルスチェックを追加|
    |Initial delay|300sec|←|とりあえずデフォルト。5分あれば上がってくるでしょう。|

4. [Create]を選択する。
5. 一覧に「instance-template-1」が表示されて、:white_check_mark:がついていればOK。

6. 同様に別リージョンのグループも作っておきます(異なる項目のみ記載)。

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|instance-group-1|**instance-group-2**|任意の名前|
    |Region|us-central1 (Iowa)|**us-west1 (Oregon)**|リージョンわける|
    |Zone|us-central1-a|**us-west1-b**|同上|

4. [Create]を選択する。
5. 一覧に「instance-template-2」が表示されて、:white_check_mark:がついていればOK。


### Create a Load balancer
負荷分散装置を作ります。

1. ハンバーガーから、「Network services - Load balancing」を選択する。
2. [Create load balancer]を選択する。
3. 「HTTP(S) Load Balancing」の[Start Configuration]を選択する。
4. 「from internet to my VMs」を選択する。
5. [continue]を選択する。
3. 以下の項目を入力する。

 
    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|-|load-balancer-1|任意の名前|

    Backend Configuration1

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|-|**backend-1**|任意の名前|
    |Backend type|Instance group|←||
    |Protocol, named port & timeout|HTTP,http,30sec|←||
    |Instance group|-|**instance-group-1**|ひとつめのグループ|
    |Port numbers|80|←||
    |Balancing mode|Utilization|←|とりあえずデフォルト|
    |Maximum backend utilization|80%|←|同上|
    |Capacity|100%|←|同上|
    |Healtch check|**http-check(TCP)**|←|HTTPでヘルスチェック|
    |Logging|yes|←||

    Backend Configuration2(異なる項目のみ)

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Instance group|-|**instance-group-2**|ふたつ目のグループ|

    Frontend Configuration

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|-|**frontend-1**|任意の名前|
    |Protocol|HTTP|←||
    |Network Service Tier|Premium|←||
    |IP Version|IPv4|←||
    |IP address|Ephemeral|←||
    |Port|80|←||


7. [Create]を選択する。
4. 一覧に「load-balancer-1」が表示されて、:white_check_mark:がついていればOK。


### Delete the project
無駄に課金されることを避けるため、プロジェクトを削除します。

1. ハンバーガーから、「Home」を選択する。
2. [Go to project settings]を選択する。
3. [SHUT DOWN]を選択する。<br>30日間は消えずに残っている。


## Update
### Update Instance template

1. ハンバーガーから、「Compute Engine」を選択する。
1. 最初に作成したインスタンスの右にある[SSH]を選択する。
1. HTMLファイルの書き換え

    ```Shell:
    $ echo "Hello!" | sudo tee /var/www/html/index.nginx-debian.html 
    ```
1. nginx 動作確認(Hello!と出ればOK)。

    ```Shell:
    $ curl http://localhost/
    Hello!
    ```

1. GCEインスタンスのシャットダウン

    ```Shell:
    $ sudo shutdown -h now
    ```

1. 更新後のインスタンスのスナップショットを取得する(異なる項目のみ記載)。

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|snapshot-1|**snapshot-2**|任意の名前|


1. 更新後のスナップショットから、イメージを作る(異なる項目のみ記載)。


    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|image-1|**image-2**|任意の名前|


1. 更新後のイメージから、インスタンステンプレートを作る(異なる項目のみ記載)。

    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Name|instance-template-1|**instance-template-2**|任意の名前|
    |Boot disk|Debian GNU/Linux 9 (stretch)|**image-2**|さっき作ったイメージ|



### Rolling Update
サービス提供を途切れさせずに、順繰りに更新をかけていきます。

1. テスト用Linuxマシンから、curlでレスポンスを確認します。

    ```Shell:
    $ while true;do curl http://[LB FrontendのIPアドレス]/;sleep 1;done
    ```

1. ハンバーガーから、「Compute Engine - Instance Group」を選択する。
1. 「instance-group-2」を選択する。
1. [ROLLING UPDATE]を選択する。
1. 以下の項目を入力する。


    |Item|Default Value|Value|Comments|
    |:-:|:-:|:-:|:-:|
    |Template|-|**instance-template-2**|さっき更新したテンプレート|
    |Target size|100%|←|すべてのインスタンスを更新|
    |Update mode|Proactive|←|即時反映|
    |Replacement Method|Substitute|←|新旧バージョンを同時に走らせながら更新する|
    |Maximum surge|1 instance(s)|←|とりあえずデフォルト|
    |Maximum unavailabel|1 instance(s)|←|同上|
    |Minimum wait time|0 sec|←|同上|
 
 1. [Update]を選択する。
 
 1. 新しいテンプレートを使ってインスタンスが追加され、立ち上がったら、
 既存のインスタンスが削除される。
 
 1. テスト用linuxマシンのレスポンスを確認すると、途切れずに新しいレスポンスに切り替わったことがわかります。
 ![Screenshot 2020-03-18 at 11.12.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525959/715bbd3f-569e-29ce-2c1b-4556e22f88e7.png)



## Confirmation

### Create test client 
1. 「Create a VM instance」と同じ手順で、テスト用のインスタンスを作ります(今回は、アメリカ東部と東京に、それぞれひとつづつ作りました)。
2. 作成したインスタンスの右にある[SSH]を選択する。

3. パッケージの最新化を行う。

    ```Shell:
    $ sudo apt update && sudo apt -y upgrade
    ```

4. Apacheユーティリティ をインストールする(Apache benchを使うため)。

    ```Shell:
    $ sudo apt -y install apache2-utils
    ```

5. Apache bench の確認(バージョン情報が表示されればOK)。

    ```Shell:
    $ ab -V
    This is ApacheBench, Version 2.3 <$Revision: 1757674 $>
    Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
    Licensed to The Apache Software Foundation, http://www.apache.org/
    ```



### Load Balancing
負荷分散の確認をしてみます。

1. ハンバーガーから、「Network services - Load balancing」を選択する。
2. [load-blancer-1]を選択する。
3. 「Frontend」に表示されているIPアドレスを控える。
4. 先程作ったテスト用Linuxマシンから、5多重で1,000リクエストを送信する。

    ```Shell:
    $ ab -c 5 -n 1000 http://[LB FrontendのIPアドレス]/
    ```

5. 「load-balancer-1 - Monitoring」タブを表示する。
6. 図のような感じで、2つのリージョンに負荷分散されたことが確認できました。
![Screenshot 2020-03-17 at 19.16.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525959/6e5f3776-45b1-1812-c9fa-790e552d190d.png)

### Degradation
縮退の確認をしてみます。

1. 先程作ったテスト用Linuxマシンから、curlでステータスコードを確認します。

    ```Shell:
    $ while true;do curl -LI http://[LB FrontendのIPアドレス]/ -o /dev/null -w '%{http_code}\n' -s;sleep 1;done
    ```

2. 「instance-group-2」の方のインスタンスに、SSHでログインし、シャットダウンします。

3. テスト用Linuxマシンでは、一部のリクエストが502(Bad Gateway)を受けて、その後正常レスポンスを受けていることがわかります。
    ![Screenshot 2020-03-17 at 19.34.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525959/d796c608-d5c6-e4e3-90d3-bf28aee92f20.png)


3. ロードバランサーのMonitoring画面でみると、「instance-group-1」に振り分けられていることがわかります。
    ![Screenshot 2020-03-17 at 19.29.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525959/315aa188-7869-f856-d09c-78b53a5db378.png)


### Autoscalling
オートスケールの確認をしてみます。

1. 「instance-group-1」の方のインスタンスに、SSHでログインします。
2. CPU使用率をお手軽に上昇させるため、stressをインストールします。
※イメージから生成したインスタンスに直接変更を加えるのは、構成管理の観点から、原則として、やらない方がよい。

    ```Shell:
    $ sudo apt -y install stress


3. CPU使用率を上昇させます。

    ```Shell:
    $ stress -c 1
    ```

4. インスタンスが追加されました(おおよそ、2〜3分)。
![Screenshot 2020-03-17 at 19.52.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525959/e2af73e7-c0ae-40a4-6f23-9e39823f6e98.png)

5. CPU使用率の上昇が収まった後、何分かすると追加されたインスタンスは削除され、インスタンスグループのMinimum instancesの数に収まります。