このドキュメントでは、Mesh v2インフラストラクチャのデプロイと動作確認の手順を説明します。
- Docker および Docker Compose がインストール済み
- AWS CLI の認証情報がホスト上で設定済み(Docker に渡される)
- smalruby3-editor モノレポがクローン済み
デプロイ前に、AWS CLIが正しく設定されているか確認します。
aws sts get-caller-identity出力例:
{
"UserId": "AIDAXXXXXXXXXXXXXXXXX",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/your-username"
}# AWS認証情報の設定
aws configure
# 入力項目:
# - AWS Access Key ID
# - AWS Secret Access Key
# - Default region name (例: ap-northeast-1)
# - Default output format (例: json)モノレポのルートディレクトリから実行します:
# npm依存関係のインストール
docker compose run --rm infra npm install
# Ruby依存関係のインストール(テスト実行に必要)
docker compose run --rm infra bundle install
# TypeScriptのビルド
docker compose run --rm infra npm run buildMesh v2では、ステージごとに環境変数ファイルが用意されています。.env シンボリックリンクを切り替えることでデプロイ先を制御します。
| ステージ | .env ファイル |
用途 |
|---|---|---|
stg |
.env.stg |
ステージング(開発用、高速な間隔) |
stg2 |
.env.stg2 |
ステージング2(並行テスト用) |
prod |
.env.production |
本番環境(コスト最適化) |
cd infra/smalruby-mesh-v2
# ステージングに切り替え
rm .env && ln -s .env.stg .env
# 本番環境に切り替え
rm .env && ln -s .env.production .env
# 現在のステージを確認
ls -la .envCRITICAL: 常に .env シンボリックリンクの切り替えでステージを指定してください。コマンドラインで環境変数を直接上書きすると、カスタムドメインなどの重要なリソースが削除される可能性があります。
| 変数名 | 開発環境推奨値 | 本番環境推奨値 | 説明 |
|---|---|---|---|
STAGE |
stg |
prod |
デプロイステージ |
MESH_SECRET_KEY |
dev-secret-key-for-testing |
(GitHub Secretsで設定) | ドメイン検証用の秘密鍵 |
MESH_HOST_HEARTBEAT_INTERVAL_SECONDS |
15 |
60 |
ホストのハートビート送信間隔(秒) |
MESH_HOST_HEARTBEAT_TTL_SECONDS |
60 |
150 |
ホストグループの有効期限(秒) |
MESH_MEMBER_HEARTBEAT_INTERVAL_SECONDS |
15 |
120 |
メンバーのハートビート送信間隔(秒) |
MESH_MEMBER_HEARTBEAT_TTL_SECONDS |
60 |
600 |
メンバーノードの有効期限(秒) |
MESH_MAX_CONNECTION_TIME_SECONDS |
300 |
1500 |
グループの最大接続時間(秒) |
重要:
- TTLはハートビート間隔の約5倍に設定することで、ネットワーク遅延やタイムアウトに対する耐性を確保
- 開発環境では15秒間隔で素早くテスト可能
- 本番環境では120秒間隔でコスト削減とUXのバランスを実現
AWS環境でCDKを初めて使用する場合、bootstrapが必要です。
docker compose run --rm infra npx cdk bootstrapBootstrap完了後の出力例:
✅ Environment aws://123456789012/ap-northeast-1 bootstrapped.
aws cloudformation describe-stacks --stack-name CDKToolkitスタックが存在すればbootstrap済みです。
CloudFormationテンプレートを生成して、デプロイ内容を確認します。
# CloudFormationテンプレートの生成
docker compose run --rm infra npx cdk synth
# デプロイ差分の確認
docker compose run --rm infra npx cdk diff.env シンボリックリンクが正しいステージを指していることを確認してからデプロイします:
# 現在のステージを確認
ls -la infra/smalruby-mesh-v2/.env
# デプロイ(STAGE は .env symlink から読み取られる)
docker compose run --rm infra npx cdk deploy| Stage | Stack名 | DynamoDB Table名 | AppSync API名 |
|---|---|---|---|
| stg | MeshV2Stack-stg | MeshV2Table-stg | MeshV2Api-stg |
| prod | MeshV2Stack | MeshV2Table | MeshV2Api |
すべてのリソースには以下のタグが自動的に付与されます:
| タグキー | 値(stg) | 値(prod) |
|---|---|---|
| Project | MeshV2 | MeshV2 |
| Stage | stg | prod |
| Service | AppSync | AppSync |
| ManagedBy | CDK | CDK |
| ResourceType | GraphQLAPI / DynamoDB | GraphQLAPI / DynamoDB |
これらのタグは、AWS Cost Explorer でのコスト分析やリソースグルーピングに使用できます。
デプロイには数分かかります。進行状況がリアルタイムで表示されます。
デプロイが完了すると、以下のような出力が表示されます:
✅ MeshV2Stack
✨ Deployment time: 120.5s
Outputs:
MeshV2Stack.GraphQLApiEndpoint = https://xxxxxxxxxxxxxxxxxx.appsync-api.ap-northeast-1.amazonaws.com/graphql
MeshV2Stack.GraphQLApiId = xxxxxxxxxxxxxxxxxxxx
MeshV2Stack.GraphQLApiKey = da2-xxxxxxxxxxxxxxxxxxxxxxxxxx
MeshV2Stack.TableArn = arn:aws:dynamodb:ap-northeast-1:123456789012:table/MeshV2Table
MeshV2Stack.TableName = MeshV2Table
Stack ARN:
arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MeshV2Stack/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
重要: GraphQLApiEndpoint と GraphQLApiKey の値を控えてください。動作確認で使用します。
デプロイ後、カスタムドメインが正しく設定されていることを確認します:
# すべてのAppSyncカスタムドメインを確認
aws appsync list-domain-names --query "domainNameConfigs[].domainName" --output table
# 期待されるドメイン:
# graphql.api.smalruby.app (prod)
# stg.graphql.api.smalruby.app (stg)
# stg2.graphql.api.smalruby.app (stg2)
# DNS解決の確認
dig stg.graphql.api.smalruby.app A +short
dig graphql.api.smalruby.app A +shortカスタムドメインが欠けている場合は、正しい .env シンボリックリンクで再デプロイしてください。
- AWS Management Console にログイン
- AppSync サービスに移動
- MeshV2Api を選択
- Schema タブでGraphQLスキーマを確認
- AWS Management Console で DynamoDB サービスに移動
- Tables から MeshV2Table を選択
- Indexes タブで GroupIdIndex GSIを確認
AppSync Consoleの Queries タブで、以下のクエリをテストできます。
mutation CreateGroup {
createGroup(
name: "テストグループ1"
hostId: "host-001"
domain: "test-domain"
useWebSocket: true
) {
id
domain
fullId
name
hostId
expiresAt
useWebSocket
}
}query ListGroups {
listGroupsByDomain(domain: "test-domain") {
id
domain
fullId
name
hostId
expiresAt
}
}GraphQL APIが正しく動作しているか確認:
query IntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
subscriptionType {
name
}
}
}期待される出力:
{
"data": {
"__schema": {
"queryType": {
"name": "Query"
},
"mutationType": {
"name": "Mutation"
},
"subscriptionType": {
"name": "Subscription"
}
}
}
}wscat または AppSync Console の Queries タブで、統合された Subscription が正しく動作することを確認します。
subscription OnMessageInGroup {
onMessageInGroup(groupId: "test-group", domain: "test-domain") {
groupId
domain
nodeStatus {
nodeId
data {
key
value
}
}
batchEvent {
events {
name
}
}
groupDissolve {
message
}
}
}購読した状態で、別のタブから reportDataByNode mutation を実行し、データがリアルタイムで届くことを確認してください。
curl コマンドでAPIをテストすることもできます。
# 環境変数の設定
export APPSYNC_ENDPOINT="<GraphQLApiEndpoint の値>"
export API_KEY="<GraphQLApiKey の値>"
# イントロスペクションクエリの実行
curl -X POST "$APPSYNC_ENDPOINT" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-d '{
"query": "query { __schema { queryType { name } mutationType { name } subscriptionType { name } } }"
}' | jqデプロイされたリソースにタグが正しく付与されているか確認します。
AppSync APIのタグ確認:
# ステージング環境
API_ARN=$(aws appsync list-graphql-apis --query "graphqlApis[?name=='MeshV2Api-stg'].arn" --output text)
aws appsync list-tags-for-resource --resource-arn $API_ARN
# 本番環境
API_ARN=$(aws appsync list-graphql-apis --query "graphqlApis[?name=='MeshV2Api'].arn" --output text)
aws appsync list-tags-for-resource --resource-arn $API_ARN期待される出力:
{
"tags": {
"Project": "MeshV2",
"Service": "AppSync",
"Stage": "stg",
"ResourceType": "GraphQLAPI",
"ManagedBy": "CDK"
}
}DynamoDB Tableのタグ確認:
# ステージング環境
TABLE_ARN=$(aws dynamodb describe-table --table-name MeshV2Table-stg --query 'Table.TableArn' --output text)
aws dynamodb list-tags-of-resource --resource-arn $TABLE_ARN
# 本番環境
TABLE_ARN=$(aws dynamodb describe-table --table-name MeshV2Table --query 'Table.TableArn' --output text)
aws dynamodb list-tags-of-resource --resource-arn $TABLE_ARN期待される出力:
{
"Tags": [
{
"Key": "Project",
"Value": "MeshV2"
},
{
"Key": "Stage",
"Value": "stg"
},
{
"Key": "Service",
"Value": "AppSync"
},
{
"Key": "ResourceType",
"Value": "DynamoDB"
},
{
"Key": "ManagedBy",
"Value": "CDK"
}
]
}# ステージング環境のテーブル詳細を確認
aws dynamodb describe-table --table-name MeshV2Table-stg
# 本番環境のテーブル詳細を確認
aws dynamodb describe-table --table-name MeshV2Table
# GSIの確認(JSON形式で詳細表示)
aws dynamodb describe-table --table-name MeshV2Table-stg \
--query 'Table.GlobalSecondaryIndexes[*].{IndexName:IndexName,KeySchema:KeySchema}' \
--output json期待される出力:
[
{
"IndexName": "GroupIdIndex",
"KeySchema": [
{
"AttributeName": "gsi_pk",
"KeyType": "HASH"
},
{
"AttributeName": "gsi_sk",
"KeyType": "RANGE"
}
]
}
]デプロイ後、integration testsを実行して動作を検証します。
docker compose run --rm infra bash -c "
export APPSYNC_ENDPOINT=\$(aws cloudformation describe-stacks \
--stack-name MeshV2Stack-stg \
--query 'Stacks[0].Outputs[?OutputKey==\`GraphQLApiEndpoint\`].OutputValue' \
--output text)
export APPSYNC_API_KEY=\$(aws cloudformation describe-stacks \
--stack-name MeshV2Stack-stg \
--query 'Stacks[0].Outputs[?OutputKey==\`GraphQLApiKey\`].OutputValue' \
--output text)
echo \"APPSYNC_ENDPOINT: \$APPSYNC_ENDPOINT\"
echo \"APPSYNC_API_KEY: \$APPSYNC_API_KEY\"
bundle exec rspec spec/requests/ --format documentation
"AppSync APIのログはCloudWatch Logsに出力されます。
# ロググループ一覧の確認
aws logs describe-log-groups --log-group-name-prefix /aws/appsync/apis
# 最新のログストリームを確認
LOG_GROUP_NAME=$(aws logs describe-log-groups \
--log-group-name-prefix /aws/appsync/apis \
--query 'logGroups[0].logGroupName' \
--output text)
echo "Log Group: $LOG_GROUP_NAME"
# 最新ログの取得
aws logs tail "$LOG_GROUP_NAME" --followX-Rayトレーシングが有効になっているため、リクエストのトレース情報を確認できます。
- AWS Management Console で X-Ray サービスに移動
- Service map でMeshV2Apiを確認
- Traces でリクエストの詳細を確認
タグを使ってリソースをグルーピングし、一元管理できます。
ステージング環境のリソースグループ:
aws resource-groups create-group \
--name "MeshV2-stg" \
--resource-query '{
"Type": "TAG_FILTERS_1_0",
"Query": "{\"ResourceTypeFilters\":[\"AWS::AllSupported\"],\"TagFilters\":[{\"Key\":\"Project\",\"Values\":[\"MeshV2\"]},{\"Key\":\"Stage\",\"Values\":[\"stg\"]}]}"
}' \
--tags Project=MeshV2,Stage=stg本番環境のリソースグループ:
aws resource-groups create-group \
--name "MeshV2-prod" \
--resource-query '{
"Type": "TAG_FILTERS_1_0",
"Query": "{\"ResourceTypeFilters\":[\"AWS::AllSupported\"],\"TagFilters\":[{\"Key\":\"Project\",\"Values\":[\"MeshV2\"]},{\"Key\":\"Stage\",\"Values\":[\"prod\"]}]}"
}' \
--tags Project=MeshV2,Stage=prod# グループ一覧
aws resource-groups list-groups
# グループ内のリソース確認
aws resource-groups list-group-resources --group-name MeshV2-stgAWS Cost Explorerでタグを使ったコスト分析が可能です。
# ステージング環境のコスト
aws ce get-cost-and-usage \
--time-period Start=2025-01-01,End=2025-01-31 \
--granularity MONTHLY \
--metrics "UnblendedCost" \
--filter '{
"Tags": {
"Key": "Stage",
"Values": ["stg"]
}
}'開発環境のリソースを削除する場合:
# .env symlink が正しいステージを指していることを確認
ls -la infra/smalruby-mesh-v2/.env
# スタック削除
docker compose run --rm infra npx cdk destroy警告: この操作でDynamoDBテーブルとデータが完全に削除されます(RemovalPolicy: DESTROY設定のため)。
Error: Need to perform AWS calls for account XXX, but no credentials found
解決策: AWS認証情報を設定してください。
aws configureError: This stack uses assets, so the toolkit stack must be deployed to the environment
解決策: CDK Bootstrapを実行してください。
docker compose run --rm infra npx cdk bootstrapError: MeshV2Table already exists
解決策: 既存のスタックを削除するか、テーブル名を変更してください。
- CloudWatch Logsでエラーメッセージを確認
- API Keyが正しいか確認
- エンドポイントURLが正しいか確認
- IAM権限が正しく設定されているか確認