Cloud Run services でタグ付きリビジョンを使用して新しいリビジョンをテストする

記事タイトルとURLをコピーする

G-gen の佐々木です。当記事では Google Cloud (旧称 GCP) のサーバーレスなコンテナサービスである Cloud Run の タグ付きリビジョン(tagged revision)機能を解説します。

Cloud Run

Cloud Run とは

Cloud Run は、Google Cloud のサーバーレスな基盤でコンテナアプリケーションを実行できるサービスです。Cloud Run の中でも HTTP リクエストをトリガーとするものは Cloud Run services といい、コンテナとサーバーレスの利点を活かしたスケーラビリティの高い Web アプリケーション実行基盤として非常に有用なサービスとなっています。
Cloud Run services の詳細については以下の記事をご一読ください。

blog.g-gen.co.jp

タグ付きリビジョンとは

Cloud Run service でデプロイしたコンテナアプリケーションは、リビジョン という単位でバージョン管理されます。Cloud Run ではリビジョンに対するトラフィック分割機能により、新旧のリビジョンに対して一定割合でトラフィックをロードバランスし、新しいリビジョンを段階的にロールアウトすることができます。

デプロイしたリビジョンに対しては、タグを付与することができます。タグ付きリビジョンには タグを含む URL が発行され、トラフィックを新しいリビジョンにルーティングすることなくアクセスすることができるようになります。 これにより、Cloud Run 環境で新しいリビジョンのテストを行い、テストが終わったらそのままトラフィックをルーティングすることができます。

# Cloud Run サービスの通常の URL 例
https://servicename-xxxxxxxxxx-an.a.run.app

# タグ付きリビジョンの URL 例(リビジョンに dev タグを付与した場合)
https://dev---servicename-xxxxxxxxxx-an.a.run.app

参考:テスト、トラフィックの移行、ロールバックにタグを使用する

タグ付きリビジョンを使用する

Cloud Run サービスのデプロイ

使用するコード(Go)

当記事では、公式ドキュメントの クイックスタート のコードをベースにし、Cloud Run サービスをデプロイします。

package main
  
import (
    "fmt"
    "log"
    "net/http"
    "os"
)
  
func main() {
    log.Print("starting server...")
    http.HandleFunc("/", handler)
  
    // Determine port for HTTP service.
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
        log.Printf("defaulting to port %s", port)
    }
  
    // Start HTTP server.
    log.Printf("listening on port %s", port)
    if err := http.ListenAndServe(":"+port, nil); err != nil {
        log.Fatal(err)
    }
}
  
func handler(w http.ResponseWriter, r *http.Request) {
    s := "Hello, World!"
    fmt.Fprintf(w, "%s\n", s) // ブラウザに文字列を表示する
}
  

コンテナイメージのビルド

Cloud Run にデプロイするため、コンテナイメージをビルドして Artifact Registry にプッシュします。ここでは Dockerfile を使用せず、Buildpack を使用してコンテナイメージをビルドします。
イメージの新旧バージョンを分かりやすくするため、コンテナイメージには v1.0 タグを付与します。

# Buildpack を使用してイメージをビルドする
$ gcloud builds submit --pack image={リポジトリの URL}/{コンテナイメージ名}:v1.0
  
# 実行例(リポジトリに Artifact Registry を使用)
$ gcloud builds submit --pack image=asia-northeast1-docker.pkg.dev/myproject/myrepo/sample-service:v1.0

サービスのデプロイ

以下のコマンドを使用して Cloud Run サービスの最初のリビジョンをデプロイします。

# Cloud Run サービスのデプロイ
$ gcloud run deploy {サービス名} \
--image {コンテナイメージのURL} \
--region {リージョン} \
--allow-unauthenticated 
  
# 実行例(v1.0のコンテナイメージを指定)
$ gcloud run deploy sample-service \
--image asia-northeast1-docker.pkg.dev/myproject/myrepo/sample-service:v1.0 \
--region asia-northeast1 \
--allow-unauthenticated 

サービスへのアクセス

サービスのデプロイ後に URL が出力されるので、ブラウザからサービスの URL にアクセスします。

# デプロイ後の出力抜粋
Service [sample-service] revision [sample-service-00001-xuh] has been deployed and is serving 100 percent of traffic.
Service URL: https://sample-service-ai4qoprwhq-an.a.run.app

最初のリビジョンでは、ブラウザ上に「Hello, World!」の文字列が表示されます。

最初のリビジョンへのアクセスを確認する

タグ付きリビジョンのデプロイ

使用するコード(Go)

最初のリビジョンと区別するため、新しいリビジョンではブラウザに表示する文字列を変更します。
当記事では、新しいリビジョンにアクセスすると「Hello, G-gen!」の文字列が表示されるようにします。

package main
  
