web-dev-qa-db-ja.com

CloudFormationを使用してGSIをDynamoDBテーブルに追加できません

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定義で既存の属性を使用しても、機能せず、同じエラーメッセージで失敗します。

13
JaredHatfield

今日も同じエラーが発生し、Amazonテクニカルサポートから回答を得ました。問題は、TableNameフィールドを指定したことです。 CloudFormationは、テーブルの命名を担当したいと考えています。どうやら、あなたがそれらにあなた自身の名前を与えるとき、これはあなたがテーブルを置き換えるアップデートであなたが得るエラーです(なぜそれが置き換える必要があるのか​​分かりませんが、それはドキュメントが言っていることです)

私にとって、これによりCloudFormationはDynamoDBテーブルを維持するのにまったく役に立たなくなります。 CloudFormationが生成したランダムテーブル名をコードが動的に認識できるように、構成を組み込む必要があります。

6
Todd Feak

AWSサポートの私への対応FWIW:

回避策A

  1. テーブルからs3にデータをエクスポートします
  2. Gsiが追加された新しいテーブル名(tablename2)でスタックを更新します
    • これにより現在のすべてのエントリが失われることに注意してください。最初に必ずs3にバックアップしてください。
  3. スタックを再度更新し、dynamodbテーブルでtablename1を使用するように戻します
  4. S3からデータをインポートするこれは、データパイプラインを使用することで簡単にできます。[.____]を参照してください。

利点は、アプリコードが固定名を使い続けることができることです。ただし、スタックを2回更新し、データをエクスポート/インポートするには、カスタムスクリプトで自動化するための作業が必要になります。

回避策B

  1. バックアップデータ
  2. CloudFormationにテーブルの名前を付けましょう
  3. AWS SDKを使用して、論理IDでスタックリソースを記述して名前を取得し、出力からテーブル名をフェッチして、テーブル名を取得します。

これにより、余分なスタックの更新が回避されると思いますが(データのエクスポート/インポートが必要になると思います)、欠点は、テーブル名をフェッチするためのコード内のネットワーク呼び出しです。 * http://docs.aws.Amazon.com/AWSJavaScriptSDK/latest/AWS/CloudFormation.html#describeStackResource-property を参照してください

繰り返しになりますが、これは、サポートがサービスチームを推進している既知の問題です。これは、非常に一般的な使用例であり、問​​題点であることがわかっているためです。本番環境でテストする前に、テスト環境で回避策を試してください。

5
Thien

私のシナリオは、範囲キーを変更してGSIを更新したいというものでした。 -まず、更新するGSIを削除する必要があります。また、GSIの削除により不要になった可能性のあるAttributeDefinition、つまりインデックス名なども削除することを忘れないでください。CloudFormationを介してテンプレートをアップロードし、変更を適用します。 -次に、必要な属性と「更新された」GSIをテンプレートに追加します。

2
Momshad Alvee

DynamoDBからすべてのデータをバックアップし、その後、サーバーレスを使用している場合は、以下のコマンドのいずれかを実行します。

個別削除:

node ./node_modules/serverless/bin/serverless remove

グローバルに削除:

serverless remove

次のコマンドを実行して、再度デプロイします。

node ./node_modules/serverless/bin/serverless deploy -v

または

serverless deploy
2
Shaw Donayre

ここで問題はどのように発生しましたか?私の場合、dynamoDBコンソールでGSIを手動で削除してから、cloudformationでGSIを追加すると、update-stackでこのエラーが発生します。

解決策:cloudformationでGSIを削除し、update-stackを実行してから、GSIを追加し直し、update-stackを再度実行すると、正常に機能します。

Cloudformationには独自のキャッシュがあり、コンソールで手動で行った変更を認識できなかったと思います。

1
richard_sun