はじめに
この記事は、「Google Cloud Platform Advent Calendar 2020」の23日目の記事です。
Cloud Runのgcloud run deploy
コマンドについ先日--source
オプションがベータ版に追加されたということでdocを読んでると、こいつがかなり強力そうだったので試し&中身を追ってみました。
release note : https://cloud.google.com/run/docs/release-notes#December_16_2020
docs : https://cloud.google.com/sdk/gcloud/reference/beta/run/deploy#--source
TL;DR
ローカルでgcloud run deploy --source
一発で本当にリリースできた
--source
オプションでやってることは実は意外とシンプル
└ ソースコードをgcsに圧縮して上げて、buildpacksを用いてランタイム検出してイメージを作成、デプロイ
--sourceオプションとは
今まではGCRに上がっているイメージを--image
オプションを指定することでcliでデプロイできていました。
GCRに上げるには別途コマンドを用意する必要がありました。
--source
オプションとはこれら全てを取っ払い、デプロイしたいローカルのパスを指定するだけでCloud Runにデプロイしてくれるというものです。
...
そう、GCRに上げる手間が無いので、今まで秘伝のタレのごとく使い回していた.circleci/config.yml
に記載してるCDジョブから開放されます!!
試してみる
さっそくやってみましょう
サービス作成
コンソールから作成する際、イメージの指定が必須だったため、gcr.io/cloudrun/hello
を使用しました
疎通確認できました
簡単なhttpサーバ作成
超ミニマムなhttpサーバ作成しました
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
ただhello world
と出てくるだけです。
Cloud Runがデフォルトで8080開けてたのでこちらも8080開けときます。
いざ実践
❯ gcloud beta run deploy test --project xxx --region xxx --platform managed --source .
Building using Buildpacks and deploying container to Cloud Run service [test] in project [xxx] region [xxx]
✓ Building and deploying... Done.
✓ Uploading sources...
✓ Building Container... Logs are available at [https://console.cloud.google.com/cloud-build/builds/xxx].
✓ Creating Revision...
✓ Routing traffic...
Service [test] revision [test-00004-hos] has been deployed and is serving 100 percent of traffic.
Service URL: https://xxx.a.run.app
1分くらいで終了しましたw(GAE FEとは...)
早速確認してみましょう
わーお...
今まで一生懸命yamlを書いていた自分が馬鹿らしくなるくらい簡単にデプロイができました。
--source
恐るべし
中身を追ってみる
せっかくなので--source
で何をやっているのか追ってみたいと思います。
改めて出力内容を確認すると
Building using Buildpacks and deploying container to Cloud Run service [test] in project [xxx] region [xxx]
✓ Building and deploying... Done.
✓ Uploading sources...
✓ Building Container... Logs are available at [https://console.cloud.google.com/cloud-build/builds/xxx].
✓ Creating Revision...
✓ Routing traffic...
Service [test] revision [test-00004-hos] has been deployed and is serving 100 percent of traffic.
Service URL: https://xxx.a.run.app
やっていることは以下の4つのようです
- Uploading sources
- gcsにソースコードをアップロード
- Building Container
- イメージの作成・GCRへアップロード
- Creating Revision
- ↑のイメージを用いてCloud Runの新しいリビジョンの作成
- Routing traffic
- トラフィックを新しいリビジョンに100%移行
個人的に
「なぜdokcerfile作成してないのにgolangのイメージでビルドできてるんだろう」
という点が謎だったので、ビルドログを見ながら詳細を追っていきたいと思います。
Uploading sources
ビルドログの最初になにやらgcsにアップロードしてるようなログが見つかりました。
Fetching storage object: gs:/xxx_cloudbuild/source/yyy.tgz#zzz
Copying gs://xxx_cloudbuild/source/yyy.tgz#zzz...
/ [0 files][ 0.0 B/ 3.6 MiB]
/ [1 files][ 3.6 MiB/ 3.6 MiB]
Operation completed over 1 objects/3.6 MiB.
GCSをみてみるとたしかにアップロードされてますね。
おそらく後述のイメージビルドのときにここのリソースを見てビルドしているんでしょう。
ダウンロードしてみると、たしかにソースコードがはいってました。
Building Container
さらにログを追っていくと、今度は何やらbuildpacks
というイメージをダウンロードしており、そこからGoのランタイムを用いて自分のコードをビルドしてるようでした。
このbuildpacks
なるものがデプロイしたいプロジェクトのランタイムを推測してくれるものっぽいです。
調べてみるとビンゴ
ビルダーにはソースコード言語を自動検出する機能が備わっています。
Status: Downloaded newer image for gcr.io/buildpacks/builder:latest
v1: Pulling from buildpacks/gcp/run
0630ec5cfbac: Already exists
cb52d192561b: Already exists
3c2cba919283: Already exists
a9868d531da1: Already exists
6e839ca0739c: Already exists
Digest: sha256:9eee082ca3961dc89d4b720552c62b50d90bb9ea40fb92fd7d6e5d80b0ba0f3c
Status: Downloaded newer image for gcr.io/buildpacks/gcp/run:v1
0.9.3: Pulling from buildpacksio/lifecycle
5c7fe08dec51: Pulling fs layer
bc1d6b18b4c1: Pulling fs layer
5c7fe08dec51: Verifying Checksum
5c7fe08dec51: Download complete
bc1d6b18b4c1: Verifying Checksum
bc1d6b18b4c1: Download complete
5c7fe08dec51: Pull complete
bc1d6b18b4c1: Pull complete
Digest: sha256:bc253af2edf1577717618cb3a95f0f16bb18fc9e804efbcc1b85f657d931a757
Status: Downloaded newer image for buildpacksio/lifecycle:0.9.3
===> DETECTING
[detector] 3 of 6 buildpacks participating
[detector] google.go.runtime 0.9.1
[detector] google.go.build 0.9.0
[detector] google.utils.label 0.0.1
===> ANALYZING
[analyzer] Previous image with name "gcr.io/xxx/cloud-run-source-deploy/test:yyy" not found
===> RESTORING
===> BUILDING
[builder] === Go - Runtime (google.go.runtime@0.9.1) ===
[builder] Using runtime version from go.mod: 1.13
[builder] Installing Go v1.13
こうして作成されたイメージはGCRにあがります。
[exporter] *** Images (015d5a9fefbb):
[exporter] gcr.io/xxx/cloud-run-source-deploy/test:yyy
[exporter] Adding cache layer 'google.go.runtime:go'
Successfully built image gcr.io/xxx/cloud-run-source-deploy/test:yyy
PUSH
Pushing gcr.io/xxx/cloud-run-source-deploy/test:yyy
DONE
Creating Revision, Routing traffic
こちらはimage指定する通常のdeployコマンドと一緒のフローですので割愛
最後に
中身を追ったことで、ブラックボックスみが深いコマンドがだいぶ咀嚼できました。
今回はソースコードがgolang & 2ファイルのみでしたが、ソースコードをgcsにあげてる仕組み上これがnode.js
とかになってくるとnode_modules
もアップロードしだすと思うので速度が気になる所。
ただ、バージョン管理したいような大規模なものじゃない限りもう全部これでいいじゃん、という気分になりました。Cloud Runすごい。
この魔法、これから活用する機会が多そうです。
最後までありがとうございました。
参考
https://cloud.google.com/run/docs/release-notes
https://cloud.google.com/sdk/gcloud/reference/beta/run/deploy#--source
https://cloud.google.com/blog/ja/products/containers-kubernetes/google-cloud-now-supports-buildpacks