Skip to content

新規テナントデプロイ手順

metro と同じ構成(Open WebUI + Agentic AI Server)で新規テナントを立ち上げる手順。

前提

  • AWS CLI, CDK CLI, Docker がインストール済み
  • 対象 AWS アカウントの profile が設定済み

1. CDK コード変更

1-1. types.ts に環境設定を追加

webui/cdk/lib/types.ts

// Environment 型にテナント名を追加
export type Environment = 'metro' | 'mlit' | 'demo' | '<新テナント名>';

// 環境設定を追加
export const NEW_CONFIG: EnvironmentConfig = {
  environment: '<新テナント名>',
  prefix: '<prefix>-ai',                    // 全リソース名のプレフィックス
  domainName: '<domain>',                    // アプリケーションドメイン
  cognitoUserPoolId: '<後で埋める>',           // 手順2で取得
  cognitoDomain: '<後で埋める>',               // 手順2で取得
  acmCertificateArn: undefined,              // 手順3で取得
  mcpServerUrl: 'https://<mcp-domain>/mcp',  // MCPサーバーURL
  awsProfile: '<profile>',
  accountId: '<account-id>',
};

1-2. app.ts にスタックを追加

webui/cdk/bin/app.ts

import { NEW_CONFIG } from '../lib/types';

const newCore = new CoreInfraStack(app, '<Name>AIv2Core', {
  env: { account: NEW_CONFIG.accountId, region: 'ap-northeast-1' },
  config: NEW_CONFIG,
  description: '<Name> AI Core Infrastructure (VPC, ALB, ECS Cluster)',
});

const newDb = new DatabaseStack(app, '<Name>AIv2Database', {
  env: { account: NEW_CONFIG.accountId, region: 'ap-northeast-1' },
  config: NEW_CONFIG,
  coreInfra: newCore.outputs,
  description: '<Name> AI Database (RDS PostgreSQL)',
});
newDb.addDependency(newCore);

const newApp = new AppStack(app, '<Name>AIv2App', {
  env: { account: NEW_CONFIG.accountId, region: 'ap-northeast-1' },
  config: NEW_CONFIG,
  coreInfra: newCore.outputs,
  database: newDb.outputs,
  description: '<Name> AI Application (ECS Services, Cognito)',
});
newApp.addDependency(newCore);
newApp.addDependency(newDb);

1-3. check-deployment.sh にテナントを追加(任意)

webui/scripts/check-deployment.sh に elif ブロックを追加。

2. Cognito User Pool 作成

# User Pool 作成
aws cognito-idp create-user-pool \
  --pool-name "<prefix>-ai-users" \
  --policies '{"PasswordPolicy":{"MinimumLength":12,"RequireUppercase":true,"RequireLowercase":true,"RequireNumbers":true,"RequireSymbols":false,"TemporaryPasswordValidityDays":7}}' \
  --username-attributes email \
  --auto-verified-attributes email \
  --mfa-configuration OFF \
  --account-recovery-setting '{"RecoveryMechanisms":[{"Priority":1,"Name":"verified_email"}]}' \
  --schema '[{"Name":"email","Required":true,"Mutable":false,"AttributeDataType":"String"},{"Name":"name","Required":false,"Mutable":true,"AttributeDataType":"String"}]' \
  --profile <profile>

# → 出力の UserPool.Id を types.ts の cognitoUserPoolId に設定

# Cognito ドメイン作成
aws cognito-idp create-user-pool-domain \
  --user-pool-id <user-pool-id> \
  --domain <prefix>-ai-auth \
  --profile <profile>

# → ドメイン名を types.ts の cognitoDomain に設定

M2M 認証用の Resource Server と App Client

MCP サーバーとの M2M 認証が必要な場合:

# Resource Server 作成
aws cognito-idp create-resource-server \
  --user-pool-id <user-pool-id> \
  --identifier docsearch \
  --name "Doc Search API" \
  --scopes '[{"ScopeName":"search","ScopeDescription":"Search access"},{"ScopeName":"read","ScopeDescription":"Read access"}]' \
  --profile <profile>

# M2M App Client 作成
aws cognito-idp create-user-pool-client \
  --user-pool-id <user-pool-id> \
  --client-name "<prefix>-ai-m2m" \
  --generate-secret \
  --allowed-o-auth-flows client_credentials \
  --allowed-o-auth-scopes "docsearch/read" "docsearch/search" \
  --allowed-o-auth-flows-user-pool-client \
  --profile <profile>

# → ClientId と ClientSecret を手順4の m2m-credentials に使用

3. ACM 証明書発行

# 証明書リクエスト
aws acm request-certificate \
  --domain-name <domain> \
  --validation-method DNS \
  --profile <profile>

# → CertificateArn を控える

# DNS 検証レコード取得
aws acm describe-certificate \
  --certificate-arn <cert-arn> \
  --query 'Certificate.DomainValidationOptions[0].ResourceRecord' \
  --profile <profile>

# → 出力の CNAME を Route53 / DNS に登録

# Route53 の場合:
aws route53 change-resource-record-sets \
  --hosted-zone-id <zone-id> \
  --change-batch '{
    "Changes": [{"Action":"UPSERT","ResourceRecordSet":{
      "Name":"<validation-name>","Type":"CNAME","TTL":300,
      "ResourceRecords":[{"Value":"<validation-value>"}]
    }}]
  }' --profile <profile>

