Code Monkey home page Code Monkey logo

dynamodb-continuous-backup's Introduction

DynamoDB Continuous Backup Utility

Amazon DynamoDB is a fast and flexible NoSQL database service for all applications that need consistent, single-digit millisecond latency at any scale. For data durability, Tables are automatically distributed across 3 facilities in an AWS Region of your choice, and ensure continous operation even in the case of AZ level interruption of service.

DynamoDB can be backed up using Amazon Data Pipeline, which creates full point in time copies of DynamoDB tables to AmazonS3. If you want to restore data from a point in time, you simply reimport that data into a new table.

PLEASE NOTE THAT THIS UTILITY IS NOW DEPRECATED IN FAVOR OF DYNAMODB POINT IN TIME RECOVERY

Import Export Backup

For some customers, this full backup and restore model works extremely well. Other customers need the ability to recover data at the item level, with a frequency that is much lower than a full periodic backup and restore. For example, they may want to recover changes made to a single item within just a few minutes.

This module gives you the ability to configure continuous, streaming backup of all data in DynamoDB Tables to Amazon S3 via AWS Lambda Streams to Firehose, which will propagate all changes to a DynamoDB Table to Amazon S3 in as little as 60 seconds. This module completely automates the provisioning process, to ensure that all Tables created in an Account over time are correctly configured for continuous backup. It does this by operating the API calls in your Account. Amazon CloudWatch Events subscribes to DynamoDB::CreateTable and DeleteTable events and then forwards them to an AWS Lambda function that automates the configuration of continuous backup. This includes:

  • Configuring DynamoDB Update Streams for the Table that's just been created
  • Creating an Amazon Kinesis Firehose Delivery Stream for the required destination of the backups on Amazon S3
  • Deploy AWS Lambda Streams to Firehose as a Lambda function in the account
  • Route the Table's NEW_AND_OLD_IMAGES update stream entries to the LambdaStreamToFirehose function

Architecture

By using this module, you can ensure that any Amazon DynamoDB Table that is created, whether as part of an application rollout, or just by a developer as they are doing development, has continuous incremental backups enabled. Once this module deployed, there are no ongoing operations needed to create these backups on S3.

When you delete DynamoDB Tables, this automation also ensures that the Kinesis Firehose Delivery Stream is deleted, but the backup data on Amazon S3 is retained.

How much will it cost?

This solution adds AWS service components to achieve continuous backup of your DynamoDB data. The additional cost will be made up of the following (depending on region prices may vary slightly):

  • Adding an update stream to the DynamoDB table. This costs $.02/100,000 reads after the first 2.5M reads per update stream
  • Adding a Kinesis Firehose Delivery Stream per table. This costs $.035/GB ingested to the delivery stream
  • Backup data storage on S3. This costs the customer ~ $.03/GB
  • CloudWatch Events. This costs $1.0/million events.
  • AWS Lambda invocations to forward DynamoDB Update Stream data to Kinesis Firehose. This costs $.20/million invocations, after the first million.

We believe that these costs are relatively low, but you should assess the cost implications to running this solution in your account, especially on tables with a very large number of write IOPS.

Getting Started

Create the configuration

To get started with this function, simply clone the project, and then create a configuration file. This module uses hjson to make the configuration easy to maintain and read over time, and there's an example file in config.hjson. You may need to work with your AWS Administrator to setup some of the IAM Roles with the correct permissions. You will only need one configuration for all tables in your account, and the following items must be configured:

  • region - the AWS Region where you want the function deployed
  • cloudWatchRoleArn - IAM Role ARN which CloudWatch Events will use to invoke your Lambda function
  • firehoseDeliveryBucket - The S3 bucket where DynamoDB backup data should be stored
  • firehoseDeliveryPrefix - The prefix on S3 where DynamoDB backup data should be stored. The table name will be added automatically to this prefix, as will the date and time of the backup file
  • firehoseDeliveryRoleArn - the ARN of the IAM role that Kinesis Firehose will use to write to S3
  • firehoseDeliverySizeMB - size in MB of dynamo DB backup files to write to S3
  • firehoseDeliveryIntervalSeconds - output interval in seconds for backup files (minimum of 60)
  • lambdaExecRoleArn - IAM Role ARN for which AWS Lambda uses to write to Kinesis Firehose
  • streamsMaxRecordsBatch - Number of update records to stream to the continuous backup function at one time. This number times your DDB record size must be < 128K
  • tableNameMatchRegex - Regular expression that is used to control which tables are provisioned for continuous backup. If omitted or invalid then it will not be used

An appendix with the structure of the required IAM role permissions is at the end of this document.

Installing into your Account

In order to deploy this function into your AWS Account, you must first build the Lambda module with the provided configuration, and then deploy it to your account. The module is configured at account level, and runs for all DynamoDB tables created.

Build the Lambda Function

We now need to build the Lambda function so we can deploy it to your account. This means we need to add the configuration file into the archive that will be run as an AWS Lambda function. To do this, run:

cd src
./build.sh <config file name>

