[備忘録][GCP] App EngineからCompute Engineにアクセスする

# 1. はじめに

この記事は Google Cloud Platfrom (GCP) の「サーバーレスVPCアクセス」設定の備忘録になります。

GCP の App Engine (GAE) スタンダード環境にデプロイしたアプリケーションから Compute Engine (GCE) に作成した仮想マシン(※インターネット非公開)に HTTP アクセスを行う処理がありました。当初は「GCE 仮想マシンと GAE アプリケーションは同じプロジェクト内にあるので接続できるだろう」と楽観的に考えていました。
しかし、いざ処理を実行したところ、エラーになってしまいました。GAE アプリケーションが GCE 仮想マシンを見つけられないようです。想定外の結果に流れ出る冷や汗。。。

# 2. 調査

はい。碌に下調べをしなかった私に落ち度がありました。
GCP のサイトにちゃんと説明がありました。

[サーバーレス VPC アクセス &nbsp;|&nbsp; Google Cloud](https://cloud.google.com/vpc/docs/serverless-vpc-access?hl=ja)
> サーバーレス VPC アクセスを使用すると、Cloud Run、App Engine、Cloud Functions などのサーバーレス環境から Virtual Private Cloud（VPC）ネットワークに直接接続できます。サーバーレス VPC アクセスを構成すると、サーバーレス環境で、内部 DNS と内部 IP アドレス（RFC 1918 および RFC 6598 で定義）を使用して VPC ネットワークにリクエストを送信できます。これらのリクエストに対するレスポンスも内部ネットワークを使用します。

どうやら通常は GAE から Virtual Private Cloud (VPC) ネットワークに接続できないみたいで、「サーバーレス VPC アクセス」というものを使う必要があるようです。
それでは Let's チャレンジ！

# 3. サーバーレス VPC アクセスのコネクタ作成（Google Cloud コンソール）

それでは「Google Cloud コンソール」からサーバーレス VPC アクセスのコネクタを作成してみたいと思います。

![svless-vpc-ac_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512108/9a7ed004-479f-234c-cbdc-6d4bdb8fcc2f.png)
サイドメニューより [VPC ネットワーク] - [サーバーレス VPC アクセス] ページを表示し、ページ上部にある「コネクタを作成」をクリックします。

![svless-vpc-ac_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512108/1b87151b-6bf7-cd60-c99e-91785b502d6e.png)
「名前」に登録するコネクタの名称を入力します。この例では"hoge-connector"とします。
「リージョン」はプロジェクトの(正確には GAE アプリケーションが配置されている)リージョンを、「ネットワーク」はコネクタを接続する VPC ネットワークを選択します。この例では特にないので、"default"を選択しています。
「サブネット」は新規に作成することとし、「カスタム IP 範囲」を選択、「IP 範囲」については説明書きにある例 "10.8.0.0" を採用することにします。

![svless-vpc-ac_003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512108/94344df8-90f7-1524-9570-c4030bfa381b.png)
続けて「スケーリング設定を表示」をクリックし、スケーリング設定を行います。

「最小インスタンス数」はこの例では最も小さい値にすることとします。ただし、"1"を入力するとエラーになり、**"2"以上の値しか入力できない**ようになっています。
「最大インスタンス数」は**最小インスタンス数よりも大きい値**を入力する必要があり、最小インスタンス数と同値を入力した場合はエラーになります。この例では最小インスタンス数よりも1つ多い"3"を設定することとします。ちなみに上限値は"10"になります。
「インスタンスのタイプ」は推定されるスループットを元に"f1-micro"、"e2-micro"、"e2-standard-4"から選択します。ここではデフォルトの"e2-micro"とします。

全ての入力が終わったら「作成」ボタンをクリックします。そうすると、サーバーレス VPC アクセスのコネクタが作成されます。

![svless-vpc-ac_004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512108/e10df233-c49d-7498-c906-84f68a28319c.png)
これで GAE アプリケーションから GCE 仮想マシンにアクセスできる準備が整いました。

:::note warn
**サーバーレス VPC アクセス・コネクタのインスタンスについて**
設定項目「インスタンスのタイプ」で気づかれたかもしれませんが、サーバーレス VPC アクセス・コネクタの実体は GCE (と同類の)仮想マシンと考えられます。仮想マシンは**立ち上がっている間、課金が行われます**。
しかもコネクタのインスタンスは、スケールダウンが行われないこと、未使用のインスタンスを手動でも落とせないことに注意してください。
なお、アクティブなインスタンスを最小時点に戻したい場合は、コネクタを**一旦削除して再作成する**必要があります。

ちなみに、今回の例では「インスタンスのタイプ」に無料枠のある"e2-micro"を選択していますが、毎月の無料枠は合計利用時間が1ヶ月の範囲になります。つまり、2つのコネクタ・インスタンスが常時起動している場合は、合計利用時間が2ヶ月となるため、無料枠オーバー分(1ヶ月分)の課金が発生します。
なお、無料枠は特定のリージョンに限定されています。
詳細については以下をご参照ください。

Google Cloud の無料プログラム | 無料枠の使用量上限 | Compute Engine
https://cloud.google.com/free/docs/free-cloud-features?hl=ja#compute
:::

# 4. app.yaml にサーバーレス VPC アクセス コネクタ定義を追加

作成したコネクタを GAE アプリケーションが利用するには、GAE にコネクタを教えてあげる必要があります。
具体的には、GAE アプリケーションのデプロイで使用する app.yaml に以下のような定義を追加します。
※【プロジェクトID】,【リージョン】,【コネクタ名】は適切な値に置き換えてください。
```yaml:app.yaml
vpc_access_connector:
    name: "projects/【プロジェクトID】/locations/【リージョン】/connectors/【コネクタ名】"
```

ちなみに、今回作成したコネクタの定義は以下のようになります。
※プロジェクトIDを"hoge-project"とした場合。
```yaml:app.yaml
vpc_access_connector:
    name: "projects/hoge-project/locations/us-central1/connectors/hoge-connector"
```

この app.yaml を使って GAE アプリケーションをデプロイすると、GAE アプリケーションから GCE 仮想マシンにアクセスできるようになります。

:::note info
**GAE アプリケーション デプロイ時の注意**
GAE アプリケーションをデプロイする時に、app.yaml に定義された vpc_access_connector のコネクタが未作成の場合、デプロイに失敗します。
したがって、コネクタを先に作成してから、GAE アプリケーションをデプロイするようにしてください。
:::

# 5. Appendix：サーバーレス VPC アクセスのコネクタ作成＆削除（gcloud コマンド）

前述のとおり、作成されたコネクタのインスタンスは立ち上がり続け、その間はずっと課金される状態になります。本番運用環境ではそれでも問題ないかもしれませんが、たとえば開発テスト環境の場合はどうでしょうか。未使用の間はコネクタのインスタンスを落としたいこともあるのではないでしょうか。
残念ながらコネクタのインスタンスを停止する方法はないため、削除が唯一の方法になります。つまり、使用する度に作成→削除を繰り返すことになりますが、削除はよいとしても作成は少々手間がかかります。
そこで、gcloud コマンドを使って、リモートでコネクタの作成、削除を行えるようにしてみましょう。

コマンドは以下になります。
※【プロジェクトID】,【リージョン】,【コネクタ名】,【ネットワーク】,【IP範囲】,【最小インスタンス数】,【最大インスタンス数)】,【インスタンスのタイプ】は適切な値に置き換えてください。
```shell
#サーバーレスVPCコネクタの作成
gcloud compute networks vpc-access connectors create 【コネクタ名】 --region 【リージョン】 --network 【ネットワーク】 --range 【IP範囲】 --min-instances 【最小インスタンス数】 --max-instances 【最大インスタンス数】 --machine-type 【インスタンスのタイプ】 --project 【プロジェクトID】

#サーバーレスVPCコネクタの状態確認
gcloud compute networks vpc-access connectors describe 【コネクタ名】 --region 【リージョン】 --project 【プロジェクトID】

#サーバーレスVPCコネクタの削除
gcloud compute networks vpc-access connectors delete 【コネクタ名】 --region 【リージョン】 --project 【プロジェクトID】
```

