Kong Gatewayを使ったマイクロサービスAPI基盤の一例

Kong Gatewayを使ったマイクロサービスAPI基盤の一例

2025.12.23

ゲームソリューション部の えがわ です。

本ブログはClassmethod SaaSで加速するゲーム開発 Advent Calendar 2025の23日目のブログとなります。

https://dev.classmethod.jp/referencecat/gamesol-businesssol-advent-calendar-2025/

今回は、Kong Gatewayを使用したソーシャルゲーム向けマイクロサービスAPI基盤を試してみました。

本記事はAPI基盤の一例として、マイクロサービスアーキテクチャにおけるAPI Gateway導入のサンプルです。
実際のプロジェクトでは、要件に応じて構成やツールを選定してください。

ソースコードは以下のリポジトリに公開しています。
https://github.com/egawa-takeki/kong-game-api-demo

Kong Gatewayとは

Kong Gatewayは、APIリクエストを一元管理するAPI Gatewayです。
認証、レートリミット、ルーティングなどの機能をバックエンドサービスから切り離し、非機能要件をAPI Gateway層で処理できます。
マイクロサービスアーキテクチャでは、複数のサービスへのアクセスを一元化することで、クライアント側の実装をシンプルに保てます。

技術スタック

カテゴリ 技術
バックエンド Go 1.25 / Echo v4
データベース MySQL 8.4 (ローカル) / TiDB Cloud (本番)
コンテナ Docker / ECS Fargate
API Gateway Kong Gateway 3.12
Control Plane Kong Konnect (SaaS)
サービスディスカバリ AWS Cloud Map
IaC Terraform
API設定管理 decK (GitOps)

アーキテクチャ

全体構成

ハイブリッド型API Gatewayの構成

Kong Konnect(SaaS)をControl Plane、ECS FargateにデプロイしたKong GatewayをData Planeとして組み合わせています。

Control Plane(Kong Konnect SaaS)

  • 設定の保存・管理
  • 管理画面での設定確認・編集
  • 分析・モニタリング
  • WebSocket(443)でData Planeと常時接続

Data Plane(ECS Fargate上のKong Gateway)

  • 実際のトラフィック処理
  • ルーティング実行
  • プラグイン実行(JWT認証、レートリミットなど)
  • 証明書はAWS SSM Parameter Storeから取得

サービス構成

サービス ポート 役割 主要機能
User Service 8080 認証・ユーザー管理 ゲスト認証、JWT発行、通貨管理
Gacha Service 8080 ガチャ抽選 ガチャプール管理、抽選ロジック、Sagaオーケストレーション
Inventory Service 8080 アイテム管理 アイテム付与、所持アイテム管理
Kong Gateway 8000 API Gateway JWT認証、レートリミット、ルーティング

本プロジェクトではAPI Gatewayでの統一的なバリデーションと可読性を優先したため、HTTP/JSONを採用しました。一般的には、高スループット・低レイテンシが求められるユースケースではgRPCが検討対象になることもあります。

データベース構成(TiDB Cloud)

本プロジェクトでは、3つのマイクロサービスが単一のTiDB Cloudクラスターを共有しています。

一般的なマイクロサービスの原則では『サービスごとにDBを分離』が推奨されることが多いですが、本構成ではあえて共有DBを採用しています。
サービスごとにスキーマ(データベース)を分離しています。

サービス スキーマ名 主なテーブル
User Service game_user users, devices, currencies, refresh_tokens
Gacha Service game_gacha gacha_pools, gacha_items, gacha_histories, sagas
Inventory Service game_inventory user_items, item_masters

この構成により、スキーマレベルでの分離を維持しつつ、運用コストを抑えられます。
将来的にサービスが成長した場合は、TiDBのスケーラビリティでDBがボトルネックになることなく対応できます。

認証システム

ゲスト認証

デバイスIDベースの認証を実装しています。初回アクセス時に自動でユーザーを作成し、JWTトークンを発行します。

curl -X POST http://localhost:8000/v1/auth/guest \
  -H "Content-Type: application/json" \
  -d '{
    "device_id": "test-device-001",
    "device_type": "ios",
    "device_name": "iPhone 15"
  }'

レスポンス:

{
  "success": true,
  "data": {
    "user_id": "uuid",
    "player_id": "PLY123456",
    "access_token": "eyJhbG...",
    "refresh_token": "dGhpcyBpcy...",
    "is_guest": true
  }
}

JWT認証