where <config file name> is the file you just created, ideally in the same directory as src. This will install the required modules into the /lib folder if they aren't there, and then create a Zip Archive which is used to deploy the Lambda function.

Deploy to AWS Lambda

Now that the function is built, we need to prepare your account and deploy the Lambda function we've just built. By running:

cd src
deploy.py --config-file <config file name>

We will:

  • Subscribe CloudWatch Events to DynamoDB CreateTable and DeleteTable API Calls
  • Deploy the Lambda function
  • Subscribe the Lambda function to the CloudWatch Events Subscription
  • Enable CloudWatch Events to invoke the Lambda function

Verify

Once deployed, you can verify the correct operation of this function by:

  • Ensuring that there is a CloudWatch Events Rule for dynamodb.amazonaws.com for events CreateTable and DeleteTable
  • This CloudWatch Events Rule has a target of the EnsureDynamoBackup Lambda function
  • Create a simple test DynamoDB table, and observe the CloudWatch Logs output from EnsureDynamoBackup indicating that it has provisioned the continuous backup. For example:
aws dynamodb create-table --region eu-west-1 --attribute-definitions AttributeName=MyHashKey,AttributeType=S --key-schema AttributeName=MyHashKey,KeyType=HASH --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 --table-name MyTestTable

This will result in log output such as:

START RequestId: 0afc60f9-7a6b-11e6-a7ee-c571d294a8c0 Version: $LATEST
Loaded configuration from config.hjson
Enabled Update Stream for MyDynamoTable
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:eu-west-1:<my account number>:table/MyDynamoTable/stream/2016-09-14T11:04:46.890
Created new Firehose Delivery Stream arn:aws:firehose:eu-west-1:<my account number>:deliverystream/MyDynamoTable
Resolved Firehose Delivery Stream ARN: arn:aws:firehose:eu-west-1:<my account number>:deliverystream/MyDynamoTable
Processed 1 Events
END RequestId: 0afc60f9-7a6b-11e6-a7ee-c571d294a8c0
REPORT RequestId: 0afc60f9-7a6b-11e6-a7ee-c571d294a8c0 Duration: 3786.87 ms Billed Duration: 3800 ms Memory Size: 128 MB Max Memory Used: 51 MB

Please note that API Calls => CloudWatch Events => AWS Lambda propagation can take several minutes.

Activating continuous backup for existing tables

Once you have performed the above steps, continuous backup will be configured for all new Tables created in DynamoDB. If you would like to also provision continuous backup for the existing tables in your account, you can use the provision_tables.py script.

First, you need to indicate if you want all tables, or only a subset of tables to be provisioned. You do this with a configuration file:

{
  "provisionAll": (true|false),
  "tableNames": [
    "Table1",
    "Table2",
    "...",
    "TableN"
  ]
}

This file, like others in the module, uses HJson. By setting provisionAll to true, the whitelist will be ignored and all Tables in your account will be configured for continuous backup. However, if you do not include the value, or set false, then the tableNames provided will be used, and only those tables will be configured:

python provision_tables.py my_table_whitelist.hjson

You can use the deprovision_tables.py script in exactly the same way to tear down the continuous backup configuration.

Limits

Please note that default Account limits are for 20 Kinesis Firehose Delivery Streams, and this module will create one Firehose Delivery Stream per Table. If you require more, please file a Limit Increase Request.

Backup Data on S3

Data is backed up automatically via Amazon Kinesis Firehose. The Firehose Delivery Stream that is created as part of provisioning will have the same name as the DynamoDB table you create. The output path of the Firehose Delivery Stream will be the configured bucket and prefix, plus the table name, and then the date in format YYYY/MM/DD/HH. An example backup file for a variety of options would look like:

{"Keys":{"MyHashKey":{"S":"abc"}},"NewImage":{"123":{"S":"asdfasdf"},"MyHashKey":{"S":"abc"}},"OldImage":{"123":{"S":"0921438-09"},"MyHashKey":{"S":"abc"}},"SequenceNumber":"19700000000011945700385","SizeBytes":45,"eventName":"MODIFY"}
{"Keys":{"MyHashKey":{"S":"abc"}},"NewImage":{"123":{"S":"asdfasq223qdf"},"MyHashKey":{"S":"abc"}},"OldImage":{"123":{"S":"asdfasdf"},"MyHashKey":{"S":"abc"}},"SequenceNumber":"19800000000011945703002","SizeBytes":48,"eventName":"MODIFY"}

Every change made to the DynamoDB Item is stored sequentially in Amazon S3, using the Date that the Item was forwarded to Kinesis Firehose from the UpdateStream. You may expect a propagation delay of a few seconds between the DynamoDB Item update/insert/delete time, and the forwarding of the event to Kinesis Firehose. Firehose will then buffer data for the configured firehoseDeliveryIntervalSeconds.

Filtering which tables are backed up

By default, all Tables in your account will be configured for backup. If you want to filter this down to a subset, you can supply a tableNameMatchRegex which will check the name of the Table created in DynamoDB against the supplied regular expression. If it matches then the Table will get backed up. If you supply an invalid regular expression, or have other issues with the supplied configuration then the table will be backed up.

