Google Cloud · ハンズオン学習ガイド

4つのサービスを繋いで
保存権限処理通知
ひとつのパイプラインにする。

写真管理アプリ「Memories」を題材に、Cloud Storage・IAM・Cloud Functions・Pub/Sub を組み合わせたイベント駆動サーバーレス環境をゼロから構築します。各サービスを「定義 → なぜ使うか → 具体例 → コード → ベストプラクティス」の順で解説し、最後に Challenge Lab(GSP315)で統合します。

対象:初学者〜ジュニアエンジニア学習時間:約1時間15分+Lab 1時間最終更新:2026-07-01
01
Orientation

このガイドについて

1.1スコープに関する注記

Google Skills(旧 Google Cloud Skills Boost)の個別ラボページは、受講登録済みアカウントでのサインインが必須のため、ラボ ID 単位(/labs/592541/labs/592550)での本文取得はできません。そのため本ガイドは、以下の情報源を根拠として再構成しています。

  • コース course_templates/637公式コース概要に明記された技術スコープ:Cloud Storage、IAM、Cloud Functions、Pub/Sub
  • 本コース末尾の Challenge Lab(labs/592550)である GSP315 の公開シナリオ・タスク構成
  • 各サービスの Google Cloud 公式ドキュメント(ベストプラクティスページ)

一般的にこの構成のコースは、①Cloud Storage の基本操作、②IAM によるアクセス制御、③Cloud Functions(現行の Cloud Run functions)のデプロイ、④Pub/Sub のメッセージング、という4つの実習を経て、最後にこれらを統合する Challenge Lab(GSP315)で総仕上げを行います。本ガイドはこの流れに沿って各サービスを解説します。

1.2提供された参照 URL の位置づけ

#URL(末尾)位置づけ(推定)
1labs/592541コース前半:Cloud Storage 実習
2labs/592542Cloud Storage 実習(CLI/SDK)
3labs/592543Cloud IAM 実習
4labs/592544Cloud Functions 実習(コンソール)
5labs/592545Cloud Functions 実習(コマンドライン)
6labs/592546Pub/Sub 実習(コンソール)
7labs/592547Pub/Sub 実習(コマンドライン)
8labs/592548Pub/Sub 実習(補足/言語別クライアント)
9labs/592549復習クイズ/知識確認
10labs/592550Challenge Lab(GSP315)※確認済み
9番までの厳密なラベルはサインインしないと確認できないため「推定」です。ただし 10番目が Challenge Lab (GSP315) であることは、複数の独立した情報源で一致しており確度は高いです。

02
Learning Path

コース全体像とラーニングパス

このコースは「写真管理アプリ Memories」というシナリオを軸に、ストレージ・権限管理・サーバーレス処理・非同期通知という、モダンなアプリ開発環境の基本4要素を一気通貫で学びます。

Fig 2.1 — 学習パイプラインの全体像

2.1なぜこの順番で学ぶのか

順番サービスこのコースにおける役割
1Cloud Storage画像などの非構造化データを保存する「置き場」を作る
2IAM誰が・どのリソースに・何をできるかを制御する土台を理解する
3Cloud Functionsアップロードをトリガーに自動処理(サムネイル生成など)を実行する
4Pub/Sub処理結果を他システムに非同期で通知する
5Challenge Lab上記すべてを組み合わせ、実務に近いシナリオを自力で完成させる

この流れは「ストレージにファイルが置かれる → 権限に基づいてイベントが検知される → 関数が起動して加工する → 完了をメッセージングで知らせる」という、サーバーレスなイベント駆動アーキテクチャの典型パターンそのものです。


03
Object Storage

Cloud Storage — オブジェクトストレージの基礎

3.1定義

Cloud Storage は、任意の量の非構造化データ(画像・動画・ログ・バックアップなど)をオブジェクトとして保存できるフルマネージドのストレージサービスです。データは「バケット」と呼ばれるコンテナに格納され、各バケットはプロジェクトに属します。