Kong GatewayでJWT検証を行い、無効なトークンには401 Unauthorizedを返却します。認証不要なエンドポイント(/v1/auth/guest)はJWT検証をスキップするよう設定しています。

kong/kong.yaml
routes:
  # Guest authentication (NO JWT required)
  - name: auth-guest-route
    paths:
      - ~/v1/auth/guest$
    methods:
      - POST
    strip_path: false
    preserve_host: false

  # User routes (JWT required)
  - name: users-route
    paths:
      - /v1/users
    methods:
      - GET
      - PUT
    strip_path: false
    preserve_host: false
    plugins:
      - name: jwt
        config:
          claims_to_verify:
            - exp
          key_claim_name: iss
          header_names:
            - Authorization

ガチャシステム(Sagaパターン)

ガチャ抽選は複数のサービスにまたがる分散トランザクションのため、Sagaパターンで実装しています。

Sagaフロー

Saga状態の定義

backend/internal/gacha/domain/saga/gacha_draw_saga.go
type SagaStatus string

const (
	StatusStarted          SagaStatus = "STARTED"
	StatusCurrencyReserved SagaStatus = "CURRENCY_RESERVED"
	StatusDrawCompleted    SagaStatus = "DRAW_COMPLETED"
	StatusItemGranted      SagaStatus = "ITEM_GRANTED"
	StatusCompleted        SagaStatus = "COMPLETED"
	StatusCompensating     SagaStatus = "COMPENSATING"
	StatusCurrencyRefunded SagaStatus = "CURRENCY_REFUNDED"
	StatusFailed           SagaStatus = "FAILED"
)

Gacha ServiceがオーケストレーターとしてUser ServiceとInventory Serviceを呼び出し、各ステップでSagaの状態をDBに保存します。失敗時は補償トランザクションでロールバックを行います。

ガチャ実行の例

curl -X POST http://localhost:8000/v1/gacha/draw \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {access_token}" \
  -d '{
    "pool_id": "pool-standard",
    "draw_count": 10
  }'

レスポンス:

{
  "success": true,
  "data": {
    "saga_id": "uuid",
    "status": "COMPLETED",
    "results": [
      {
        "item_master_id": "char-ssr-001",
        "rarity": "SSR",
        "is_new": true,
        "is_pickup": false
      }
    ],
    "cost": {
      "currency_type": "free_gem",
      "amount": 3000
    },
    "pity": {
      "count": 10,
      "max_count": 90
    }
  }
}

API Gateway機能

レートリミット

サービス別にレートリミットを設定しています。

kong/kong.yaml
services:
  - name: user-service
    plugins:
      - name: rate-limiting
        config:
          minute: 30
          policy: local
          fault_tolerant: true

  - name: gacha-service
    plugins:
      - name: rate-limiting
        config:
          minute: 10
          policy: local
          fault_tolerant: true

  - name: inventory-service
    plugins:
      - name: rate-limiting
        config:
          minute: 60
          policy: local
          fault_tolerant: true

超過時は429 Too Many Requestsを返却します。

OAS Validation(Enterprise機能)

OpenAPI仕様に基づくリクエスト検証を行います。
リクエストボディ、ヘッダー、クエリパラメータ、パスパラメータを検証し、不正なリクエストには400 Bad Requestを返却します。

kong/kong.yaml
plugins:
  - name: oas-validation
    config:
      api_spec: "${OAS_API_SPEC}"
      api_spec_encoded: false
      validate_request_body: true
      validate_request_header_params: true
      validate_request_query_params: true
      validate_request_uri_params: true
      validate_response_body: false
      verbose_response: true

Correlation ID

リクエストごとにUUIDを生成し、X-Request-IDヘッダーでバックエンドに伝播します。ログトレーシングに活用できます。

kong/kong.yaml
plugins:
  - name: correlation-id
    config:
      header_name: X-Request-ID
      generator: uuid
      echo_downstream: true

インフラ構成(Terraform)

ディレクトリ構成

terraform/
├── main.tf              # モジュール呼び出し
├── variables.tf         # 変数定義
├── outputs.tf           # 出力定義
├── versions.tf          # バージョン指定
└── modules/
    ├── vpc/             # VPC・サブネット
    ├── security_groups/ # セキュリティグループ
    ├── alb/             # ALB・ターゲットグループ
    ├── cloudmap/        # Cloud Map(サービスディスカバリ)
    ├── ecr/             # ECRリポジトリ
    ├── ecs/             # ECSクラスター・タスク定義・サービス
    ├── ssm/             # SSM Parameter Store
    └── github_oidc/     # GitHub Actions用OIDC

モジュール構成

