Cloud Run サービス内の gcloud コマンドラインのチュートリアル


このチュートリアルでは、Cloud Run サービス内の gcloud および gsutil コマンドライン ツールを使用して、Cloud Run サービスのインベントリを作成します。このチュートリアルで学んだことを既存の Cloud オペレーション スクリプトに適用することや、クライアント ライブラリを使用してより堅牢なサービスを構築する前に概念実証を作成することもできます。

Shell クイックスタートに示されているように、ウェブサービス内のシェル スクリプトと同様に、gcloud および gsutil ツールを使用します。Cloud Run では、どちらのツールも Google Cloud サービス ID で自動的に認証することで Google Cloud サービスと連携します。サービス ID に付与されている権限はすべて gcloud CLI で使用できます。

gcloud CLI は、Google Cloud 全体で情報の収集とリソース管理を幅広く行えるため、ウェブサービス内でこのツール使用することにより、呼び出し元がこれらの機能を誤って使用するリスクを最小限に抑えられます。セキュリティ制御を使用しない場合、偶発的または意図的な悪意のある活動を許可することにより、同じプロジェクト内で稼働している他のサービスまたはリソースに対してリスクが生じる場合があります。リスクの例として、以下が挙げられます。

  • プライベート仮想マシンの IP アドレスの検出が可能になる。
  • 同じプロジェクト内のデータベースからプライベート データへのアクセスが可能になる。
  • 他の稼働中のサービスの削除が可能になる。

たとえば、ユーザー入力として開いたままにする代わりに、コードで実行される gcloud コマンドを指定するように、このチュートリアルのいくつかの手順は、リスクを最小化するために制御を強制する方法を示しています。

Cloud Run サービス内でコマンドライン ツールを使用したスクリプト記述は、ローカルでコマンドラインを使用する場合と似ています。主な違いは、主要なスクリプト ロジックの周囲に追加する、追加の制限です。

目標

  • カスタム コンテナを作成し、Dockerfile と一緒にビルドする。
  • Cloud Run サービスを作成、構築、デプロイする。
  • gcloud ツールと gsutil ツールをウェブサービスで安全に使用する。
  • Cloud Run サービスのレポートを生成して Cloud Storage に保存する。

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

始める前に

  1. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  5. Google Cloud プロジェクトで課金が有効になっていることを確認します

  6. Artifact Registry, Cloud Build, Cloud Run, and Cloud Storage API を有効にします。

    API を有効にする

  7. gcloud CLI をインストールして初期化します

必要なロール

チュートリアルを完了するために必要な権限を取得するには、プロジェクトに対して次の IAM ロールを付与するよう管理者に依頼してください。

ロールの付与の詳細については、アクセスの管理をご覧ください。

必要な権限は、カスタムロールや他の事前定義ロールから取得することもできます。

gcloud のデフォルトを設定する

Cloud Run サービスを gcloud のデフォルトに構成するには:

  1. デフォルト プロジェクトを設定します。

    gcloud config set project PROJECT_ID

    PROJECT_ID は、このチュートリアルで作成したプロジェクトの名前に置き換えます。

  2. 選択したリージョン向けに gcloud を構成します。

    gcloud config set run/region REGION

    REGION は、任意のサポートされている Cloud Run のリージョンに置き換えます。

Cloud Run のロケーション

Cloud Run はリージョナルです。つまり、Cloud Run サービスを実行するインフラストラクチャは特定のリージョンに配置され、そのリージョン内のすべてのゾーンで冗長的に利用できるように Google によって管理されます。

レイテンシ、可用性、耐久性の要件を満たしていることが、Cloud Run サービスを実行するリージョンを選択する際の主な判断材料になります。一般的には、ユーザーに最も近いリージョンを選択できますが、Cloud Run サービスで使用されている他の Google Cloud サービスのロケーションも考慮する必要があります。使用する Google Cloud サービスが複数のロケーションにまたがっていると、サービスの料金だけでなくレイテンシにも影響することがあります。

Cloud Run は、次のリージョンで利用できます。

ティア 1 料金を適用

  • asia-east1(台湾)
  • asia-northeast1(東京)
  • asia-northeast2(大阪)
  • europe-north1(フィンランド) リーフアイコン 低 CO2
  • europe-southwest1(マドリッド)
  • europe-west1(ベルギー) リーフアイコン 低 CO2
  • europe-west4(オランダ)
  • europe-west8(ミラノ)
  • europe-west9(パリ) リーフアイコン 低 CO2
  • me-west1(テルアビブ)
  • us-central1(アイオワ) リーフアイコン 低 CO2
  • us-east1(サウスカロライナ)
  • us-east4(北バージニア)
  • us-east5(コロンバス)
  • us-south1(ダラス)
  • us-west1(オレゴン) リーフアイコン 低 CO2