3.2なぜ使うか

  • サーバーの容量管理が不要で、ペタバイト級までシームレスにスケールする
  • 99.999999999%(イレブンナイン)の年間耐久性を持つ
  • Standard/Nearline/Coldline/Archive の4クラスでアクセス頻度に応じたコスト最適化ができる
  • Cloud Functions や Pub/Sub とイベント連携しやすい(本コースの核心)

3.3具体例(コンソールでの操作フロー)

Fig 3.1 — バケット作成〜アップロードの流れ

バケット名はグローバルネームスペースで一意である必要がありますが、オブジェクト名はバケット内でのみ一意であれば構いません。

3.4コード例(gcloud CLI)

bash
# 環境変数の準備
export PROJECT_ID=$(gcloud config get-value project)
export BUCKET_NAME="${PROJECT_ID}-photos"
export REGION="asia-northeast1"

# リージョンバケットを作成
gcloud storage buckets create gs://${BUCKET_NAME} \
  --project=${PROJECT_ID} \
  --location=${REGION} \
  --uniform-bucket-level-access

# オブジェクトをアップロード
gcloud storage cp ./sample.jpg gs://${BUCKET_NAME}/

# バケット内の一覧を確認
gcloud storage ls gs://${BUCKET_NAME}/
TIPgcloud storage コマンドは従来の gsutil の後継で、より高速かつ一貫性のある挙動をします。新規学習では gcloud storage を使うのがおすすめです。

3.5ベストプラクティス

#項目✅ 推奨❌ 避けるべき
1バケット命名機密情報を含まない推測されにくい名前にするmysecret-prod-bucket のように機密情報を露出させる
2アクセス制御均一バケットレベルアクセス(IAMのみ)を有効化し最小権限で運用オブジェクトごとにACLを個別設定して管理を複雑化させる
3公開設定公開が必要なオブジェクトだけを明示的に許可するバケット全体をうっかり公開設定にする
4ストレージクラスアクセス頻度に応じて4クラスを使い分けるすべて Standard のまま高コストを放置する
5再試行戦略新規コネクションでの再試行やヘッジドリクエストを実装する同一パスへの単純リトライのみで「サーバー固着」を起こす
6オブジェクト名ランダム性のあるプレフィックスでホットスポットを回避する連番やタイムスタンプのみの命名で書き込みを集中させる
7ライフサイクルルールで古いデータを自動的に低コスト化・削除する不要データを手動管理のまま放置しコストを増大させる

04
Access Control

Cloud IAM — アクセス制御の基礎

4.1定義

IAM(Identity and Access Management)は「誰が(Principal)」「どのリソースに(Resource)」「何をできるか(Permission)」を、ロールの付与によって制御する仕組みです。Google Cloud では権限を直接付与せず、権限をまとめた「ロール」を主体に紐づけます。

Fig 4.1 — Principal / Role / Permission / Resource の関係

4.2なぜ使うか

  • 誤操作や不正アクセスの被害範囲(ブラストラディウス)を最小化できる
  • Owner/Editor/Viewer の広範な基本ロールに頼らず、事前定義ロール(roles/storage.objectViewer など)で細かく制御できる
  • 退職者や異動者のアクセスを確実に取り消せる(Challenge Lab でも実施)

4.3具体例

このコースでは、プロジェクトに参加している「前任のクラウドエンジニア」のアクセス権を確認し、不要になった時点で削除する、実務でも頻出のシナリオを扱います。

Fig 4.2 — 前任エンジニアのアクセス権を取り消す

4.4コード例(gcloud CLI)

bash
# 現在のIAMポリシーを確認
gcloud projects get-iam-policy ${PROJECT_ID}

# 特定ユーザーの roles/viewer を削除(最小権限の原則の実践)
gcloud projects remove-iam-policy-binding ${PROJECT_ID} \
  --member="user:previous-engineer@example.com" \
  --role="roles/viewer"

# バケット単位で最小権限を付与する例(リソース単位に絞る)
gcloud storage buckets add-iam-policy-binding gs://${BUCKET_NAME} \
  --member="serviceAccount:thumbnail-fn@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/storage.objectViewer"

4.5ベストプラクティス

