Deploy connect-go APIs with Cloud Run and API Gateway

Connect で実装した Go の API と、それを Cloud Run / API Gateway で使用する方法を紹介します。

```mermaid
flowchart LR
    subgraph APIGateway
    APIConfig-->Gateway
    end
    client["Client"]
    server1["Cloud Run
    gRPC"]
    server2["Cloud Run
    gRPC"]
    client -->|gRPC| APIGateway
    APIGateway -->|greet.v1.GreetService| server1
    APIGateway -->|weather.v1.WeatherService|server2
```

Topic は以下のとおりです。
- [API Gateway](https://cloud.google.com/api-gateway/docs/get-started-cloud-run-grpc)
- Cloud Run
- gRPC
- [Connect for Go](https://github.com/connectrpc/connect-go)
- Golang
- Cloud DNS
- Cloud Load Balancing

さらに詳しく見たい方は読み続けてください。

---

2023年9月1回目です。

このメモは、API Gateway についてです。

API Gateway に API を複数ぶら下げたことはありますか？

OpenAPI の場合は、Console から操作できますが、gRPC に関しては、CUI の操作が必要です。

また、protobuf descriptor( `.pb` ) と API Config File を準備して、 API Config という Resource を作成する必要があります。

今回、設定するにあたり、参考となるものを見つけることができなかったため、メモに残します。

## Deploy APIs
- Golang で実装し、connect-go を使います。
- gRPC の API を Cloud Run に deploy します。
```bash
gcloud run deploy
```

https://github.com/danny-yamamoto/go-connect-greet/blob/main/Dockerfile

## Compile Proto Definition File(.proto)

```mermaid
flowchart LR
    proto1["greet.proto"]
    proto2["weather.proto"]
    config["api_config.yaml"]
    pb["descriptor.pb"]
    apiconfig["api-config resource"]
    proto1 --> pb
    proto2 --> pb
    pb --> apiconfig
    config --> apiconfig
```

- Folder 内の構成は次のとおりです。
```bash
.
├── greet.proto
└── weather.proto
```

- `.proto` をコンパイルして、`.pb` を生成します。
- `.proto` が複数存在する場合は、半角スペースで区切ります。
```bash
protoc --proto_path=. --descriptor_set_out=./descriptor.pb greet.proto weather.proto 
```

## Create a api_config.yaml
- 複数の API をぶら下げる場合は、`selector` を一致させます。

https://github.com/danny-yamamoto/go-connect-greet/blob/main/api-gateway/api_config.yaml

- 片方の API のみ認証を必須とするという設定が可能です。`allow_unregistered_calls` を `false` にします。

https://github.com/danny-yamamoto/go-connect-greet/blob/3c50b8c9aaad11fbdc5608c91a4a6e284a412bf7/api-gateway/api_config.yaml#L8-L13

## Create a API Gateway
- Official[^1] の手順に従います。
- api_config.yaml、`.pb` は、基本的に１つずつです。config を override する場合は、config を2つ使うこともできます。

[^1]:https://cloud.google.com/api-gateway/docs/get-started-cloud-run-grpc

## Create a Custom Domain
- こちらも、Official[^2] の手順に従います。
- このメモ作成時点では、Custom Domain は、Preview です。注意が必要です。

[^2]:https://cloud.google.com/api-gateway/docs/using-custom-domains?hl=ja

## Make requests
- HTTP/1.1 POST で確認します。

- greet
```bash
root@4c686d82623b:/# curl \
    --header "Content-Type: application/json" \
    --data '{"name": "taro"}' \
https://hoge.example.jp/greet.v1.GreetService/Greet -i
HTTP/2 200 
content-type: application/json
greet-version: v1
grpc-accept-encoding: gzip
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
grpc-status: 0
grpc-message: 
x-cloud-trace-context: 3779da58de8184d23fcf29be2b8bf0eb;o=1
date: Mon, 04 Sep 2023 03:01:01 GMT
server: Google Frontend
content-length: 27
via: 1.1 google

{"greeting":"Hello, taro!"}
root@4c686d82623b:/# 
```
- weather
```bash
root@4c686d82623b:/# curl \
    --header "Content-Type: application/json" \
    --data '{"condition": "Sunny"}' \
https://hoge.example.jp/weather.v1.WeatherService/Weather -i
HTTP/2 200 
content-type: application/json
grpc-accept-encoding: gzip
weather-version: v1
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
grpc-status: 0
grpc-message: 
x-cloud-trace-context: 8e3e4a02c615f7147cef703e5b0a2aa0;o=1
date: Mon, 04 Sep 2023 03:02:03 GMT
server: Google Frontend
content-length: 36
via: 1.1 google

{"text":"Today's weather is Sunny."}
root@4c686d82623b:/# 
```

- gRPC Client で確認します。
![0291629885351fdb37bab.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569971/4d56ed34-2480-d5f4-3606-d9b8c31e4624.jpeg)

## Summary
- API Gateway について書きました。
- IaC(Terraform) の運用について検討が必要だと感じました。
- `api_config.yaml` の変更が発生する場合に、切り替えは、request の lost 無しに上手くいくのか？
- protobuf descriptor の compile と IaC の apply の順序についても考える必要があると思います。

この投稿をみて何か得られた方は、いいね ❤️ をお願いします。

それでは、また別の話でお会いしましょう。👋