terraform/main.tf
module "vpc" {
  source = "./modules/vpc"
  project_name = var.project_name
  vpc_cidr     = var.vpc_cidr
}

module "cloudmap" {
  source = "./modules/cloudmap"
  project_name   = var.project_name
  vpc_id         = module.vpc.vpc_id
  namespace_name = "game.local"
}

module "ecs" {
  source = "./modules/ecs"
  project_name                        = var.project_name
  private_subnet_ids                  = module.vpc.private_subnet_ids
  kong_security_group_id              = module.security_groups.kong_security_group_id
  kong_konnect_control_plane_endpoint = var.kong_konnect_control_plane_endpoint
  # ...
}

Kong Data Planeタスク定義

terraform/modules/ecs/main.tf
resource "aws_ecs_task_definition" "kong" {
  family                   = "${var.project_name}-kong"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "256"
  memory                   = "512"
  execution_role_arn       = aws_iam_role.ecs_task_execution.arn
  task_role_arn            = aws_iam_role.ecs_task.arn

  container_definitions = jsonencode([
    {
      name      = "kong"
      image     = "kong/kong-gateway:3.12"
      essential = true

      environment = [
        { name = "KONG_ROLE", value = "data_plane" },
        { name = "KONG_DATABASE", value = "off" },
        { name = "KONG_CLUSTER_MTLS", value = "pki" },
        { name = "KONG_CLUSTER_CONTROL_PLANE", value = var.kong_konnect_control_plane_endpoint }
        # ...
      ]

      secrets = [
        { name = "KONG_CLUSTER_CERT_DATA", valueFrom = var.kong_cluster_cert_arn },
        { name = "KONG_CLUSTER_CERT_KEY_DATA", valueFrom = var.kong_cluster_cert_key_arn }
      ]
    }
  ])
}

AWS Cloud Map(サービスディスカバリ)

Kong GatewayからバックエンドサービスへのルーティングにCloud Mapを使用しています。

サービス DNS名
User Service user.game.local:8080
Gacha Service gacha.game.local:8080
Inventory Service inventory.game.local:8080

ECSサービスをCloud Mapに登録することで、タスクのIPアドレスが自動的にDNSに登録されます。

terraform/modules/ecs/main.tf
resource "aws_ecs_service" "user" {
  name            = "${var.project_name}-user"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.user.arn
  # ...

  service_registries {
    registry_arn   = var.user_service_registry_arn
    container_name = "user"
  }
}

GitOps(decK)

Kong設定の管理

Kong GatewayのルーティングやプラグインをYAMLファイルで定義し、decKを使用してKong Konnectに同期します。

kong/
└── kong.yaml    # Kong設定ファイル

CI/CDパイプライン

GitHub Actionsで自動デプロイを行います。

Pull Request時

  • deck gateway diffで変更内容を表示
  • PRコメントに差分を投稿

Mainブランチマージ時

  • OpenAPI仕様をKong設定に注入
  • deck gateway syncでKong Konnectに同期
.github/workflows/kong-deploy.yml
jobs:
  sync:
    name: Kong Config Sync
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - name: Inject OpenAPI spec into Kong config
        run: |
          yq -o=json '.' openapi.yaml | jq -c '.' > /tmp/oas-spec.json
          cp kong/kong.yaml kong/kong-with-oas.yaml
          export OAS_SPEC=$(cat /tmp/oas-spec.json)
          yq -i '
            (.plugins[] | select(.name == "oas-validation") | .config.api_spec) = strenv(OAS_SPEC)
          ' kong/kong-with-oas.yaml

      - name: Sync to Kong Konnect
        run: |
          deck gateway sync kong/kong-with-oas.yaml \
            --konnect-addr $KONG_ADDR \
            --konnect-token $KONG_TOKEN \
            --konnect-control-plane-name $KONG_CP_NAME

設定変更はGitHubにマージするだけで、本番環境に反映されます。

初回セットアップ

CI/CDパイプラインが動作するためには、まずインフラを手動で構築する必要があります。

事前準備

  1. Kong Konnectアカウント: Kong KonnectでControl Planeを作成し、Data Plane用の証明書を取得
  2. TiDB Cloudアカウント: データベースクラスターを作成し、接続情報を取得
  3. AWSアカウント: Terraformを実行するためのIAM権限を設定

Kongの証明書取得は以下の記事をご確認ください。

https://dev.classmethod.jp/articles/kong-fargate-otel-newrelic/#Kong%2520Konnect%2520%25E3%2581%25A7%2520Control%2520Plane%2520%25E3%2582%2592%25E4%25BD%259C%25E6%2588%2590

