GCP導入メモ

以前作ったGCPプロジェクトを再度使い始めたので個人的な備忘録としてメモしておく。

# Cloud SDKの導入
https://cloud.google.com/sdk/
特に迷うことはなかった、ダウンロードしてシェルを実行する。
自分は `~/google` ディレクトリを作成したので、パスは `export PATH="~/google/google-cloud-sdk/bin:$PATH"` とした。

# 課金の有効化
GAEを使おうとしたら課金を有効化しろ、と言われたので有効化した。
クレジットカードを登録するだけでよい。
https://console.cloud.google.com/billing

# 課金アラートの設定
従量課金が怖いので、アラートを設定した。お支払い→予算とアラートから設定できる。
とりあえず1000円にしておいた（でも最初は無料で使える範囲で運用するつもり）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195490/a8d58ecd-a992-ac2b-c964-9e0453dbf199.png)

# 無料枠の確認
GCPはスタートしてから12ヶ月間 $300 のクレジット無料、というものがあったが、今回は以前使っていたプロジェクトを再利用しているために、このクレジットは利用できなかった。
だが、以下にあるように無料枠が存在するので、この枠内で運用できるようにすれば課金が発生しない。
https://cloud.google.com/free/?hl=ja
https://cloud.google.com/free/docs/always-free-usage-limits?hl=ja

ポイントになりそうなところだけ、次項にメモします。
※特定の条件のみ、という条件があるものもあります

## GCP無料枠で使えそうな（便利そうな）もの

| サービス | 枠 | 備考 |
|:-:|:--|:--|
| Google Compute Engine(GCE) | t1.micro <br> 30GB HDD <br> 1GB Egress | 1インスタンスなら永続無料で運用できる <br>  対象リージョン: us-*1  |
| GAE | 28インスタンス時間/日 | 1インスタンスなら永続無料 <br> スケールしないようにすればOK <br> 2インスタンスの場合は14時間無料 |
| Cloud Storage | 5GB | 画像、HTMLなどの静的リソースが置ける |
| Cloud Firestore  | 1GB <br> R50k, W20k, RM20k | オペレーション件数で課金される。<br> https://firebase.google.com/docs/firestore/quotas?hl=ja も参照 |
| Cloud Functions | 100万回 | AWSのlambdaみたいなもの。 <br> ステートレスで、サーバを立てるまでもない処理に <br> DBアクセスする場合はアクセス回数に注意 |
| BigQuery | クエリ1T <br> 保存10G | スモールスタートならこれで十分 |
| Cloud Shell | 5GBストレージ | ブラウザ上でコンソールログインして作業ができる、お手軽 |

# GCEインスタンスの作成
https://console.cloud.google.com/compute/instances
ドメインなどを割り当てる場合、IPを固定化しておくと良いです（利用しないで取得しておくと課金されますが、利用していれば課金されません、AWSのEC2と同じです）。
外部からアクセスする場合は 80, 443 ポートをあけておきます。

# GAEインスタンスの作成
https://console.cloud.google.com/appengine
GAEインスタンスも無料なので作成しておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195490/cfdf6856-f86d-9072-9de7-efcdefedd2c3.png)

フレキシブル（Flex）は無料枠の対象外なので注意します。基本的に標準（Standard）で問題ありません。
標準でできないような処理をする場合は、先程作成したGCEインスタンスを使うのがおすすめです。
ここではPythonを選んだとして進めます。

Pythonの開発環境についてはpyenv、pyenv-virtualenvあたりをインストールしておくと良いです。
※gcloud系のコマンドを使うにはpython2系の環境が必要ですが、以下の開発ではPython3系を使います。

以下を参考にさせていただきました。

* https://qiita.com/shigechioyo/items/198211e84f8e0e9a5c18

## GAE for Python3でのデプロイ
Python3系のGAEでデプロイまで行ってみます。Python3.7系が必要です。
https://cloud.google.com/appengine/docs/standard/python3/quickstart

```shell
# コンポーネントのインストール
gcloud components install app-engine-python
# Python3系の開発環境を作る
pyenv virtualenv 3.7.1 python-gae
pyenv activate python-gae
```

クイックスタートを参考に、最低限デプロイに必要なファイルを揃えます。
https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/standard_python37/hello_world

