Serverless NEG(Network Endpoint Group)を設定しGAEと連携してみた

初めまして、***最近お客様にフォースがないアピールをするためにトルーパーに変身した***g-yamaです。
今後トルーパーと名乗ります。
(画像欠けているけど)

GAE上で個人ブログを構築し運用しているのですが、GCPのベータ版機能：Serverless NEG（Network Endpoint Group)を使ってみたくなり、ブログに適用する前に検証してみたので、記事にしました。

## 運営しているブログ
ヤマログというブログを運営しています。
https://yamavlog.com/

GCPで触ったことなどの備忘録を書いていますが、たまにガジェットネタなんかも書いています。
※GAEでWordpressを構築する方法や今回のServerless NEGに関する記事もこちらに書いています。

## Serverless NEG（Network Endpoint Group)って何？？
端的に言えば、**GCPのロードバランサのエンドポイントにサーバーレスサービス(GAE,Cloud Run,Cloud Functions)を指定できる機能**です。

これにより、GCPのサーバーレスサービスが、

1. **マルチリージョン構成で構築・運用が可能**
2. **使えなかったGCPの機能が利用可能**

となります。

2.について個人的に特に注目しており、

* **WAF(Cloud Armor)**
* **CDN(Cloud CDN)**

が、利用できるようになる点が非常に嬉しいです。

これらはロードバランサとの組合せでの利用が前提の機能なので、GCPのサーバーレスサービスでは利用が出来ず泣き所だったのですが、このデメリットがようやく解消される事になります。

また、**GCPのロードバランサとネットワークは他のパブリッククラウドの追随を許さない性能を誇る**ので、1.についても相当な物が期待出来ると思います。
ゲーム向けのインフラにマッチしそうですね。

詳細については、以下リンク記事をご覧頂けたらと思います。

