𝕏 f B! L
案件・求人数 12,345
案件を探す(準備中) エージェントを探す(準備中) お役立ち情報 ログイン
案件・求人数 12,345
Google Cloud Run Functions第2世代完全ガイド【サーバーレス関数の進化と移行術】

Google Cloud Run Functions第2世代完全ガイド【サーバーレス関数の進化と移行術】

Google CloudCloud Run FunctionsサーバーレスCloud Functions
目次
⚡ 3秒でわかる!この記事のポイント
  • Cloud Run Functions第2世代はCloud Runベースに刷新され処理時間60分・メモリ32GBに大幅拡張
  • 第1世代からの移行手順とコード変更のポイントを詳細に解説
  • Eventarc統合・トラフィック分割・最小インスタンスで本番運用品質を実現

Google Cloudのサーバーレス関数サービスが**Cloud Functions(第1世代)からCloud Run Functions(第2世代)**へと大きく進化しました。基盤がCloud Runに統合されたことで、処理時間・メモリ・同時実行の制限が大幅に緩和され、より幅広いユースケースに対応できるようになっています。

本記事では、第2世代の新機能と改善点、第1世代からの移行手順、SES現場での実践的な活用法を詳しく解説します。

この記事でわかること
  • Cloud Run Functions第2世代のアーキテクチャと新機能
  • 第1世代との詳細な比較と移行手順
  • Eventarc・Cloud Run統合による高度なイベント処理
  • パフォーマンス最適化とコスト削減テクニック

Cloud Run Functions第2世代とは

アーキテクチャの変化

第2世代では、内部基盤がCloud Runに統合されました。これにより、Cloud Runの持つ強力なインフラ機能をサーバーレス関数から利用できるようになりました。

【第1世代アーキテクチャ】
ユーザー → Cloud Functions独自基盤 → 関数実行

【第2世代アーキテクチャ】
ユーザー → Cloud Run基盤 → Cloud Run Functions → 関数実行

         Eventarc(イベント駆動)
         Cloud Build(ビルド)
         Artifact Registry(コンテナ保存)

第1世代 vs 第2世代 比較表

機能第1世代第2世代
処理時間上限9分(540秒)60分(3,600秒)
メモリ上限8 GB32 GB
vCPU最大2最大8
同時実行数/インスタンス1最大1,000
最小インスタンスなし対応
トラフィック分割なし対応
イベントトリガー独自Eventarc
VPCコネクタ必須Direct VPC egress
リビジョン管理なし対応
Cloud Run統合なしネイティブ

Cloud Run Functions第2世代アーキテクチャ図解

第2世代のセットアップ

プロジェクト初期化

# 必要なAPIの有効化
gcloud services enable \
  cloudfunctions.googleapis.com \
  run.googleapis.com \
  eventarc.googleapis.com \
  cloudbuild.googleapis.com \
  artifactregistry.googleapis.com

# プロジェクト設定
gcloud config set project my-project-id
gcloud config set run/region asia-northeast1

HTTP関数の作成

// index.ts - HTTP関数(第2世代)
import { HttpFunction } from '@google-cloud/functions-framework';

export const helloWorld: HttpFunction = (req, res) => {
  const name = req.query.name || req.body?.name || 'World';

  res.json({
    message: `Hello, ${name}!`,
    version: '2nd-gen',
    timestamp: new Date().toISOString(),
    region: process.env.FUNCTION_REGION || 'unknown',
  });
};
// package.json
{
  "name": "cloud-run-functions-demo",
  "version": "1.0.0",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc",
    "start": "functions-framework --target=helloWorld",
    "deploy": "gcloud functions deploy hello-world --gen2 --runtime=nodejs22 --trigger-http --allow-unauthenticated --region=asia-northeast1 --entry-point=helloWorld"
  },
  "dependencies": {
    "@google-cloud/functions-framework": "^3.4.0"
  },
  "devDependencies": {
    "typescript": "^5.4.0",
    "@types/node": "^22.0.0"
  }
}

デプロイ

# HTTP関数のデプロイ
gcloud functions deploy hello-world \
  --gen2 \
  --runtime=nodejs22 \
  --trigger-http \
  --allow-unauthenticated \
  --region=asia-northeast1 \
  --memory=256Mi \
  --cpu=1 \
  --timeout=60s \
  --min-instances=0 \
  --max-instances=100 \
  --entry-point=helloWorld