#項目✅ 推奨❌ 避けるべき
1最小権限の原則タスク遂行に必要な最小限の権限のみを付与するとりあえず roles/editorroles/owner を付与
2付与範囲バケットや関数などリソース単位でロールを絞り込むプロジェクト全体に広いロールを付与する
3サービスアカウント用途ごとに専用SAを作成し機能を分離するすべての関数で同一の高権限SAを共有する
4定期棚卸しIAM Recommender で未使用権限を定期的に削除する付与した権限を放置し「権限の肥大化」を起こす
5監査Cloud Audit Logs で IAM 変更を継続的に監視する権限変更を記録・追跡せず放置する
6グループ活用多数ユーザーへの付与はグループ単位で行うユーザーを1人ずつ列挙して管理コストを増やす

05
Serverless Compute

Cloud Functions(Cloud Run functions)

5.1定義

Cloud Functions は、サーバー管理不要でイベント(HTTP リクエストや Cloud Storage への書き込みなど)に応じて単一目的のコードを実行できるサーバーレス実行環境です。第2世代(Gen2)は Cloud Run 上で稼働し、現在は「Cloud Run functions」という製品名に統合されています。内部的には Cloud Run サービスと Eventarc トリガーの組み合わせとして構成されます。

Fig 5.1 — アップロードをトリガーにしたイベント処理パイプライン

5.2なぜ使うか

  • インフラのプロビジョニング不要で、コードをデプロイするだけで即座にスケールする
  • Cloud Storage・Pub/Sub・Firestore など多様なイベントソースと直接連携できる
  • 使った分だけの課金(リクエストが来ない間はコストが発生しない)

5.3具体例(コンソールでのデプロイ手順)

  1. 関数名・リージョン・トリガー種別(Cloud Storage の finalized イベント)を設定する
  2. 対象バケットを指定する
  3. エントリポイント(実行される関数名)とランタイム(例:Node.js 22)を設定する
  4. ソースコード(index.jspackage.json)を記述してデプロイする

5.4コード例(Node.js/概念コード)

Cloud Storage への画像アップロードをトリガーにサムネイルを生成し、完了を Pub/Sub に通知する処理の概念的な骨組みです。

javascript
const functions = require(@google-cloud/functions-framework);
const { Storage } = require(@google-cloud/storage);
const { PubSub } = require(@google-cloud/pubsub);
const { pipeline } = require(stream/promises);
const sharp = require(sharp);
 
const storage = new Storage();
const pubsub = new PubSub();
 
functions.cloudEvent(generateThumbnail, async (cloudEvent) => {
const event = cloudEvent.data;
const { bucket: bucketName, name: fileName } = event;
 
// 冪等性の確保:既にサムネイルなら再処理しない。拡張子なしのサムネイル名(例:xxx_thumb)も含む
if (fileName.includes('_thumb') || fileName.endsWith('_thumb')) {
console.log(`Skip: ${fileName} is already a thumbnail`);
return;
}
 
const bucket = storage.bucket(bucketName);
const dotIndex = fileName.lastIndexOf('.');
const thumbName = dotIndex !== -1 ? `${fileName.slice(0, dotIndex)}_thumb${fileName.slice(dotIndex)}` : `${fileName}_thumb`;
 
await pipeline(
bucket.file(fileName).createReadStream(),
sharp().resize(64, 64),
bucket.file(thumbName).createWriteStream()
);
 
await pubsub.topic(process.env.TOPIC_NAME).publishMessage({
data: Buffer.from(JSON.stringify({ thumbnail: thumbName })),
});
});
bash — deploy
# デプロイ例(Gen2 / Cloud Storage トリガー)
gcloud functions deploy generateThumbnail \
  --gen2 \
  --runtime=nodejs22 \
  --region=${REGION} \
  --source=. \
  --entry-point=generateThumbnail \
  --trigger-event-filters="type=google.cloud.storage.object.v1.finalized" \
  --trigger-event-filters="bucket=${BUCKET_NAME}" \
  --set-env-vars=TOPIC_NAME=${TOPIC_NAME} \
  --max-instances=2

5.5ベストプラクティス