* [Serverless network endpoint groups overview](https://cloud.google.com/load-balancing/docs/negs/serverless-neg-concepts)
* [Serverless NEG でシステム開発をより柔軟に](https://medium.com/google-cloud-jp/serverless-neg-%E3%81%A7%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E9%96%8B%E7%99%BA%E3%82%92%E3%82%88%E3%82%8A%E6%9F%94%E8%BB%9F%E3%81%AB-4f9cebd2780f)
* [NEG とは何か](https://medium.com/google-cloud-jp/neg-%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B-cc1e2bbc979e)

## 注意事項
**当記事執筆時点ではServerless NEGはbeta版となっており、GCPのSLAは保証されません、ご利用される際はご注意下さい。**

## 事前準備
### Cloud SDKの最新化と認証、config設定
手順は割愛させて頂きますが、Serverless NEGを設定する前に

* Cloud SDKの最新化
* Cloud SDKの認証
* config設定(作業プロジェクトや作業アカウントの指定)

は事前に行っておく必要があります。

### 作業アカウントの権限確認
作業アカウントに、下記IAMロールが付与されているかご確認下さい。

* Network Admin
* Compute Instance Admin
* Security Admin

プロジェクト管理者/編集者のIAMロールが付与されているアカウントであれば大丈夫だと思います。
[GCP公式Doc:Serverless NEG-Configure permissions](https://cloud.google.com/load-balancing/docs/negs/setting-up-serverless-negs#configure_permissions)

### GAEアプリケーションのデプロイ
今回はバックエンドアプリケーションをGAEにするので、GAE SEにアプリケーションを事前にデプロイしておきます。
アプリケーションは何でも構いません。
※Hello Word!と返すだけのプログラムでもOKです。

私はテスト用のWordpressをデプロイし試す事にしました。

### 静的IPアドレスの生成
**Serverless NEGはロードバランサと連携(実態はロードバランサのエンドポイント機能)**します。
このため、ロードバランサのフロントエンド(forwarding rule)用の静的IPアドレスが必要となるので作成しておきます。

#### 静的IPアドレスの作成

```
gcloud compute addresses create 【静的IPアドレス論理名】 \
     --ip-version=IPV4 \
     --global
```

#### 生成した静的IPアドレスの確認
```
gcloud compute addresses describe 【作成した静的IPアドレス論理名】 \
    --format="get(address)" \
    --global
````

実行するとIPアドレスが表示されます。
**後ほど利用するので控えておきます。**

### Cloud SDK beta版 componentsのインストール
Cloud SDKで設定するのでbeta componentsをインストールします。

```
gcloud components install beta
```

## Serverless NEG作成
下記コマンドを実行し、Serverless NEGを作成します。

```
gcloud beta compute network-endpoint-groups create 【ServerlessNEG論理名】 \
     --region=【リージョン名】 \
     --network-endpoint-type=SERVERLESS  \
     --app-engine-app \
     --app-engine-service=default
```

### Severless NEG作成結果の確認
下記コマンドを実行し確認します。
リストに作成したServerless NEGが表示されていればOKです。

```
gcloud beta compute network-endpoint-groups list

NAME         LOCATION         ENDPOINT_TYPE  SIZE
xxxxxxx-neg  asia-northeast2  SERVERLESS     0
```


### 補足1:コマンドオプションについて
今回指定したコマンドオプションは次の通りです。

|オプション        |説明    |
|---------------|-------|
|region  |Serverless NEGを作成するリージョン名。<br>**バックエンドアプリケーションと同じリージョン**にする必要があります。  |
|network-end-point-type  |NEGの種別Serverless<br>NEGにする場合は値を***SERVERLESS***にします。  |
|app-engine-app  |デフォルトルーティングでGAEを有効にする。  |
|app-engine-service  |Serverless NEGに追加するGAEのサービス名。<br>指定が無ければ省略可。  |

その他オプションについては、下記公式リファレンスをご覧下さい。
[gcloud beta compute network-endpoint-groups create](https://cloud.google.com/sdk/gcloud/reference/beta/compute/network-endpoint-groups/create#--app-engine-service)

### 補足2:マルチリージョン構成にする場合
**マルチリージョン構成にする場合はリージョンごとのServerless NEGを作成し、ロードバランサのバックエンドサービスに作成したServerless NEGを全て追加すればOKです。**

ロードバランサのバックエンドサービスへの追加は後述の手順を参照下さい。

## ロードバランサ・バックエンドサービスの設定
コマンドを順次実行し、バックエンドサービスの設定を進めていきます。

### バックエンドサービスの作成

```
gcloud compute backend-services create 【バックエンドサービス論理名】 --global

NAME                     BACKENDS  PROTOCOL
xxxxxxx-backend-service            HTTP
```

### バックエンドサービスにServerless NEGを追加

```
gcloud beta compute backend-services add-backend 【作成したバックエンドサービス論理名】 \
     --global \
     --network-endpoint-group=【作成したServerlesNEG論理名】 \
     --network-endpoint-group-region=【リージョン名(ServerlessNEGと同じリージョンにする必要あり)】
```

### バックエンドサービスの確認

```
gcloud beta compute backend-services list

NAME                     BACKENDS                                           PROTOCOL  LOAD_BALANCING_SCHEME  HEALTH_CHECKS
xxxxxxx-backend-service  【リージョン名】/networkEndpointGroups/xxxxxxx-neg       HTTP      EXTERNAL
```

## ロードバランサの設定
コマンドを順次実行し、ロードバランサの設定を進めていきます。
**ロードバランサの設定反映は多少時間がかかります。**

### ロードバランサの作成

```
gcloud compute url-maps create 【ロードバランサの論理名】 \
     --default-service 【作成したバックエンドサービス論理名】

NAME             DEFAULT_SERVICE
xxxxxxx-url-map  backendServices/xxxxxxx-backend-service
```

### ターゲットhttpプロキシを作成しロードバランサに追加

```
gcloud compute target-http-proxies create 【ターゲットhttpプロキシ論理名】 \
     --url-map=【作成したロードバランサの論理名】

NAME                URL_MAP
xxxxxxx-http-proxy  xxxxxxx-url-map
```

### フロントエンド(forwarding rule)をロードバランサに追加

```
gcloud compute forwarding-rules create 【フロントエンド論理名】 \
     --address=【前述の手順で作成した静的IPアドレスの確認で控えたIPアドレスを指定】 \
     --target-http-proxy=【作成したターゲットhttpプロキシ論理名】 \
     --global \
     --ports=80
```


### ロードバランサ・フロントエンドの確認

```
gcloud compute forwarding-rules list
 
NAME                       REGION  IP_ADDRESS                              IP_PROTOCOL  TARGET
xxxxxxx-http-content-rule          【前述の手順で作成した静的IPアドレスIPアドレス】    TCP          xxxxxxx-http-proxy
```

## 動作確認
ロードバランサにリクエストしてみます。

ブラウザのURL入力欄に、**ロードバランサ・フロントエンドのIPアドレス(【前述の手順で作成した静的IPアドレス】)**を入力し実行します。
![alt](https://storage.googleapis.com/yama-blog.appspot.com/1/2020/07/sucess-serveless-neg-gae-1-1-1536x972.jpg)

ロードバランサ経由でGEAにつながり、Wordpressの画面が表示されました。

## 後片付け
### ロードバランサの削除
[Cloud Consoleメニュー]->[ネットワークサービス]->[負荷分散]から、今回作成したロードバランサを削除します。
![alt](https://storage.googleapis.com/yama-blog.appspot.com/1/2020/07/delete-url-map-1536x669.jpg)

### Serverless NEGと静的IPアドレスの削除
下記コマンドを実行します。

```
# Serverless NEGの削除
gcloud beta compute network-endpoint-groups delete 【作成したServerlessNEG論理名】 --region=【リージョン名】

# 静的IPアドレスの削除
gcloud compute addresses delete 【作成した静的IPアドレス論理名】 --global
```

## まとめ
構築後に色々試してみたのですが、全く問題なかったので個人ブログに早速導入しました。
現在の構成はこんな感じです。
※会社の諸先輩方、アーキテクト図変じゃね？というご指摘はお手柔らかにお願いします。
![yamavlog-architect-202008-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683846/9c3b9e71-d2ba-a316-898f-313400c04fab.jpeg)



個人ブログの方は常時SSL化しているので、当記事と若干設定内容が異なります。差分設定など[こちらの記事にまとめました。](https://yamavlog.com/gae-worpress-migration-serverless-neg/)

**Cloud Armor**や**Cloud CDN**との連携もバッチリできます。
**Cloud IAP**は連携させるとエラーが出ちゃいました。
(確認中ですが、Serverless NEGとはまだ連携出来なそう??)

GCPのサーバーレスサービスの課題が、Serverless NEGでかなり解消されるんじゃないかなと思います。

またマルチリージョン化も出来るようになるので、リージョンレベルでの負荷分散や障害対策にもServerless NEGが活躍しそうです。

GAが待ち遠しいですね。

## 参考情報
* [GCP公式Doc:Setting up serverless NEGs](https://cloud.google.com/load-balancing/docs/negs/setting-up-serverless-negs#top_of_page)
* [GCP公式Doc:gcloud beta compute network-endpoint-groups create](https://cloud.google.com/sdk/gcloud/reference/beta/compute/network-endpoint-groups/create#--app-engine-service)