# デプロイ確認
gcloud functions describe hello-world \
  --gen2 \
  --region=asia-northeast1

Eventarc統合によるイベント駆動

Eventarcの概要

第2世代ではEventarcがイベントトリガーの標準となりました。Cloud Storageのアップロード、Pub/Subメッセージ、Firestoreの変更など、90以上のGCPサービスからのイベントを受信できます。

Cloud Storage トリガー

// storage-trigger.ts
import { CloudEvent } from '@google-cloud/functions-framework';
import { Storage } from '@google-cloud/storage';
import sharp from 'sharp';

interface StorageObjectData {
  bucket: string;
  name: string;
  contentType: string;
  size: string;
}

const storage = new Storage();

export const processUploadedImage = async (
  event: CloudEvent<StorageObjectData>
) => {
  const { bucket, name, contentType } = event.data!;

  if (!contentType?.startsWith('image/')) {
    console.log(`Skipping non-image file: ${name}`);
    return;
  }

  console.log(`Processing image: gs://${bucket}/${name}`);

  // 画像のリサイズ処理
  const file = storage.bucket(bucket).file(name);
  const [buffer] = await file.download();

  const resized = await sharp(buffer)
    .resize(800, 600, { fit: 'inside' })
    .webp({ quality: 85 })
    .toBuffer();

  const thumbnailName = `thumbnails/${name.replace(/\.[^.]+$/, '.webp')}`;

  await storage.bucket(bucket).file(thumbnailName).save(resized, {
    metadata: { contentType: 'image/webp' },
  });

  console.log(`Thumbnail created: ${thumbnailName}`);
};
# Cloud Storage トリガーでデプロイ
gcloud functions deploy process-uploaded-image \
  --gen2 \
  --runtime=nodejs22 \
  --trigger-event-filters="type=google.cloud.storage.object.v1.finalized" \
  --trigger-event-filters="bucket=my-upload-bucket" \
  --region=asia-northeast1 \
  --memory=1Gi \
  --cpu=2 \
  --timeout=300s \
  --entry-point=processUploadedImage

Firestore トリガー

// firestore-trigger.ts
import { CloudEvent } from '@google-cloud/functions-framework';
import { Firestore } from '@google-cloud/firestore';

interface FirestoreEventData {
  value: {
    name: string;
    fields: Record<string, any>;
  };
  oldValue?: {
    name: string;
    fields: Record<string, any>;
  };
}

const db = new Firestore();

export const onOrderCreated = async (
  event: CloudEvent<FirestoreEventData>
) => {
  const { value } = event.data!;
  const orderId = value.name.split('/').pop();

  console.log(`New order created: ${orderId}`);

  // 注文処理のワークフロー
  // 1. 在庫チェック
  // 2. 決済処理
  // 3. 確認メール送信
  // 4. 配送手配

  await db.collection('order-logs').add({
    orderId,
    status: 'processing',
    timestamp: new Date(),
  });
};

Pub/Sub トリガー

// pubsub-trigger.ts
import { CloudEvent } from '@google-cloud/functions-framework';

interface PubSubData {
  message: {
    data: string;  // base64エンコード
    attributes: Record<string, string>;
  };
}

export const processMessage = async (
  event: CloudEvent<PubSubData>
) => {
  const data = JSON.parse(
    Buffer.from(event.data!.message.data, 'base64').toString()
  );

  console.log('Received message:', data);

  // メッセージ処理
  switch (data.type) {
    case 'user.created':
      await handleUserCreated(data.payload);
      break;
    case 'order.completed':
      await handleOrderCompleted(data.payload);
      break;
    default:
      console.warn(`Unknown event type: ${data.type}`);
  }
};

async function handleUserCreated(payload: any) {
  // ウェルカムメール送信、初期設定など
}

async function handleOrderCompleted(payload: any) {
  // レポート更新、通知送信など
}

第2世代の強力な新機能

同時実行(Concurrency)

第2世代の最大の改善点の1つが、1インスタンスで複数リクエストを同時処理できるようになったことです。

# 同時実行数を設定してデプロイ
gcloud functions deploy api-handler \
  --gen2 \
  --runtime=nodejs22 \
  --trigger-http \
  --region=asia-northeast1 \
  --concurrency=80 \
  --cpu=2 \
  --memory=1Gi \
  --min-instances=1 \
  --max-instances=50