You can also go further by supplying your own code which validates if a Table should be backed up. For instance, you might check a configuration file or database entry, or check other properties such as the number of IOPS. To implement your own function, simply code a new module in dynamo_continuous_backup.py that takes a single String argument (the DynamoDB table name) and returns Boolean. Once done, you can register the function by setting it's name as the implementation function on line 53:

def my_filter_function(dynamo_table_name):
	# custom logic implementation to filter tables in/out of backup
	...
	return (True|False)

optin_function = my_filter_function

Prerequisites for setup & running

In order to use this module, you will need to have installed the following:

  • Python
  • Boto3
  • HJson
  • ShortUUID
  • aws-cli

Installation of Python & Pip is beyond the scope of this document, but once installed, run:

pip install --upgrade boto3 awscli hjson shortuuid

and on some systems you may need to run with sudo, and on Mac may need to add --ignore-installed six.

When running provision/deprovision tables, you will need to provide access credentials which provide at least the following AWS service permissions:

"dynamodb:DescribeStream",
"dynamodb:DescribeTable",
"dynamodb:ListStreams",
"dynamodb:ListTables",
"dynamodb:UpdateTable",
"firehose:CreateDeliveryStream",
"firehose:DescribeDeliveryStream",
"firehose:ListDeliveryStreams",
"firehose:DeleteDeliveryStream",
"lambda:AddPermission",
"lambda:CreateEventSourceMapping",
"lambda:GetEventSourceMapping",
"lambda:GetFunction",
"lambda:GetPolicy",
"lambda:ListAliases",
"lambda:ListEventSourceMappings",
"lambda:ListFunctions",
"lambda:UpdateEventSourceMapping",
"lambda:DeleteEventSourceMapping"

Performing a Restore

Determining which data needs to be restored

The first step in performing a restoration operation is to determine which data must be restored. You can easily review all changes made to a Table Item over time, by running queries via Amazon EMR, using Presto or Hive integration with Amazon S3. First, provision an Amazon EMR Cluster, and ensure that it has Hive and Hue enabled as installed tools. Once up, connect to Hue and open a query editor.

The first thing we'll need is a SerDe that allows us to read the complex, nested JSON structure that our DynamoDB Update Stream forwards to Kinesis Firehose. The OpenX JSON Serde is excellent for this - to load it into your cluster, follow the instructions for building the SerDe, upload the generated JAR to S3, and run:

add jar s3://mybucket/prefix/json-serde-1.3.8-SNAPSHOT-jar-with-dependencies.jar;

We'll now create a Hive Table on top of our backup location, which uses this SerDe to read the JSON and let us query fine grained details. This table will be read-only on our backup data, and you can drop it at any time:

create external table MyTable_<YYYY><MM><DD>_<HH>(
	Keys map<string,map<string,string>>,
	NewImage map<string,map<string,string>>,
	OldImage map<string,map<string,string>>,
	SequenceNumber string,
	SizeBytes bigint,
	eventName string)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
location 's3://backup-bucket/backup-prefix/MyTable/<YYYY>/<MM>/<DD>/<HH>';

Please note that with the above, we'd just be looking at a single hour's worth of backup changes. If you'd prefer to look at a whole day, then you'd just remove the <HH> part of the table creation statement and location.

You can then query changes to your table, down to item level, by using the following HQL:

select  OldImage['attribute1']['s'],
        NewImage['attribute1']['s'],
        SequenceNumber,
        SizeBytes,
        EventName
from MyTable_<YYYY><MM><DD>_<HH>
where Keys['MyHashKey']['s'] = <some hash key value of the item>
order by SequenceNumber desc;

You can add as many different attributes from the item as needed, or use the NewImage['attribute1']['s'] values in a where clause that matches items that indicate the need for restoration.

Restoring a DynamoDB Item

This module does not provide any direct function for performing an update to an Item in DynamoDB, simply because we believe there are many many different ways you might want to do this, as well as a likely need for validation and approval to make a manual change to an application table. The above queries give you the ability to see how values were changed over time, and make an educated decision about what the 'restored' values should be, and it is highly likely that these changes should be introduced via the application itself, rather than bypassing application logic and directly updating the database. However, every customer has different requirements, and so please carefully consider the implications of updating your application DB before making any direct changes.

Appendix 1: IAM Role Permissions

This module requires 3 roles in order to deliver data between CloudTrail, CloudWatch and Amazon Kinesis on your behalf. The following role policies are required, and each minimum set of permissions is shown.

cloudWatchRoleArn

IAM Role ARN which CloudWatch Events uses to invoke your AWS Lambda Function.

Trust Relationship: events.amazonaws.com

Predefined Policy: CloudWatchEventsInvocationAccess

firehoseDeliveryRoleArn

IAM Role ARN that Kinesis Firehose will use to write to S3. This role must have at least permissions to write to Amazon S3, find buckets, and create log events.