ティア 2 料金を適用

  • africa-south1(ヨハネスブルグ)
  • asia-east2(香港)
  • asia-northeast3(ソウル、韓国)
  • asia-southeast1(シンガポール)
  • asia-southeast2 (ジャカルタ)
  • asia-south1(ムンバイ、インド)
  • asia-south2(デリー、インド)
  • australia-southeast1(シドニー)
  • australia-southeast2(メルボルン)
  • europe-central2(ワルシャワ、ポーランド)
  • europe-west10(ベルリン)
  • europe-west12(トリノ)
  • europe-west2(ロンドン、イギリス) リーフアイコン 低 CO2
  • europe-west3(フランクフルト、ドイツ) リーフアイコン 低 CO2
  • europe-west6(チューリッヒ、スイス) リーフアイコン 低 CO2
  • me-central1(ドーハ)
  • me-central2(ダンマーム)
  • northamerica-northeast1(モントリオール) リーフアイコン 低 CO2
  • northamerica-northeast2(トロント) リーフアイコン 低 CO2
  • southamerica-east1(サンパウロ、ブラジル) リーフアイコン 低 CO2
  • southamerica-west1(サンティアゴ、チリ) リーフアイコン 低 CO2
  • us-west2(ロサンゼルス)
  • us-west3(ソルトレイクシティ)
  • us-west4(ラスベガス)

Cloud Run サービスをすでに作成している場合は、Google Cloud コンソールの Cloud Run ダッシュボードにリージョンが表示されます。

コードサンプルを取得する

使用するコードサンプルを取得するには:

  1. ローカルマシンにサンプルアプリのリポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/cloud-run-samples.git

    または、zip 形式のサンプルをダウンロードし、ファイルを抽出してもかまいません。

  2. Cloud Run のサンプルコードが含まれているディレクトリに移動します。

    cd cloud-run-samples/gcloud-report/

コードを確認する

このセクションには、取得したコードサンプルに関する情報が含まれています。

レポートを生成して Cloud Storage にアップロードする

このシェル スクリプトは、現在のプロジェクトとリージョンで Cloud Run サービスのレポートを生成し、結果を Cloud Storage にアップロードします。名前に指定した文字列 search 引数を持つサービスをリストします。

このスクリプトは、gcloud run services list コマンド、gcloud 高度なフォーマット オプションgsutil ストリーミング転送コピーモードを使用します。

set -eo pipefail

# Check for required environment variables.
requireEnv() {
  test "${!1}" || (echo "gcloud-report: '$1' not found" >&2 && exit 1)
}
requireEnv GCLOUD_REPORT_BUCKET

# Prepare formatting: Default search term to include all services.
search=${1:-'.'}
limits='spec.template.spec.containers.resources.limits.flatten("", "", " ")'
format='table[box, title="Cloud Run Services"](name,status.url,metadata.annotations.[serving.knative.dev/creator],'${limits}')'

# Create a specific object name that will not be overridden in the future.
obj="gs://${GCLOUD_REPORT_BUCKET}/report-${search}-$(date +%s).txt"

# Write a report containing the service name, service URL, service account or user that
# deployed it, and any explicitly configured service "limits" such as CPU or Memory.
gcloud run services list \
  --format "${format}" \
  --filter "metadata.name~${search}" | gsutil -q cp -J - "${obj}"

# /dev/stderr is sent to Cloud Logging.
echo "gcloud-report: wrote to ${obj}" >&2
echo "Wrote report to ${obj}"

このスクリプトを繰り返し呼び出すと、よりコストがかからず、レポートが更新されるため、サービスとして実行しても安全です。新しい Cloud リソースの作成やコストのかかるタスクの実行など、gcloud CLI を使用する他のスクリプトは、何度も呼び出されると費用が高くなる場合があります。べき等のスクリプト(繰り返し呼び出しても同じ結果を生成するスクリプト)はサービスとして実行するほうが安全です。

HTTP リクエストでスクリプトを呼び出す

この Go のコードは、シェル スクリプトを実行してレポートを生成するウェブサービスを設定します。検索クエリはユーザー入力であるため、入力として悪意のあるコマンドを防ぐために、文字、数字、ハイフンのみが含まれように、コードによって入力が検証されます。この文字セットは、コマンド インジェクション攻撃を防ぐのに十分制限されています。

ウェブサービスは、引数として検索パラメータをシェル スクリプトに渡します。


// Service gcloud-report is a Cloud Run shell-script-as-a-service.
package main

import (
	"log"
	"net/http"
	"os"
	"os/exec"
	"regexp"
)

