Edited at

Cloud Runで動かすGo + Echo Framework

Google Cloud Next ’19でKnativeベースの新サービス Cloud Runが発表されました。

https://cloud.withgoogle.com/next/sf

Cloud Functionに代表されるGCPのServerlessは、HTTPをトリガとする場合、Go言語ではhttp.HandlerFunc 型をサポートしてやる必要がありました。

これはこれで便利なのですが、じゃあ別プラットフォームで可動している何らのFramework入りGoサーバーをCloud Functionに移行しようとする際、改修は少々入ってしまうので、移行計画なんかを立ててる間にめんどくさくなってきます(えっ)

素直にGAE使えとかGKEとかあーあー聞こえない


Knative

Knativeの詳しい説明は、下記に譲りまして

Welcome to Knative | Knative


  • Kubernetesをベースとしたオートスケール

  • 稼働単位がコンテナ

  • インフラの設定などを極力自動化

発表された当初、その思想や考え方から、Knativeとは、Kubernetesを中核に置いた、オートスケールするHerokuみたいなものを実現するなにか という印象でした。発表以降、特段触ったわけでも無かったのですが、Cloud Runというマネージド・サービスがリリースされた今、ちょっくらやってみっか!と腰を上げたところです。


Go + Echo

過去の遺産として、Echo Frameworkで作られた、ちょっとしたAPIサーバーがいくつかありますので、こちらをCloud Runでデモ稼働させることを目的にします。

環境は Go 1.12 + go modules を利用する前提です。

今回利用したプロジェクトの全ては

https://github.com/onori/cloud-run-go-echo

に存在します。


main.go

package main

import (
"net/http"
"os"

"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)

func main() {
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())

e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})

e.GET("/:param", func(c echo.Context) error {
param := c.Param("param")
return c.String(http.StatusOK, param)
})

e.Logger.Fatal(e.Start(":" + os.Getenv("PORT")))
}


試しに2つのルーティングを準備してみました。/ でHello Worldが表示されるのと /:param でパラメータに入力された値がそのまま表示されます。


Docker buildと実行テスト

ローカルのDockerでビルドしてみる、下記のようなDockerfileを作成。

#build stage

FROM golang:stretch AS builder
WORKDIR /go/src/app
COPY . .
ENV GO111MODULE=on
RUN go build -o server

#final stage
FROM gcr.io/distroless/base
COPY --from=builder /go/src/app/server /app
ENV PORT=${PORT}
ENTRYPOINT [ "/app" ]
CMD [ "/server" ]

上記のDockerfileから、 docker build -t cloud-run-go-echo . でビルド実行後、 docker run -e PORT=1323 -p 1323:1323 --rm cloud-run-go-echo でコンテナ化したサーバーが動くか確認します。

localhost:1323/ が実行できていれば、問題ないでしょう。


Cloud Runの設定

GCPのコンソールから「Cloud Run」と入力し、サービスを有効化します。

CloudRun.png

今回はGKEへのインストールは行いませんでした、あくまでもサービスとしてCloud Runの利用を試します。


Google Container Registryへイメージを登録

CloudSDK はインストール済とした上で話を進めます。まず、今回作成したDockerイメージをContainer Registryに合わせた形でimageを新しく作り変えましょう。手順や詳細説明は、Container Registryのクイックスタートがわかりやすいです。

docker tag cloud-run-go-echo gcr.io/[PROJECT-ID]/cloud-run-go-echo:tag1

docker push gcr.io/[PROJECT-ID]/cloud-run-go-echo:tag1

push後にGCRコンソールでこのようにイメージが登録されていればOKです。

GCR.png


イメージをCloud Runで実行

gcloud beta run deploy --image gcr.io/[PROJECT-ID]/cloud-run-go-echo:tag1                                   

Please specify a region:
[1] us-central1
[2] cancel
Please enter your numeric choice: 1

To make this the default region, run `gcloud config set run/region us-central1`.

Service name: (cloud-run-go-echo):
Deploying container to Cloud Run service [cloud-run-go-echo] in project [PROJECT-ID] region [us-central1]
Allow unauthenticated invocations to new service [cloud-run-go-echo]?
(y/N)? y

✓ Deploying new service... Done.
✓ Creating Revision... Deploying Revision.
- Routing traffic...
Done.

Service [cloud-run-go-echo] revision [cloud-run-go-echo-00001] has been deployed and is serving traffic at https://xxxxxxxxx.run.app

gcloud beta run deploy からコンテナイメージを指定した後、外部公開サービスの場合は、「Allow unauthenticated invocations to new service」でyを選択してください。

その後、1分くらいでエンドポイントURLが発行されました。デプロイの手軽さからして、本当にHerokuっぽくていいです、脳死で行ける。


実行テスト

発行されたURLにアクセスすると、echoのハンドラで指定された/ のプログラムが処理されてるのがわかります。

home.png

/:param を渡すと、

param.png

こちらもちゃんとパラメータの値を受け取っています! echoでも問題なくルーティングが出来てますね!


コンソールの様子

CloudRunConsole.png

Cloud Runのコンソール画面。ログまで見れちゃってもう色々便利っすなー。使い勝手はやはり簡易的なHerokuという印象です。

USリージョンなんだけど、TTFBどんなもんかっていうと、150msくらい。

TTFB.png


Cloud Runに東京リージョンが追加されたので計測しました

TTFBは25msほど。素晴らしい。

image.png


総評

個人的にはかなり好きなサービスになりそうです。あーそうそう、こういうのでいいのよ、っていう、なんですかね、このちょうど良い感。Cloud Runに関しては更に色々調べていきます。ちなみにまだベータなのでご注意を。

間違いなど有りましたらコメント欄で指摘の程よろしくお願いいたします。