【同時実行の効果】
第1世代: 100リクエスト/秒 → 100インスタンス必要
第2世代: 100リクエスト/秒 → 2-5インスタンスで処理可能

                        コスト75%削減!

最小インスタンス(Min Instances)

コールドスタートを回避するために、最小インスタンス数を設定できます。

# 最小インスタンスを設定
gcloud functions deploy critical-api \
  --gen2 \
  --min-instances=2 \
  --max-instances=100
ユースケースmin-instances推奨値
API(レイテンシ重視)1-3
バッチ処理0
Webhook受信1
社内ツール0
本番API(高トラフィック)3-10

トラフィック分割

カナリアデプロイやA/Bテストを実現するトラフィック分割機能です。

# 新しいリビジョンをデプロイ(トラフィック0%)
gcloud functions deploy my-function \
  --gen2 \
  --no-traffic

# 10%のトラフィックを新リビジョンに振り分け
gcloud run services update-traffic my-function \
  --region=asia-northeast1 \
  --to-revisions=my-function-00002-abc=10

# 問題なければ100%に切り替え
gcloud run services update-traffic my-function \
  --region=asia-northeast1 \
  --to-latest

Direct VPC Egress

VPCコネクタを使わずに直接VPCにアクセスできるようになりました。

# Direct VPC egressでデプロイ
gcloud functions deploy internal-api \
  --gen2 \
  --network=my-vpc \
  --subnet=my-subnet \
  --egress-settings=private-ranges-only \
  --region=asia-northeast1

第1世代からの移行

移行チェックリスト

□ ランタイムバージョンの確認(Node.js 22推奨)
□ --gen2 フラグの追加
□ イベントトリガーのEventarc形式への変更
□ 環境変数の移行
□ IAM権限の更新
□ VPC接続設定の見直し
□ テストの実行と動作確認
□ モニタリング・アラートの再設定

コード変更のポイント

// 第1世代(変更前)
import { Request, Response } from '@google-cloud/functions-framework';

export const myFunction = (req: Request, res: Response) => {
  // Cloud Functions独自のシグネチャ
  res.send('Hello');
};

// 第2世代(変更後) - 同じシグネチャが使用可能!
import { HttpFunction } from '@google-cloud/functions-framework';

export const myFunction: HttpFunction = (req, res) => {
  // 基本的にはコード変更不要
  res.send('Hello');
};

イベントトリガーの変更:

// 第1世代のCloud Storageトリガー
export const processFile = (data: any, context: any) => {
  const file = data;
  console.log(`Processing: ${file.name}`);
};

// 第2世代のCloud Storageトリガー
import { CloudEvent } from '@google-cloud/functions-framework';

export const processFile = (event: CloudEvent<StorageObjectData>) => {
  const file = event.data!;
  console.log(`Processing: ${file.name}`);
};

デプロイコマンドの変更

# 第1世代
gcloud functions deploy my-function \
  --runtime=nodejs20 \
  --trigger-bucket=my-bucket

# 第2世代
gcloud functions deploy my-function \
  --gen2 \
  --runtime=nodejs22 \
  --trigger-event-filters="type=google.cloud.storage.object.v1.finalized" \
  --trigger-event-filters="bucket=my-bucket" \
  --region=asia-northeast1

パフォーマンス最適化

コールドスタート対策

// グローバルスコープで初期化(インスタンス再利用時に効く)
import { Firestore } from '@google-cloud/firestore';
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';

// これらはコールドスタート時のみ初期化される
const db = new Firestore();
const secretManager = new SecretManagerServiceClient();
let cachedApiKey: string | null = null;

export const myFunction: HttpFunction = async (req, res) => {
  // APIキーのキャッシュ
  if (!cachedApiKey) {
    const [secret] = await secretManager.accessSecretVersion({
      name: 'projects/my-project/secrets/api-key/versions/latest',
    });
    cachedApiKey = secret.payload?.data?.toString() || '';
  }

  // 処理実行
  const result = await processRequest(req.body, cachedApiKey);
  res.json(result);
};

メモリ・CPU最適化