手動でのTerraform実行

初回は以下の手順でインフラを構築します。

cd terraform

# 変数ファイルを作成
cp terraform.tfvars.example terraform.tfvars
# terraform.tfvarsを編集し、各種シークレットを設定

# 初期化
terraform init

# 実行計画を確認
terraform plan

# インフラを構築
terraform apply

Dockerイメージのビルド・プッシュ

ECRリポジトリが作成されたら、初回のDockerイメージをプッシュします。

# ECRにログイン
aws ecr get-login-password --region ap-northeast-1 | \
  docker login --username AWS --password-stdin <ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com

# 各サービスをビルド・プッシュ
cd backend

# User Service
docker build -t <ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/kong-game/user-service:latest \
  -f docker/user-service/Dockerfile .
docker push <ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/kong-game/user-service:latest

# Gacha Service
docker build -t <ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/kong-game/gacha-service:latest \
  -f docker/gacha-service/Dockerfile .
docker push <ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/kong-game/gacha-service:latest

# Inventory Service
docker build -t <ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/kong-game/inventory-service:latest \
  -f docker/inventory-service/Dockerfile .
docker push <ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/kong-game/inventory-service:latest

GitHub Secretsの設定

CI/CDパイプラインが動作するよう、以下のSecretsをGitHubリポジトリに設定します。

Secret名 説明
AWS_ROLE_ARN GitHub OIDC用のIAMロールARN
KONG_KONNECT_ADDR Kong KonnectのAPIエンドポイント
KONG_KONNECT_TOKEN Kong Konnectのアクセストークン
KONG_KONNECT_CP_NAME Control Plane名
KONG_CLUSTER_CERT Data Plane用証明書
KONG_CLUSTER_CERT_KEY Data Plane用秘密鍵
DB_HOST, DB_PORT, DB_USER, DB_PASSWORD TiDB Cloud接続情報
JWT_SECRET JWT署名用シークレット

初回セットアップが完了すれば、以降はGitHubへのPush/Mergeで自動デプロイが実行されます。

デプロイフロー(CI/CD)

本プロジェクトでは、GitHub Actionsを使用した3種類のCI/CDパイプラインを用意しています。

Terraformデプロイ(インフラ)

terraform/配下のファイルが変更された際に実行されます。

トリガー 実行内容
Pull Request terraform plan → 変更内容をレビュー
Main マージ terraform apply → AWSリソースを更新

バックエンドデプロイ

backend/配下のファイルが変更された際に実行されます。変更されたサービスのみビルド・デプロイする効率的なパイプラインです。

変更対象 ビルド対象
backend/internal/user/** User Service のみ
backend/internal/gacha/** Gacha Service のみ
backend/internal/inventory/** Inventory Service のみ
backend/internal/shared/**, go.mod 全サービス

decKデプロイ(Kong設定)

kong/配下またはopenapi.yamlが変更された際に実行されます。

トリガー 実行内容
Pull Request deck gateway diff → 変更差分をPRにコメント
Main マージ deck gateway sync → Kong Konnectに即時反映

OpenAPI仕様(openapi.yaml)はCI/CD時にKong設定に注入されるため、API仕様とOAS Validationプラグインの設定が常に同期されます。

ローカル開発環境

Docker Composeで全サービスを起動できます。

cd backend
docker-compose up -d

起動後、以下のエンドポイントでアクセスできます。

ローカル環境と本番環境の違い

ローカル開発環境ではKong Gateway OSS版を使用しているため、エンタープライズ専用機能は利用できません

機能 ローカル(OSS) 本番(Konnect)
JWT認証 ✅ 利用可 ✅ 利用可
レートリミット ✅ 利用可 ✅ 利用可
Correlation ID ✅ 利用可 ✅ 利用可
OAS Validation ❌ スキップ ✅ 利用可

ローカル用のKong設定(backend/kong-local.yaml)では、OAS Validationプラグインを除外しています。
本番環境でのみOpenAPI仕様に基づくリクエスト検証が有効になります。

さいごに

今回はKong Gatewayを使用したマイクロサービスAPI基盤を構築してみました。
Kong Konnect(SaaS)とECS Fargateを組み合わせることで、運用負荷を軽減しつつ柔軟なAPI管理が実現できます。

GitOpsによる設定管理やSagaパターンによる分散トランザクションなど、実践的なパターンも試してみています。
この記事がどなたかの参考になれば幸いです。

この記事をシェアする

FacebookHatena blogX

関連記事