CloudFormationスタックの一部として定義されている既存のDynamoDBテーブルがあります。 CFN AWS :: DynamoDB :: Tableのドキュメント によると、GlobalSecondaryIndexes属性を置き換える必要はありません。以下の注意事項についても詳しく説明します。
1つのグローバルセカンダリインデックスを中断することなく削除または追加できます。
と同様に...
新しいグローバルセカンダリインデックスを含めるようにテーブルを更新すると、AWS CloudFormationはインデックスの作成を開始してから、スタックの更新を続行します。 AWS CloudFormationは、テーブルのサイズによってはバックフィルフェーズに時間がかかる可能性があるため、インデックスの作成が完了するのを待ちません。
ただし、実際には、更新を実行しようとすると、次のエラーメッセージが表示されます。
CloudFormation cannot update a stack when a custom-named resource requires replacing. Rename mytablename and update the stack again.
新しい属性を使用するGSIを追加しているので、置換が必要であると言うAttributeDefinitionsを変更する必要があります。ただし、AttributeDefinitionsで定義された既存の属性のみを使用してGSIを追加しようとしても、同じエラーメッセージが表示されます。
これが私のテーブルの元のCFN定義からのスニペットです:
{
"myTable": {
"Type": "AWS::DynamoDB::Table",
"Properties": {
"TableName": "mytablename",
"AttributeDefinitions": [
{
"AttributeName": "entryId",
"AttributeType": "S"
},
{
"AttributeName": "entryName",
"AttributeType": "S"
},
{
"AttributeName": "appId",
"AttributeType": "S"
}
],
"KeySchema": [
{
"KeyType": "HASH",
"AttributeName": "entryId"
},
{
"KeyType": "RANGE",
"AttributeName": "entryName"
}
],
"ProvisionedThroughput": {
"ReadCapacityUnits": {
"Ref": "readThroughput"
},
"WriteCapacityUnits": {
"Ref": "writeThroughput"
}
},
"GlobalSecondaryIndexes": [
{
"IndexName": "appId-index",
"KeySchema": [
{
"KeyType": "HASH",
"AttributeName": "appId"
}
],
"Projection": {
"ProjectionType": "KEYS_ONLY"
},
"ProvisionedThroughput": {
"ReadCapacityUnits": {
"Ref": "readThroughput"
},
"WriteCapacityUnits": {
"Ref": "writeThroughput"
}
}
}
]
}
}
}
これが私がそれを更新したいものです:
{
"myTable": {
"Type": "AWS::DynamoDB::Table",
"Properties": {
"TableName": "mytablename",
"AttributeDefinitions": [
{
"AttributeName": "entryId",
"AttributeType": "S"
},
{
"AttributeName": "entryName",
"AttributeType": "S"
},
{
"AttributeName": "appId",
"AttributeType": "S"
},
{
"AttributeName": "userId",
"AttributeType": "S"
}
],
"KeySchema": [
{
"KeyType": "HASH",
"AttributeName": "entryId"
},
{
"KeyType": "RANGE",
"AttributeName": "entryName"
}
],
"ProvisionedThroughput": {
"ReadCapacityUnits": {
"Ref": "readThroughput"
},
"WriteCapacityUnits": {
"Ref": "writeThroughput"
}
},
"GlobalSecondaryIndexes": [
{
"IndexName": "appId-index",
"KeySchema": [
{
"KeyType": "HASH",
"AttributeName": "appId"
}
],
"Projection": {
"ProjectionType": "KEYS_ONLY"
},
"ProvisionedThroughput": {
"ReadCapacityUnits": {
"Ref": "readThroughput"
},
"WriteCapacityUnits": {
"Ref": "writeThroughput"
}
}
},
{
"IndexName": "userId-index",
"KeySchema": [
{
"KeyType": "HASH",
"AttributeName": "userId"
}
],
"Projection": {
"ProjectionType": "KEYS_ONLY"
},
"ProvisionedThroughput": {
"ReadCapacityUnits": {
"Ref": "readThroughput"
},
"WriteCapacityUnits": {
"Ref": "writeThroughput"
}
}
}
]
}
}
}
ただし、前述のように、AttributeDefinitionsでuserIdを定義せず、新しいGSI定義で既存の属性を使用しても、機能せず、同じエラーメッセージで失敗します。
今日も同じエラーが発生し、Amazonテクニカルサポートから回答を得ました。問題は、TableNameフィールドを指定したことです。 CloudFormationは、テーブルの命名を担当したいと考えています。どうやら、あなたがそれらにあなた自身の名前を与えるとき、これはあなたがテーブルを置き換えるアップデートであなたが得るエラーです(なぜそれが置き換える必要があるのか分かりませんが、それはドキュメントが言っていることです)
私にとって、これによりCloudFormationはDynamoDBテーブルを維持するのにまったく役に立たなくなります。 CloudFormationが生成したランダムテーブル名をコードが動的に認識できるように、構成を組み込む必要があります。
AWSサポートの私への対応FWIW:
利点は、アプリコードが固定名を使い続けることができることです。ただし、スタックを2回更新し、データをエクスポート/インポートするには、カスタムスクリプトで自動化するための作業が必要になります。
これにより、余分なスタックの更新が回避されると思いますが(データのエクスポート/インポートが必要になると思います)、欠点は、テーブル名をフェッチするためのコード内のネットワーク呼び出しです。 * http://docs.aws.Amazon.com/AWSJavaScriptSDK/latest/AWS/CloudFormation.html#describeStackResource-property を参照してください
繰り返しになりますが、これは、サポートがサービスチームを推進している既知の問題です。これは、非常に一般的な使用例であり、問題点であることがわかっているためです。本番環境でテストする前に、テスト環境で回避策を試してください。
私のシナリオは、範囲キーを変更してGSIを更新したいというものでした。 -まず、更新するGSIを削除する必要があります。また、GSIの削除により不要になった可能性のあるAttributeDefinition、つまりインデックス名なども削除することを忘れないでください。CloudFormationを介してテンプレートをアップロードし、変更を適用します。 -次に、必要な属性と「更新された」GSIをテンプレートに追加します。
DynamoDBからすべてのデータをバックアップし、その後、サーバーレスを使用している場合は、以下のコマンドのいずれかを実行します。
個別削除:
node ./node_modules/serverless/bin/serverless remove
グローバルに削除:
serverless remove
次のコマンドを実行して、再度デプロイします。
node ./node_modules/serverless/bin/serverless deploy -v
または
serverless deploy
ここで問題はどのように発生しましたか?私の場合、dynamoDBコンソールでGSIを手動で削除してから、cloudformationでGSIを追加すると、update-stackでこのエラーが発生します。
解決策:cloudformationでGSIを削除し、update-stackを実行してから、GSIを追加し直し、update-stackを再度実行すると、正常に機能します。
Cloudformationには独自のキャッシュがあり、コンソールで手動で行った変更を認識できなかったと思います。