import (
    "fmt"
    "log"
    "net/http"
    "os"
)
  
func main() {
    log.Print("starting server...")
    http.HandleFunc("/", handler)
  
    // Determine port for HTTP service.
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
        log.Printf("defaulting to port %s", port)
    }
  
    // Start HTTP server.
    log.Printf("listening on port %s", port)
    if err := http.ListenAndServe(":"+port, nil); err != nil {
        log.Fatal(err)
    }
}
  
func handler(w http.ResponseWriter, r *http.Request) {
    s := "Hello, G-gen!" // ここを修正する
    fmt.Fprintf(w, "%s\n", s)
}
  

新しいコンテナイメージのビルド

最初のリビジョン同様に、コンテナイメージをビルドして Artifact Registry にプッシュします。
新しいイメージには v2.0 タグを付与します。

# Buildpack を使用してイメージをビルドする
$ gcloud builds submit --pack image={リポジトリの URL}/{コンテナイメージ名}:v2.0
  
# 実行例(リポジトリに Artifact Registry を使用)
$ gcloud builds submit --pack image=asia-northeast1-docker.pkg.dev/myproject/myrepo/sample-service:v2.0

タグ付きリビジョンのデプロイ

gcloud run deploy コマンドで --tag オプションを使用することで、タグ付きリビジョンをデプロイすることができます。ここで --no-traffic オプションを指定することで、新しいリビジョンにトラフィックがルーティングされないようにします。
既存のサービスに対して新しいリビジョンをデプロイするため、サービス名 には最初に作成したサービスと同じ名前を使用します。

# タグ付きリビジョンをデプロイする
$ gcloud run deploy {サービス名} \
--image {コンテナイメージのURL} \
--region {リージョン} \
--no-traffic \
--tag {タグ名}
  
# 実行例(v2.0のコンテナイメージを指定し、「dev」タグを付与)
$ gcloud run deploy sample-service \
--image asia-northeast1-docker.pkg.dev/myproject/myrepo/sample-service:v2.0 \
--region asia-northeast1 \
--no-traffic \
--tag dev

タグ付きリビジョンへのアクセス

タグ付きのリビジョンをデプロイするとタグが含まれる URL が発行されるので、ブラウザで URL にアクセスします。
タグ付きリビジョンの URL には、サービスの本来の URL に dev--- のような形式でタグが付与されています。

# タグ付きリビジョンのデプロイ後の出力抜粋
Service [sample-service] revision [sample-service-00002-caw] has been deployed and is serving 0 percent of traffic.
The revision can be reached directly at https://dev---sample-service-ai4qoprwhq-an.a.run.app

コンソールからタグをクリックすることでもアクセスすることが可能です。

コンソールからタグ付きリビジョンの URL にアクセスする

「Hello, G-gen!」が表示されているため、トラフィックがルーティングされていない新しいリビジョンにアクセスできていることがわかります。

タグ付きリビジョンへのアクセスを確認する

タグがついていないサービスの URL にアクセスすると、現在トラフィックがルーティングされている最初のリビジョンにアクセスできるため、新しいリビジョンがまだ公開されていないことがわかります。

サービスの URL から最初のリビジョンにアクセスできることを確認する

トラフィックの移行

タグ付きリビジョンへのトラフィック移行

タグ付きリビジョンのテストが終わったら、最初のリビジョンからトラフィックを移行します。
gcloud run services update-traffic コマンドの --to-tags オプションでタグ名を指定し、トラフィックを何パーセント割り当てるかを指定します。

# タグ付きリビジョンにトラフィックをルーティングする
$ gcloud run services update-traffic {サービス名} \
--region {リージョン} \
--to-tags {タグ名}={ルーティングするトラフィックの割合}
  
# 実行例(dev タグが付与されたリビジョンにトラフィックを 100% ルーティングする)
$ gcloud run services update-traffic sample-service \
--region asia-northeast1 \
--to-tags dev=100

タグ付きの新しいリビジョンにトラフィックが 100% ルーティングされている

サービスの URL にアクセスすると、新しいリビジョンにアクセスできるようになっています。

サービスの URL からタグ付きの新しいリビジョンにアクセスできることを確認する

タグの削除

タグが不要になったら --remove-tag オプションでタグを指定し、サービスを更新します。

# リビジョンからタグを削除する
$ gcloud run services update-traffic {サービス名} \
--region {リージョン} \
--remove-tags {タグ名}
  
# 実行例(dev タグを削除)
$ gcloud run services update-traffic sample-service \
--region asia-northeast1 \
--remove-tags dev

佐々木 駿太 (記事一覧)

G-gen最北端、北海道在住のクラウドソリューション部エンジニア

2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2024に選出。好きなGoogle CloudプロダクトはCloud Run。

趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。