【ユースケース別推奨設定】
┌───────────────────────┬───────┬────────┬───────────┐
│ ユースケース           │ CPU   │ メモリ  │ タイムアウト │
├───────────────────────┼───────┼────────┼───────────┤
│ 軽量API               │ 0.083 │ 128Mi  │ 10s       │
│ 標準API               │ 1     │ 512Mi  │ 30s       │
│ 画像処理              │ 2     │ 2Gi   │ 120s      │
│ データ処理            │ 4     │ 8Gi   │ 540s      │
│ ML推論               │ 8     │ 32Gi  │ 3600s     │
│ バッチ処理            │ 4     │ 4Gi   │ 3600s     │
└───────────────────────┴───────┴────────┴───────────┘

コスト最適化

【コスト計算例: 月間100万リクエスト】

第1世代(concurrency=1):
- CPU: 100万 × 0.5秒 × $0.000016/vCPU-秒 = $8.00
- メモリ: 100万 × 0.5秒 × 256MB × $0.0000025/GB-秒 = $0.32
- リクエスト: 100万 × $0.40/100万 = $0.40
- 合計: 約$8.72/月

第2世代(concurrency=80):
- CPU: 12,500インスタンス秒 × $0.000024/vCPU-秒 = $0.30
- メモリ: 12,500 × 256MB × $0.0000025/GB-秒 = $0.008
- リクエスト: 100万 × $0.40/100万 = $0.40
- 合計: 約$0.71/月

→ 第2世代で約92%のコスト削減!

SES現場での活用シナリオ

Webhook処理サーバー

// Stripe Webhook処理
export const stripeWebhook: HttpFunction = async (req, res) => {
  const sig = req.headers['stripe-signature'] as string;

  try {
    const event = stripe.webhooks.constructEvent(
      req.rawBody!,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET!
    );

    switch (event.type) {
      case 'payment_intent.succeeded':
        await handlePaymentSuccess(event.data.object);
        break;
      case 'customer.subscription.deleted':
        await handleSubscriptionCancelled(event.data.object);
        break;
    }

    res.json({ received: true });
  } catch (err) {
    console.error('Webhook error:', err);
    res.status(400).send(`Webhook Error: ${err}`);
  }
};

スケジュール実行(Cloud Scheduler連携)

# 日次レポート生成ジョブ
gcloud scheduler jobs create http daily-report \
  --schedule="0 9 * * *" \
  --time-zone="Asia/Tokyo" \
  --uri="https://asia-northeast1-my-project.cloudfunctions.net/daily-report" \
  --http-method=POST \
  --oidc-service-account-email=scheduler@my-project.iam.gserviceaccount.com

マイクロサービスのエンドポイント

// マイクロサービス: ユーザーサービス
export const userService: HttpFunction = async (req, res) => {
  const { method, path } = req;

  try {
    switch (`${method} ${path}`) {
      case 'GET /users':
        return res.json(await listUsers(req.query));
      case 'GET /users/:id':
        return res.json(await getUser(req.params.id));
      case 'POST /users':
        return res.status(201).json(await createUser(req.body));
      case 'PUT /users/:id':
        return res.json(await updateUser(req.params.id, req.body));
      default:
        return res.status(404).json({ error: 'Not Found' });
    }
  } catch (error) {
    console.error('User service error:', error);
    res.status(500).json({ error: 'Internal Server Error' });
  }
};

まとめ

Cloud Run Functions第2世代は、Cloud Runベースへの刷新により大幅な性能向上とコスト削減を実現しました。

改善ポイント効果
処理時間上限9分 → 60分(6.7倍)
メモリ上限8GB → 32GB(4倍)
同時実行1 → 最大1,000
コスト最大92%削減(高トラフィック時)
コールドスタート最小インスタンスで回避

SES案件では、第2世代への移行支援Eventarc統合の設計・実装が求められる機会が増えています。Google Cloud Functions入門から基礎を固め、本記事の内容で第2世代の実践力を身につけましょう。

関連記事

SES案件をお探しですか?

SES記事をもっと読む →
🏗️

SES BASE 編集長

SES業界歴10年以上のメンバーが在籍する編集チーム。SES企業での営業・エンジニア経験、フリーランス独立経験を持つメンバーが、業界のリアルな情報をお届けします。

📊 業界データに基づく記事制作 🔍 IPA・経済産業省データ参照 💼 SES実務経験者が執筆・監修