#項目✅ 推奨❌ 避けるべき
1冪等性同じイベントで複数回呼ばれても同じ結果になるよう設計する副作用のある処理を無条件に繰り返し実行する
2無限ループ防止生成物が自分自身をトリガーしないようファイル名等でガードする生成物が再度トリガー対象になり無限ループが発生する
3コールドスタート対策依存を最小化し、重い初期化はグローバルスコープで1回だけ毎回の呼び出しで重い処理を再初期化する
4権限関数専用SAを作り必要な権限のみ付与するデフォルトSA(Editor相当)をそのまま使う
5依存の固定package-lock.json 等でバージョンを固定するバージョン未指定で環境ごとに挙動が変わる
6エラーハンドリング例外を捕捉しログ出力、必要に応じ再試行ポリシーを設定未処理の例外でクラッシュし原因追跡が困難になる

06
Async Messaging

Pub/Sub — 非同期メッセージング

6.1定義

Pub/Sub は、メッセージの送信者(Publisher)と受信者(Subscriber)を分離する非同期メッセージングサービスです。Publisher は「トピック」にメッセージを送信し、Subscriber は「サブスクリプション」を通じてメッセージを受信します。

Fig 6.1 — 1トピックから複数の Subscriber へのファンアウト

6.2なぜ使うか

  • Publisher と Subscriber が互いの稼働状況を意識せず疎結合で連携できる
  • 1トピックに複数のサブスクリプションを紐づける「ファンアウト」で、同じイベントを複数システムに配信できる
  • サービス障害時にもメッセージが保持され、リトライや再処理が可能

6.3具体例

Challenge Lab のシナリオでは、サムネイル生成完了を知らせるトピックを用意し、Cloud Function がそこにメッセージを発行します。この時点ではサブスクリプションを作らず「送信先の箱」だけを用意するのがポイントです(後続の消費者が必要になった時点で追加できます)。

6.4コード例(gcloud CLI)

bash
# トピックを作成
gcloud pubsub topics create ${TOPIC_NAME}

# 動作確認用にサブスクリプションを作成
gcloud pubsub subscriptions create ${TOPIC_NAME}-sub \
  --topic=${TOPIC_NAME}

# テストメッセージを発行
gcloud pubsub topics publish ${TOPIC_NAME} \
  --message="thumbnail generated"

# サブスクリプションからメッセージを取得
gcloud pubsub subscriptions pull ${TOPIC_NAME}-sub --auto-ack --limit=5

6.5ベストプラクティス

#項目✅ 推奨❌ 避けるべき
1Publisher再利用クライアントを使い回して接続確立のオーバーヘッドを避けるリクエストごとに新しいクライアントを生成する
2メッセージ保持Publish前にサブスクリプションを用意するか保持を有効化するサブスクリプション不在のままPublishし、メッセージを失う
3冪等な処理「少なくとも1回配信」を前提に重複処理に耐える設計にするメッセージが必ず1回だけ届く前提で実装する
4デッドレターキュー失敗し続けるメッセージをデッドレタートピックへ退避させる失敗メッセージが際限なく再配信され続ける
5順序保証順序が必要な場合のみ ordering key を設定する一律で順序保証を要求しスループットを落とす
6バッチ処理クライアントのバッチ機能でスループットとコストを最適化する1メッセージ1リクエストで大量発行しコストを増大させる

07
Capstone · GSP315

総合演習:Challenge Lab(GSP315)

7.1シナリオ概要

あなたは Jooli 社のジュニアクラウドエンジニアとして、写真管理アプリ「Memories」の開発チームから、アプリ開発環境の初期構築を依頼されます。ステップバイステップの手順書は与えられず、これまでの実習で得たスキルをもとに自力でタスクを完了させる、実務に近いシナリオです。

7.2統合アーキテクチャ図

Fig 7.1 — GSP315 の統合アーキテクチャ

7.3タスク一覧

タスク内容主な技術
Task 1写真保存用の Cloud Storage バケットを作成するCloud Storage
Task 2Cloud Run function が使用する Pub/Sub トピックを作成するPub/Sub
Task 3アップロードをトリガーにサムネイルを生成する関数(Gen2)を作成・デプロイFunctions / Eventarc
Task 4画像をアップロードしてインフラ全体の動作を検証するStorage / Functions / Pub/Sub
Task 5前任のクラウドエンジニアのプロジェクトアクセスを削除するIAM