```shell

# flaskと、requestsは今後使う可能性が高いので。
pip install flask requests
# 一応
pip install --upgrade pip
# requirements.txtを作る
pip freeze > requirements.txt
```
`pip freeze` したものをrequirements.txtにしておくと、ライブラリの意図しないアップデートで動作しなくなる、という問題が発生しなくなります。
virtualenvで専用の環境（バージョン）を作って、「この環境では基本的に上記の`requirements.txt`と一致している環境にしておくのが個人的なおすすめです。

さて、サンプルを参考に、 `main.py` と `app.yaml` を作成します。
`main.py` についてはクイックスタートのものと同一なので割愛します。

```app.yaml
runtime: python37
automatic_scaling:
  max_instances: 1
```

app.yamlの設定は以下を参考にしました。
省略された設定についてはよろしく設定されるので、下のドキュメントを頑張って読む必要はありません。
https://cloud.google.com/appengine/docs/standard/python/config/appref?hl=ja

（スケールしてお金がかからないように）インスタンスの最大台数を1に設定しています。
最小は0です（トラフィックがない場合は0になり、トラフィックが来た場合にインスタンスが起動する）。最小を1に設定すると、0にならなくなります。

なお、サービス名は任意に設定できますが、`default` のサービス名のインスタンスが1個以上デプロイされている必要があるため、今回は省略して `default` としました。

デプロイは以下のように、`gcloud app deploy`コマンドを実行します。
`--project`でプロジェクト名を指定できたり、`--version`でバージョン名称を設定したり、引数に`app_hogehoge.yaml`を設定したりすることができますが、今回はすべて省略しています。
初回は1分半くらいかかりました。

```shell
(python-gae) [sonuma@local ~/google/public_bath_search]$ gcloud app deploy
Services to deploy:

descriptor:      [/path/to/repository/app.yaml]
source:          [/path/to/repository]
target project:  [<PROJECT_NAME>]
target service:  [default]
target version:  [デプロイした時刻<YYYYMMDDtHHMMSS>]
target url:      [<デプロイターゲットURL>]


Do you want to continue (Y/n)?  y

Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 1 file to Google Cloud Storage                 ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [<デプロイターゲットURL>]

You can stream logs from the command line by running:
  $ gcloud app logs tail -s default

To view your application in the web browser run:
  $ gcloud app browse
```

defaultサービスの場合、URLは ```https://<プロジェクト名>.appspot.com```になります。
他サービスでデプロイする場合、```https://<サービス名>-dot-<プロジェクト名>.appspot.com```になります。
このホスト表現は変化しないので、ドメイン割当先として使うことができます。

以下を実行すると、ブラウザが開いて"デプロイターゲットURL"を表示します。

```shell
gcloud app browse
```
ブラウザに`Hello World!`が表示されたらデプロイ成功です。

## GAEメモ
GAEを使う上で気になった部分をメモしています。

### --no-promoteオプション
以前のバージョンが存在する状態で`gloud app deploy`すると、以前のインスタンスへ割り当てられているトラフィックを全て新規のバージョンへ移し替える作業が行われます。
このタイミングを制御したい場合、`--no-promote`オプションを指定することで、トラフィックの割当を手動（あるいはAPI、CLIなど）で行うことができるようになります。
https://cloud.google.com/sdk/gcloud/reference/app/deploy

### バージョン名

バージョン名称を省略するとデプロイ時刻ベースのバージョン文字列でデプロイされますが、`--version`で固定のバージョン名称を指定することで、以前のインスタンスを上書きすることができます。
バージョン数には上限があるため、小規模なアプリの場合はバージョン名を上書きしておいても良さそう。
※https://cloud.google.com/appengine/docs/standard/go/an-overview-of-app-engine?hl=ja のバージョン数を参考。

### インスタンスの停止
GAE Standardではインスタンスを停止できない（削除は可能）。
インスタンスに一定時間アクセスが来ない場合、インスタンス数が0になるため、削除は不要というニュアンスだと思われる。

# 以上
無事GAEとGCEのインスタンスが起動したので、いろいろ試してみようと思います。

# （おまけ）devドメインの取得
せっかくなのでドメインを買った。年額 \1,400 なので、Amazonプライムよりだいぶ安い。
https://support.google.com/domains/answer/4491208
LINE Payでバーチャルカードを作っていたのだけど、それで購入することができた（今だけお得なのかも）。

# 参考にさせていただいたページ
https://qiita.com/riku-shiru/items/a870edd9dc0b132e092c
https://qiita.com/Brutus/items/22dfd31a681b67837a74