func main() {
	http.HandleFunc("/", scriptHandler)

	// 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 scriptHandler(w http.ResponseWriter, r *http.Request) {
	search := r.URL.Query().Get("search")
	re := regexp.MustCompile(`^[a-z]+[a-z0-9\-]*$`)
	if !re.MatchString(search) {
		log.Printf("invalid search criteria %q, using default", search)
		search = "."
	}

	cmd := exec.CommandContext(r.Context(), "/bin/bash", "script.sh", search)
	cmd.Stderr = os.Stderr
	out, err := cmd.Output()
	if err != nil {
		log.Printf("Command.Output: %v", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}
	w.Write(out)
}

go.mod ファイルは、go モジュールでアプリケーションの依存関係を宣言します。

module github.com/GoogleCloudPlatform/cloud-run-samples/gcloud-report

go 1.19

コンテナ環境を定義する

Dockerfile は、環境がどのようなものかをサービス向けに定義するものです。最終コンテナ イメージが gcloud Google Cloud CLI イメージに基づいている点を除いて、helloworld-shell クイックスタートの Dockerfile に似ています。これにより、Google Cloud CLI のカスタム インストールと構成の手順なしで、gcloudgsutil をサービスで使用できるようになります。


# Use the official golang image to create a binary.
# This is based on Debian and sets the GOPATH to /go.
# https://hub.docker.com/_/golang
FROM golang:1.20-buster as builder

# Create and change to the app directory.
WORKDIR /app

# Retrieve application dependencies.
# This allows the container build to reuse cached dependencies.
# Expecting to copy go.mod and if present go.sum.
COPY go.* ./
RUN go mod download

# Copy local code to the container image.
COPY invoke.go ./

# Build the binary.
RUN go build -mod=readonly -v -o server

# Use a gcloud image based on debian:buster-slim for a lean production container.
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM gcr.io/google.com/cloudsdktool/cloud-sdk:slim

WORKDIR /app

# Copy the binary to the production image from the builder stage.
COPY --from=builder /app/server /app/server
COPY *.sh /app/
RUN chmod +x /app/*.sh

# Run the web service on container startup.
CMD ["/app/server"]

Artifact Registry 標準リポジトリを作成する

コンテナ イメージを保存する Artifact Registry 標準リポジトリを作成します。

gcloud artifacts repositories create REPOSITORY \
    --repository-format=docker \
    --location=REGION

次のように置き換えます。

  • REPOSITORY は、リポジトリの一意の名前に置き換えます。
  • REGION は、Artifact Registry の Google Cloud リージョンに置き換えます。

Cloud Storage バケットを設定する

レポートをアップロードする Cloud Storage バケットを作成します。

gsutil mb gs://REPORT_ARCHIVE_BUCKET

REPORT_ARCHIVE_BUCKET は、グローバルに一意のバケット名に置き換えます。

サービス ID を設定する

サービスが持っている他のインフラストラクチャに対する権限を制限するには、サービス ID を作成し、作業に必要な特定の IAM 権限をカスタマイズします。

その場合、必要な権限は Cloud Run サービスを読み取る権限と、Cloud Storage バケットとの間で読み書きを行う権限です。

  1. サービス アカウントを作成します。

    gcloud iam service-accounts create gcloud-report-identity

  2. サービス アカウントに Cloud Run サービスの読み取り権限を付与します。

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=serviceAccount:gcloud-report-identity@PROJECT_ID.iam.gserviceaccount.com \
      --role roles/run.viewer
  3. Cloud Storage バケットに対して読み書きを行う権限をサービス アカウントに付与します。

    gsutil iam ch \
      serviceAccount:gcloud-report-identity@PROJECT_ID.iam.gserviceaccount.com:objectViewer,objectCreator \
      gs://REPORT_ARCHIVE_BUCKET

このカスタマイズされたサービス ID のアクセス制限により、サービスが他の Google Cloud リソースにアクセスすることを防ぎます。

サービスを公開する

配布コードは次の 3 つのステップで構成されます。

  • Cloud Build でコンテナ イメージを作成します。
  • コンテナ イメージを Artifact Registry にアップロードします。
  • コンテナ イメージを Cloud Run にデプロイします。

コードを配布するには:

  1. コンテナをビルドして、Artifact Registry に公開します。

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/gcloud-report

    次のように置き換えます。

    • PROJECT_ID は、Google Cloud プロジェクト ID に置き換えます。
    • REPOSITORY は、Artifact Registry リポジトリの名前に置き換えます。
    • REGION は、Artifact Registry の Google Cloud リージョンに置き換えます。

    gcloud-report は、サービスの名前です。

    成功すると、SUCCESS メッセージに ID、作成時間、イメージの名前が表示されます。イメージは Artifact Registry に保存され、必要に応じて再利用できます。

  2. 次のコマンドを実行して、サービスをデプロイします。

    gcloud run deploy gcloud-report \
       --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/gcloud-report \
       --update-env-vars GCLOUD_REPORT_BUCKET=REPORT_ARCHIVE_BUCKET \
       --service-account gcloud-report-identity \
       --no-allow-unauthenticated

    次のように置き換えます。

    • PROJECT_ID は、Google Cloud プロジェクト ID に置き換えます。
    • REPOSITORY は、Artifact Registry リポジトリの名前に置き換えます。
    • REGION は、サービスの Google Cloud リージョンに置き換えます。

    gcloud-report は、コンテナ名とサービス名の一部です。コンテナ イメージは、gcloud を設定するで構成したサービスとリージョン(Cloud Run)にデプロイされます。

    --no-allow-unauthenticated フラグは、サービスへの未認証アクセスを制限します。サービスを非公開にすることで、Cloud Run の組み込み認証を利用して不正なリクエストをブロックできます。Identity and Access Management(IAM)に基づく認証の詳細については、IAM を使用したアクセスの管理をご覧ください。

    デプロイが完了するまで待ちます。これには 30 秒ほどかかる場合があります。成功すると、コマンドラインにサービス URL が表示されます。

  3. サービスにコードの更新をデプロイする場合は、上記のステップを繰り返します。サービスをデプロイするたびに、リビジョンが作成されます。準備ができると、トラフィックの送信が自動的に開始します。

Google Cloud ユーザーにこのサービスの呼び出し権限を付与する方法については、IAM を使用してアクセスを管理するをご覧ください。プロジェクト編集者とオーナーには、自動的にこの権限が付与されます。

レポートを生成する

Cloud Run サービスのレポートを生成するには:

  1. curl を使用して認証済みリクエストを送信します。

    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" SERVICE_URL

    SERVICE_URL は、デプロイの完了後に Cloud Run で提示された URL に置き換えます。

    新しいプロジェクトを作成して、このチュートリアルに沿って操作した場合、出力は次のようになります。

    Wrote report to gs://REPORT_ARCHIVE_BUCKET/report-.-DATE.txt

    ファイル名の . は、ソースコードに記載されているデフォルトの検索引数です。

    検索結果の機能を使用するには、リクエストに search 引数を追加します。

    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" SERVICE_URL?search=gcloud

    このクエリは次のような出力を返します。

    Wrote report to gs://REPORT_ARCHIVE_BUCKET/report-gcloud-DATE.txt
  2. gsutil ツールを使用してローカルでファイルを取得します。

    gsutil cp gs://REPORT_FILE_NAME .

    コマンド内の . は、現在の作業ディレクトリを意味します。

    REPORT_FILE_NAME は、前の手順で出力した Cloud Storage オブジェクト名に置き換えます。

ファイルを開いてレポートを確認します。次のようになります。

4 つのサービス属性の列を含む、プロジェクト内の Cloud Run サービスのリストのスクリーンショット。
4 つの列はサービスの説明から取得されます。これには、サービスの名前、最初のデプロイに割り当てられた URL、サービスの最初の作成者、サービスの最大の CPU とメモリの上限 を使用します。

将来に向けた堅牢性の改善

このサービの開発をさらに進める場合は、より堅牢なプログラミング言語で書き直し、Cloud Run Admin APICloud Storage クライアント ライブラリの使用を検討してください。

gcloud コマンドに --log-http を追加し、gsutil コマンドに -D を追加すると、行われている API 呼び出しを調査(と一部の認証の詳細を確認)できます。

このオペレーションを自動化する

これで、Cloud Run サービスのレポートを HTTP リクエストによってトリガーできるようになりました。レポートが必要なときは、レポートの生成に以下の自動化を使用します。

クリーンアップ

このチュートリアル用に新規プロジェクトを作成した場合は、そのプロジェクトを削除します。既存のプロジェクトを使用し、このチュートリアルで変更を加えずに残す場合は、チュートリアル用に作成したリソースを削除します。

プロジェクトを削除する

課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. Google Cloud コンソールで、[リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

チュートリアル リソースを削除する

  1. このチュートリアルでデプロイした Cloud Run サービスを削除します。

    gcloud run services delete SERVICE-NAME

    SERVICE-NAME は、選択したサービス名です。

    Cloud Run サービスは Google Cloud コンソールから削除することもできます。

  2. チュートリアルの設定時に追加した gcloud のデフォルト リージョン構成を削除します。

     gcloud config unset run/region
    
  3. プロジェクト構成を削除します。

     gcloud config unset project
    
  4. このチュートリアルで作成した他の Google Cloud リソースを削除します。

次のステップ