ちなみに、今回例として作成したコネクタの場合は以下のようになります。
※プロジェクトIDを"hoge-project"とした場合。
```shell
#サーバーレスVPCコネクタの作成
gcloud compute networks vpc-access connectors create hoge-connector --region us-central1 --network default --range 10.8.0.0/28 --min-instances 2 --max-instances 3 --machine-type e2-micro --project "hoge-project"

#サーバーレスVPCコネクタの状態確認
gcloud compute networks vpc-access connectors describe hoge-connector --region us-central1 --project "hoge-project"

#サーバーレスVPCコネクタの削除
gcloud compute networks vpc-access connectors delete hoge-connector --region us-central1 --project "hoge-project"
```

# 6. おわりに

サーバーレス VPC コネクタについては、検索すれば情報はいくつか見つかります。しかし、作成手順を事細かに説明してくれるような易しい(優しい)情報は見当たらず、躊躇いながら作業を行いました。
今回はその経験を踏まえて、記事を書いてみました。
ここで書いた内容が、少しでも誰かのお役に立てれば幸いです。

# 7. 参考にさせていただいた情報

サーバーレス VPC アクセス &nbsp;|&nbsp; Google Cloud
https://cloud.google.com/vpc/docs/serverless-vpc-access?hl=ja

app.yaml 構成ファイル &nbsp;|&nbsp; App Engine スタンダード環境での Java に関するドキュメント &nbsp;|&nbsp; Google Cloud
https://cloud.google.com/appengine/docs/standard/java-gen2/config/appref?hl=ja#vpc_access_connector