# 検証完了を確認(数分待つ)
aws acm describe-certificate --certificate-arn <cert-arn> \
  --query 'Certificate.Status' --profile <profile>
# → "ISSUED" になったら types.ts の acmCertificateArn に設定

4. Secrets Manager 作成

# Anthropic API Key
aws secretsmanager create-secret \
  --name "<prefix>-ai/anthropic-api-key" \
  --secret-string "<api-key>" \
  --profile <profile>

# M2M 認証情報(手順2で取得した ClientId/Secret を使用)
aws secretsmanager create-secret \
  --name "<prefix>-ai/m2m-credentials" \
  --secret-string '{"client_id":"<id>","client_secret":"<secret>","cognito_domain":"<cognito-domain>"}' \
  --profile <profile>

5. ECR にイメージを準備

既存テナントのイメージをコピーする場合:

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

# ECR リポジトリ作成
aws ecr create-repository --repository-name <prefix>-ai-openwebui --profile <profile>
aws ecr create-repository --repository-name <prefix>-ai-agentic --profile <profile>

# 既存イメージの pull → tag → push
REGISTRY=<account-id>.dkr.ecr.ap-northeast-1.amazonaws.com

docker pull $REGISTRY/<既存prefix>-ai-openwebui:latest
docker tag  $REGISTRY/<既存prefix>-ai-openwebui:latest $REGISTRY/<prefix>-ai-openwebui:latest
docker push $REGISTRY/<prefix>-ai-openwebui:latest

docker pull $REGISTRY/<既存prefix>-ai-agentic:latest
docker tag  $REGISTRY/<既存prefix>-ai-agentic:latest $REGISTRY/<prefix>-ai-agentic:latest
docker push $REGISTRY/<prefix>-ai-agentic:latest

6. CDK synth で検証

cd webui/cdk
npx cdk synth <Name>AIv2Core <Name>AIv2Database <Name>AIv2App

types.ts の Cognito / ACM の値が全て埋まっていることを確認。

7. CDK デプロイ

npx cdk deploy <Name>AIv2Core --profile <profile> --require-approval never
npx cdk deploy <Name>AIv2Database --profile <profile> --require-approval never
npx cdk deploy <Name>AIv2App --profile <profile> --require-approval never

# または一括(依存関係は CDK が自動解決):
npx cdk deploy <Name>AIv2Core <Name>AIv2Database <Name>AIv2App --profile <profile> --require-approval never

所要時間の目安: - CoreInfra: 約3-4分(VPC, ALB, NAT Gateway) - Database: 約7-8分(RDS PostgreSQL) - App: 約5-6分(ECS Services, Cognito OAuth)

8. DNS 設定

CoreInfra デプロイ後に出力される ALB DNS Name を使って CNAME を登録:

# ALB DNS Name 確認
aws cloudformation describe-stacks --stack-name <Name>AIv2Core \
  --query 'Stacks[0].Outputs[?OutputKey==`AlbDnsName`].OutputValue' \
  --output text --profile <profile>

# Route53 に CNAME 登録
aws route53 change-resource-record-sets \
  --hosted-zone-id <zone-id> \
  --change-batch '{
    "Changes": [{"Action":"UPSERT","ResourceRecordSet":{
      "Name":"<domain>.","Type":"CNAME","TTL":300,
      "ResourceRecords":[{"Value":"<alb-dns-name>"}]
    }}]
  }' --profile <profile>

9. 動作確認

# HTTPS リダイレクト確認(302 → Cognito ログイン)
curl -s -o /dev/null -w "%{http_code}" https://<domain>/

# ユーザー作成
aws cognito-idp admin-create-user \
  --user-pool-id <user-pool-id> \
  --username <email> \
  --temporary-password 'TempPass123!' \
  --user-attributes Name=email,Value=<email> \
  --profile <profile>

作成されるリソース一覧

リソース 命名規則
VPC <prefix>-ai-v2-vpc
ALB <prefix>-ai-v2-alb
ECS Cluster <prefix>-ai-v2-cluster
RDS PostgreSQL <prefix>-ai-v2-openwebui-db
Target Group (WebUI) <prefix>-ai-v2-openwebui-tg
Target Group (Agentic) <prefix>-ai-v2-agentic-tg
Security Group (ALB) <prefix>-ai-v2-alb-sg
Security Group (ECS) <prefix>-ai-v2-ecs-sg
Security Group (RDS) <prefix>-ai-v2-rds-sg
CloudMap Namespace <prefix>-ai-v2.local
S3 (ALB Logs) <prefix>-ai-v2-alb-logs
ECR (OpenWebUI) <prefix>-ai-openwebui
ECR (Agentic) <prefix>-ai-agentic

削除する場合

スタックは依存関係の逆順で削除:

npx cdk destroy <Name>AIv2App --profile <profile>
npx cdk destroy <Name>AIv2Database --profile <profile>
npx cdk destroy <Name>AIv2Core --profile <profile>

別途手動で削除が必要なもの: - Cognito User Pool - Secrets Manager のシークレット(<prefix>-ai/anthropic-api-key, <prefix>-ai/m2m-credentials) - ACM 証明書 - DNS レコード - ECR リポジトリ(イメージが残っている場合 --force が必要)