7.4手順ごとの解説

Task 1: バケット作成 — ラボパネルに指定されたバケット名(例:qwiklabs-gcp-XX-xxxxxxxx-bucket)を使い、リージョンを選択してデフォルト設定で作成します。バケット名は採点システムが検証するため、指定された名前を正確に使用することが重要です。

Task 2: Pub/Sub トピック作成 — 関数が処理完了後にメッセージを発行するためのトピックを作成します。この段階ではサブスクリプションの作成は要求されていません(関数が Publisher として使うだけのため)。

Task 3: Cloud Run function(サムネイル生成)

  • トリガー:対象バケットへの Cloud Storage finalized イベント
  • エントリポイントはコード内の関数名と完全に一致させる(不一致はデプロイ後の動作不良の典型的な原因)
  • Eventarc がイベントを読み取れるよう、Cloud Storage サービスエージェントへ roles/pubsub.publisher を付与するなど権限伝播が必要な場合がある(数分のタイムラグあり)

Task 4: 動作検証 — 指定の画像(例:map.jpg)をアップロードし、数十秒〜数分後にサムネイルが生成されることを確認します。生成されない場合は関数の「トリガー」タブで設定が正しく保存されているか確認し、必要ならトリガーを再作成します。

Task 5: IAM クリーンアップ — プロジェクトには「あなた(Owner)」と「前任エンジニア(Viewer)」の2プリンシパルが存在します。前任エンジニアの roles/viewer バインディングを削除し、最小権限の原則を実践して完了します。

7.5よくあるエラーと対処

症状想定される原因対処
サムネイルが生成されないEventarc/Storage サービスエージェント権限が未伝播数分待って再アップロード、または権限設定を再確認
デプロイ成功だが関数がエラー終了エントリポイント名とコード内の関数名が不一致「エントリポイント」欄を関数名と完全一致させる
サムネイルが無限に生成される生成物自身が再度トリガー対象になっているファイル名にサフィックスを付け既存サムネイルを除外
Pub/Sub Publish でエラーStorage サービスエージェントに roles/pubsub.publisher 未付与該当サービスエージェントへ IAM ロールを追加
権限削除が完了と判定されない削除対象のメンバー/ロール指定が誤りget-iam-policy で現状確認してから正確に削除

08
Cheat Sheet

サービス横断ベストプラクティス早見表

観点Cloud StorageIAMCloud FunctionsPub/Sub
最小権限バケット単位でロールを付与リソース単位で付与関数専用SAを用意トピック/サブ単位で絞る
スケール対策ランダムプレフィックスでホットスポット回避該当なしコールドスタート対策・依存最小化バッチ発行で最適化
信頼性ライフサイクル管理・再試行戦略定期的な権限棚卸し冪等な処理設計デッドレターキュー・冪等Subscriber
可観測性アクセスログ・監査ログCloud Audit LogsCloud Logging でエラー監視未処理メッセージ滞留を監視

09
Troubleshooting

よくあるエラーとトラブルシューティング

カテゴリ症状チェックポイント
権限伝播遅延「Permission denied」が数分後に解消するEventarc/Storage サービスエージェントへの権限付与直後は数分の伝播待ちが必要
バケット名の衝突バケット作成に失敗するバケット名はグローバルで一意。プロジェクトID等を含めて一意性を担保する
関数のタイムアウト大きな画像処理で関数がタイムアウトするメモリ/タイムアウト設定を見直すか、ストリーム処理でメモリ使用量を削減
メッセージ消失Publishしたのにメッセージが届かないサブスクリプション未作成のままPublishしていないか確認(保持設定も検討)

10
References

参考ソース一覧

10.6 Challenge Lab(GSP315)シナリオ確認に使用したソース

以下は公式ドキュメントではなく、GSP315 のシナリオ・タスク構成を裏付けるために参照したコミュニティ/サードパーティ記事です。コード例はいずれも本ガイド用に独自に書き直しており、これらからの転載ではありません。