Trust Relationship: firehose.amazonaws.com

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "s3:AbortMultipartUpload",
        "s3:GetBucketLocation",
        "s3:GetObject",
        "s3:ListBucket",
        "s3:ListBucketMultipartUploads",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::<my bucket>",
        "arn:aws:s3:::<my bucket>/*"
      ]
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "logs:PutLogEvents"
      ],
      "Resource": [
        "arn:aws:logs:eu-west-1:<my account>:log-group:/aws/kinesisfirehose/*:log-stream:*"
      ]
    }
  ]
}

lambdaExecRoleArn

IAM Role ARN for which AWS Lambda uses to write to Kinesis Firehose. This role must have rights to use PutRecords on Kinesis Firehose.

Trust Relationship: lambda.amazonaws.com

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1444729748000",
            "Effect": "Allow",
            "Action": [
                "firehose:CreateDeliveryStream",
                "firehose:DescribeDeliveryStream",
                "firehose:ListDeliveryStreams",
                "firehose:PutRecord",
                "firehose:PutRecordBatch",
                "dynamodb:DescribeStream",
                "dynamodb:DescribeTable",
                "dynamodb:GetRecords",
                "dynamodb:GetShardIterator",
                "dynamodb:ListStreams",
                "dynamodb:ListTables",
                "dynamodb:UpdateTable",
                "logs:CreateLogGroup",
	            "logs:CreateLogStream",
	            "logs:PutLogEvents",
	            "lambda:CreateFunction",
                "lambda:CreateEventSourceMapping",
	            "lambda:ListEventSourceMappings",
	            "iam:passrole",
                "s3:Get*",
                "s3:List*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

License

Licensed under the Apache License, 2.0.

dynamodb-continuous-backup's People

Contributors

austin43 avatar grayaii avatar hyandell avatar ianmeyers avatar jasondavis25 avatar rjuliano avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dynamodb-continuous-backup's Issues

No DynamoDB Update Stream Triggers found routing to LambdaStreamToFirehose

Provisioned tables using provision_tables.py are not de-provisioned using deprovision_tables.py

11/07 12:03 > ./deprovision_tables.py provisioning_whitelist.hjson
Building Table List for Processing from provisioning_whitelist.hjson
Loaded configuration from config.hjson
Removed Event Source Mapping for DynamoDB Update Stream arn:aws:dynamodb:us-west-2:$ACCOUNT:table/bobStackLocal-DynamoDBLocalCMV1-1TBKHYKVQ0YS8-configurationSpec-YUVCHLSWS637/stream/2016-11-03T16:00:07.347
No DynamoDB Update Stream Triggers found routing to LambdaStreamToFirehose for bobStackLocal-DynamoDBLocalCMV1-1TBKHYKVQ0YS8-configurationSpec-YUVCHLSWS637 - OK

Also : This does not remove the firehose entries.

lambdaExecRoleArn missing permissions.

I ran into a couple permissions issues while using the iam roles in the readme, my latest version for the lambda function needed the following added:

            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents",
            "lambda:CreateFunction",
            "iam:passrole"

Support for CLI Profiles on Deploy.py

We currently leverage a multi-account structure, and I'd like to deploy this to an account in which I need to use a CLI profile to access via command line. As far as I can tell there's currently no support as part of the deploy.py to specify a CLI profile to utilize.

No data in s3

I am not seeing any data in s3, but I don't see any errors anywhere.

This is how I build/deploy and create a dummy table:

cd src

./build.sh alex_02.hjson

python deploy.py --redeploy --config-file alex_02.hjson

aws dynamodb create-table --region us-west-2 --attribute-definitions \
  AttributeName=MyHashKey,AttributeType=S --key-schema \
  AttributeName=MyHashKey,KeyType=HASH --provisioned-throughput \
  ReadCapacityUnits=1,WriteCapacityUnits=1 --table-name alex02_foobar6

The lambda function gets fired and the output looks correct:
screen shot 2017-04-11 at 3 21 17 pm

I then manually created some items via the AWS Consul:
screen shot 2017-04-11 at 3 24 23 pm

But the S3 bucket is empty.

The stream for my table looks like there is some data that is going through:
screen shot 2017-04-11 at 3 25 30 pm

Would could be the issue?
Or better yet, how can I debug this?

Missing iam permission

Found two more permissions for the lambda exec role:

            "lambda:CreateEventSourceMapping",
            "lambda:ListEventSourceMappings",

Unable to import module 'index': No module named index

I am trying this out for the first time. Here is what I did (after setting up all the IAM roles):

src/build.sh src/alex_02.hjson
python src/deploy.py --config-file src/alex_02.hjson --redeploy

I then go and create a table like so:

aws dynamodb create-table --region us-west-2 \
  --attribute-definitions AttributeName=MyHashKey,AttributeType=S \
  --key-schema AttributeName=MyHashKey,KeyType=HASH \
  --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 \
  --table-name alex02_foobar5

After first the error was "bucket does not exist", so I created the bucket.
Now that I manually created the bucket, I get this error:

Unable to import module 'index': No module named index

Any idea what could the problem?
Maybe it's the way I'm building it?
Does it matter which directory I build it from?

Deploy script ResourceNotFoundException when setting DynamoDBCreateDelete target

When running the deploy.py script, I get the following error:

$ ./deploy.py --config-file config.hjson
Created new CloudWatch Events Rule arn:aws:events:eu-west-1:xxxxxxxxxxxx:rule/DynamoDBCreateDelete
Using existing DynamoDB Ensure Backup Module at arn:aws:lambda:eu-west-1:xxxxxxxxxxxx:function:EnsureDynamoBackup
Traceback (most recent call last):
File "./deploy.py", line 187, in
configure_backup(config['region'], config['cloudWatchRoleArn'], config['lambdaExecRoleArn'], args.redeploy)
File "./deploy.py", line 167, in configure_backup
lambda_arn = deploy_lambda_function(region, lambda_role_arn, cwe_rule_arn, redeploy_lambda)
File "./deploy.py", line 111, in deploy_lambda_function
response_doc = json.loads(lambda_client.get_policy(FunctionName=LAMBDA_FUNCTION_NAME)['Policy'])
File "/usr/local/lib/python2.7/site-packages/botocore/client.py", line 251, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/usr/local/lib/python2.7/site-packages/botocore/client.py", line 537, in _make_api_call
raise ClientError(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (ResourceNotFoundException) when calling the GetPolicy operation: The resource you requested does not exist.

Current solution is to go into AWS console and manually set the Target to EnsureDynamoBackup for the DynamoDBCreateDelete rule.

version 1.3

In deploy.py, I believe line 17 should be
version = '1.3'

after the 1.3 update.

Firehose LambdaStreamsDefaultDeliveryStream not found under account

2016-11-03T16:05:24.322Z 81820a90-cb82-4566-90db-35866393c78b
{
"message": "Firehose LambdaStreamsDefaultDeliveryStream not found under account.",
"code": "ResourceNotFoundException",
"time": "2016-11-03T16:05:24.322Z",
"requestId": "54279dc9-a1df-11e6-a64e-d184623b1b33",
"statusCode": 400,
"retryable": false,
"retryDelay": 65.43006924912333
}

11/03 09:15 > grep -r LambdaStreamsDefaultDeliveryStream *
createDefaultDeliveryStream.sh:deliveryStreamName="LambdaStreamsDefaultDeliveryStream"
index.js: 'DEFAULT' : 'LambdaStreamsDefaultDeliveryStream'

I realize this is probably https://github.com/awslabs/lambda-streams-to-firehose codebase.

Naming/versioning issue during deployment

The build.sh file creates a version of dynamodb_continuous_backup.zip with a version number at the end. deploy_lambda_function is looking for one without (../dist/dynamodb_continuous_backup.zip).

us-west-1 errors - kinesis firehose not available?

I'm not sure whether this is a fundamental incompatibility or something that can be worked around, but:

I have a set of DynamoDB tables in us-west-1 region;

I've followed the instructions in the README.md, and they're straightforward enough;

However, when I attempt to provision backups for my tables, I receive the following error:

root@#:/dynamodb-continuous-backup/src# python provision_tables.py provisioning_whitelist.hjson 
Building Table List for Processing from provisioning_whitelist.hjson
Using compiled configuration config.hjson
Loaded configuration from config.hjson
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-1:xxxxxxx:table/TestBackups/stream/2017-09-01T16:36:28.852
Exception while provisioning table TestBackups
Could not connect to the endpoint URL: "https://firehose.us-west-1.amazonaws.com/"
Proceeding...
Enabled Update Stream for SecondTable
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-1:xxxxx:table/SecondTable/stream/2017-09-01T16:52:20.160
Exception while provisioning table SecondTable
Could not connect to the endpoint URL: "https://firehose.us-west-1.amazonaws.com/"
Proceeding...
Enabled Update Stream for ThirdTable
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-1:xxxxx:table/ThirdTable/stream/2017-09-01T16:52:48.014
Exception while provisioning table ThirdTable
Could not connect to the endpoint URL: "https://firehose.us-west-1.amazonaws.com/"
Proceeding...

Initially I'd configured my region as us-west-1, and although deployment appeared to be successful, testing showed nothing being backed up and invocation errors (with similar messages being logged to Cloudwatch).

Removing the Cloudwatch events and Lambda function, running the deprovisioning script, then setting the region to us-west-2 and re-deploying the Lambda function is at least throwing errors for me now.

My question: Is it possible to back up DynamoDB tables in us-west-1 region using dynamodb-continuous-backup, even if Kinesis Firehose is unavailable there?

Need help with initial IAM role permissions - cloudTrailRoleArn

I am trying to deploy this in us-east-1 region and receiving the follow error when I run ./deploy.py --config-file config.hjson after creating the 3 roles. For the cloudTrailRoleArn, I updated the AWS account ID and swapped eu-west-1 to us-east-1 and added as inline IAM policy. Do I need any other IAM trust relationships?

An error occurred (InvalidCloudWatchLogsRoleArnException) when calling the UpdateTrail operation: Access denied. Check the trust relationships for your role.

Perhaps a bit clearer setup docs here on the IAM roles?

Unable to match the tag value , while it does exist in a Dynamo DB

HI team

First of this is my first post, so excuse me if I have post it on a wrong forum or things like that :-)

I have dynamo DB created and I have tagged it
In my python script, I can see that I can retrive that value
But when i am taking it through a loop its failing to match in my lambda fucntion

When i tried that piece of code in mylaptop its working perfectly

code :

def table_regex_optin(dynamo_table_name):
client = boto3.client('dynamodb')
response = client.list_tables()
try :
response = client.list_tags_of_resource(
ResourceArn='arn:aws:dynamodb:ap-southeast-2:${AWS::AccountId}:table/'+dynamo_table_name
)
print('getting the tags:',response['Tags'])

    for tag in response['Tags']:
        if tag['Key'].lower() == 'backup-needed' and tag['Value'].lower() == 'true':
            return True
except:
    print('i am failing to match the tag')
    return False 

The output of the below statement ๐Ÿ‘
print('getting the tags:',response['Tags'])
prints all the tag i have included the 'backup-needed' , but its not matching in the next line

IAM role permissions issues?

When I run this:

user@ip-168-0-1-100$python provision_tables.py provisioning_whitelist.hjson
Building Table List for Processing from provisioning_whitelist.hjson
Using compiled configuration config.hjson
Loaded configuration from config.hjson
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-2:xxx:table/Questionnaire/stream/2017-09-12T22:15:29.068
Resolved Firehose Delivery Stream ARN: arn:aws:firehose:us-west-2:xxx:deliverystream/Questionnaire
Exception while provisioning table Questionnaire
An error occurred (InvalidParameterValueException) when calling the CreateEventSourceMapping operation: Cannot access stream arn:aws:dynamodb:us-west-2:xxx:table/Questionnaire/stream/2017-09-12T22:15:29.068. Please ensure the role can perform the GetRecords, GetShardIterator, DescribeStream, and ListStreams Actions on your stream in IAM.
Proceeding...

The block starting with Resolved Firehose to proceeding... seems to repeat for all tables in my collection.

From what I can tell the cloudWatchRoleArn, firehoseDeliveryRoleArn, and lambdaExecRoleArn have the correct permissions. They look similar to the permissions policies shown in the appendix. Is there an additional configuration step that I've missed? Perhaps something specific to the firehose setup??

Does not work

Just following the doc, and it does seem to work out of the box. First had to create the roles, and managed to get all the way to creating the dynamodb tables.
After the table creation, I see cloudwatch error on lambda execution, but the lambda log group is not created so it is hard to tell why the lambda execution failed. So manually tested the lambda function, and it fails with

"errorMessage": "Unable to import module 'index'"

At this point, I am giving up on trying more alternatives. Will come back to this later to figure out whats going on, but definitely need more instructions in the doc to make this work.

Cloud formation template

Hi
Is there a cloudformation template to build this stack?
How about just the backup piece for now?
If not please let me know, I am working on creating one.

EnsureDynamoBackup is not authorized to perform: lambda:DeleteEventSourceMapping

While I am doing "delete_table" to dynamodb, the cloudwatch log says:

ClientError: An error occurred (AccessDeniedException) when calling the DeleteEventSourceMapping operation: User: arn:aws:sts::<account>:assumed-role/LambdaExecRole/EnsureDynamoBackup is not authorized to perform: lambda:DeleteEventSourceMapping on resource: arn:aws:lambda:us-west-2:<account>:event-source-mapping

I tried adding "lambda:DeleteEventSourceMapping" to the LambdaExecRole IAM role. but still get the same error.

Setting up a second table causes an error in the lambda function

An error occurred (ResourceConflictException) when calling the CreateFunction operation: Function already exist: LambdaStreamToFirehose: ClientError
Traceback (most recent call last):
File "/var/task/index.py", line 28, in event_handler
backup.configure_table(dynamo_table_name)
File "/var/task/dynamo_continuous_backup.py", line 354, in configure_table
ensure_update_stream_event_source(dynamo_stream_arn)
File "/var/task/dynamo_continuous_backup.py", line 229, in ensure_update_stream_event_source
function_arn = ensure_lambda_streams_to_firehose()
File "/var/task/dynamo_continuous_backup.py", line 285, in ensure_lambda_streams_to_firehose
Publish=True
File "/var/runtime/botocore/client.py", line 159, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/var/runtime/botocore/client.py", line 494, in _make_api_call
raise ClientError(parsed_response, operation_name)
ClientError: An error occurred (ResourceConflictException) when calling the CreateFunction operation: Function already exist: LambdaStreamToFirehose

Missing permissions for S3 bucket in us-west-2

Running into an issue accessing the LambdaStreamToFirehose file in us-west-2, think maybe the bucket policy isn't open:

error occurred (AccessDeniedException) when calling the CreateFunction operation: Your access has been denied by S3, please make sure your request credentials have permission to GetObject for aws-lambda-streams-to-firehose-us-west-2/LambdaStreamToFirehose-1.4.1.zip. S3 Error Code: AccessDenied. S3 Error Message: Access Denied:

provision_tables.py provisions all defined dynamo tables, ignores whitelist

provision_tables.py seems to ignore the whitelist and provisions all tables found.

whitelist file > https://gist.github.com/BMR59920/b5f9a4b7ce8d346fd0b59c4159905e64

11/02 12:23 > python provision_tables.py provisioning_whitelist_LOCAL.hjson
Building Table List for Processing from provisioning_whitelist_LOCAL.hjson
Loaded configuration from config.hjson
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-2:102671227235:table/bobKclEsPoc/stream/2016-11-01T16:23:49.656
Created new Firehose Delivery Stream arn:aws:firehose:us-west-2:102671227235:deliverystream/bobKclEsPoc
Resolved Firehose Delivery Stream ARN: arn:aws:firehose:us-west-2:102671227235:deliverystream/bobKclEsPoc
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-2:102671227235:table/abcZZZtestTable/stream/2016-11-02T17:43:34.570
Resolved Firehose Delivery Stream ARN: arn:aws:firehose:us-west-2:102671227235:deliverystream/abcZZZtestTable
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-2:102671227235:table/kms-dmk-poc-DomainKeyStore-6HZKCFESK4DF/stream/2016-09-30T22:02:51.942
Created new Firehose Delivery Stream arn:aws:firehose:us-west-2:102671227235:deliverystream/kms-dmk-poc-DomainKeyStore-6HZKCFESK4DF
Resolved Firehose Delivery Stream ARN: arn:aws:firehose:us-west-2:102671227235:deliverystream/kms-dmk-poc-DomainKeyStore-6HZKCFESK4DF
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-2:102671227235:table/makeUpAUniqueName/stream/2016-11-01T16:23:53.497
Created new Firehose Delivery Stream arn:aws:firehose:us-west-2:102671227235:deliverystream/makeUpAUniqueName
Resolved Firehose Delivery Stream ARN: arn:aws:firehose:us-west-2:102671227235:deliverystream/makeUpAUniqueName
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-2:102671227235:table/bobStackDev-DynamoDBDevCMV1-167S2NF9HGV14-configurationSpec-115NOKVJHVP3H/stream/2016-11-01T16:23:56.785
Created new Firehose Delivery Stream arn:aws:firehose:us-west-2:102671227235:deliverystream/bobStackDev-DynamoDBDevCMV1-167S2NF9HGV14-configurationSpec-115N
Resolved Firehose Delivery Stream ARN: arn:aws:firehose:us-west-2:102671227235:deliverystream/bobStackDev-DynamoDBDevCMV1-167S2NF9HGV14-configurationSpec-115N
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-2:102671227235:table/bobStackDev-DynamoDBDevCMV1-167S2NF9HGV14-coreCollection-1APN6270TEKY8/stream/2016-08-17T19:42:44.331
Created new Firehose Delivery Stream arn:aws:firehose:us-west-2:102671227235:deliverystream/bobStackDev-DynamoDBDevCMV1-167S2NF9HGV14-coreCollection-1APN627
Resolved Firehose Delivery Stream ARN: arn:aws:firehose:us-west-2:102671227235:deliverystream/bobStackDev-DynamoDBDevCMV1-167S2NF9HGV14-coreCollection-1APN627
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-2:102671227235:table/bobStackDev-DynamoDBDevCMV1-167S2NF9HGV14-dataUnit-1SSKUOB3E1UWB/stream/2016-08-17T19:43:51.038

AccessDeniedException when calling the CreateFunction : denied by S3

CloudWatch reports the following after deploy and table create. This is in the us-west-2 region.
I think this is for the source bucket that houses LambdaStreamToFirehose-1.3.5.zip

An error occurred (AccessDeniedException) when calling the CreateFunction operation: Your access has been denied by S3, please make sure your request credentials have permission to GetObject for aws-lambda-streams-to-firehose-us-west-2/LambdaStreamToFirehose-1.3.5.zip. S3 Error Code: AccessDenied. S3 Error Message: Access Denied: ClientError
Traceback (most recent call last):
File "/var/task/index.py", line 28, in event_handler
backup.configure_table(dynamo_table_name)
File "/var/task/dynamo_continuous_backup.py", line 320, in configure_table
ensure_update_stream_event_source(dynamo_stream_arn)
File "/var/task/dynamo_continuous_backup.py", line 197, in ensure_update_stream_event_source
function_arn = ensure_lambda_streams_to_firehose()
File "/var/task/dynamo_continuous_backup.py", line 253, in ensure_lambda_streams_to_firehose
Publish=True
File "/var/runtime/botocore/client.py", line 159, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/var/runtime/botocore/client.py", line 494, in _make_api_call
raise ClientError(parsed_response, operation_name)
ClientError: An error occurred (AccessDeniedException) when calling the CreateFunction operation: Your access has been denied by S3, please make sure your request credentials have permission to GetObject for aws-lambda-streams-to-firehose-us-west-2/LambdaStreamToFirehose-1.3.5.zip. S3 Error Code: AccessDenied. S3 Error Message: Access Denied

Table names longer than 64 characters cause ValidationException

11/01 09:40 > python provision_tables.py provisioning_whitelist_LOCAL.hjson
Building Table List for Processing from provisioning_whitelist_LOCAL.hjson
Loaded configuration from config.hjson
current_region: us-west-2
...
Resolved DynamoDB Stream ARN: arn:aws:dynamodb:us-west-2:102671227235:table/bobStackDev-DynamoDBDevCMV1-167S2NF9HGV14-configurationSpec-115NOKVJHVP3H/stream/2016-11-01T16:23:56.785
Exception while provisioning table bobStackDev-DynamoDBDevCMV1-167S2NF9HGV14-configurationSpec-115NOKVJHVP3H
An error occurred (ValidationException) when calling the CreateDeliveryStream operation: 1 validation error detected: Value 'pdhStackDev-DynamoDBDevCMV1-167S2NF9HGV14-configurationSpec-115NOKVJHVP3H' at 'deliveryStreamName' failed to satisfy constraint: Member must have length less than or equal to 64
Proceeding...

I realize that this is a limitation of the DeliveryStreamName in Kinesis Firehose.

What's the best approach to start using this backup method?

Hey,

just a quick question for people who started to use the continuous backup with already created tables. I understand that this backup solution is creating backup files in s3 after an event happened in the database so it means that the majority of data will not be backed up.

did you use Import/Export method to backup everything prior to the installation? and now restore would mean to first import everything from the 1st full backup and then reimport everything from the continuous backup?

firehose delivery stream not created

Hi Ian,

I have followed the steps and everything worked fine until deploying Lambda function. But when I create a table, firehose delivery stream is not created and I do not see any log output for EnsureDynamoBackup. "There was an error loading Log streams". I have double checked every step and everything seems fine. Any idea what could have gone wrong with the firehose stream?

Thanks,
Anudeep

Lambda streams to to firehose bucket not availlable in all regions

Hi,

I'm deploying this in eu-west-1 and succeeded pretty far, altough when running provision_tables.py I receive the following error message

An error occurred (InvalidParameterValueException) when calling the CreateFunction operation: Error occurred while GetObject. S3 Error Code: PermanentRedirect. S3 Error Message: The bucket is in this region: null. Please use this region to retry the request

According to boto3 docs at http://boto3.readthedocs.io/en/latest/reference/services/lambda.html#Lambda.Client.create_function regarding the create_function call it says:

This bucket must reside in the same AWS region where you are creating the Lambda function.

This seems to be the reason for the error above.
So is there an easy way to get this setup deployed in eu-west-1 without creating an own s3 bucket and changing the code to point to the new location?

Restoring data

It's not clear from the documentation how to actually perform a restore. I'm assuming there's a way to do it via Data Pipeline and EMR but can you clarify a bit more? Looks like the current instructions only show how to identify the records needed to be restored but what if I wanted to completely restore the table?

S3 error

Whether I am running provision_tables or creating new tables, I keep getting the following error. Perhaps I have configured something incorrectly, but I believe I properly followed the docs and created the IAM roles in the README.

Resolved Firehose Delivery Stream ARN: arn:aws:firehose:us-east-1::deliverystream/
Deploying LambdaStreamToFirehose/LambdaStreamToFirehose-1.4.5.zip from s3://awslabs-code-us-std
Exception while provisioning table
An error occurred (InvalidParameterValueException) when calling the CreateFunction operation: Error occurred while GetObject. S3 Error Code: NoSuchBucket. S3 Error Message: The specified bucket does not exist

I have created the "firehoseDeliveryBucket" and the "firehoseDeliveryPrefix" from the config.hjson file. I have also granted access to that bucket to the "firehoseDeliveryRoleArn".

Is there somewhere else I can look?

Am I supposed to deploy LambdaStreamToFirehose-1.4.5.zip to awslabs-code-us-std S3 bucket?

Thank you.

setup_existing_tables.py::resolve_table_list() does not return all tables

I have an account where running the provision_tables.py script (which uses setup_existing_tables.py) only provisions 6 of the 10 DynamoDB tables on the account. Possibly an issue with the paging in the dynamo_client.list_tables() function as removing the ExclusiveStartTableName parameter resolves this issue for this account.

Discussion - Why is Firehose necessary?

From what I understand, Firehose acts as a huge buffer that can transform data before uploading to a destination.

Why do we even need Firehose? DDB delivery streams can invoke Lambda. Can't Lambda do all the heavy lifting?

What's the downside of eliminating Firehose from the picture?

Please use GIT tags to match the tags in the script(s)

As a user of this project, I want to have control over the version my deployment script provisions this project.

Right now, I have to do it via commit IDs, which is not user friendly.

I would appreciate if the GIT tags would match the version mentioned in the build.sh or similar.

nodejs is no longer supported for creating or updating AWS Lambda functions

While I tried to deploy the function I got

An error occurred (InvalidParameterValueException) when calling the CreateFunction operation: The runtime parameter of nodejs is no longer supported for creating or updating AWS Lambda functions. We recommend you use the new runtime (nodejs4.3) while creating or updating functions.

error. Any plans for update? Is the nodejs code compatible with nodejs4.3 and it's sufficient to update https://github.com/awslabs/dynamodb-continuous-backup/blob/master/src/dynamo_continuous_backup.py#L275?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.