新規テナントデプロイ手順
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 が必要)