将不同账户中的 Amazon Redshift 集群中的数据卸载到 Amazon S3 - AWS 规范指引

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

将不同账户中的 Amazon Redshift 集群中的数据卸载到 Amazon S3

Andrew Kamel,Amazon Web Services

Summary

当测试应用程序时,在测试环境中使用生产数据会很有帮助。使用生产数据,您可以更准确地评估正在开发的应用程序。

此模式将从生产环境中的 Amazon Redshift 集群中提取数据,并将这些数据传输到 Amazon Web Services(AWS)上的开发环境中的 Amazon Simple Storage Service(Amazon S3)存储桶中。

此模式将逐步完成 DEV 和 PROD 账户的设置,包括:

  • 所需的资源

  • AWS Identity and Access Management (IAM) 角色

  • 调整与子网、安全组和虚拟私有云(VPC)之间的网络连接,以便支持 Amazon Redshift 连接

  • 一个带有 Python 运行时的示例 AWS Lambda 函数,用于测试架构

要授予对 Amazon Redshift 集群的访问权限,该模式 AWS Secrets Manager 用于存储相关证书。好处是拥有直接连接到 Amazon Redshift 集群所需的全部信息,而无需知道 Amazon Redshift 集群位于何处。此外,您还可以监控密钥的使用情况

保存在 Secrets Manager 中的密钥包括 Amazon Redshift 集群的主机、数据库名称、端口和相关的凭证。

有关使用此模式时的安全注意事项的信息,请参阅最佳实践部分。

先决条件和限制

先决条件

限制

  • 根据您要查询的数据量,Lambda 函数可能会超时。

    如果您的运行时间超过了 Lambda 的最大超时时间(15 分钟),请对您的 Lambda 代码采用一种异步方法。此模式的代码示例使用适用于 Python 的 psycopg2 库,此库目前不支持异步处理。

  • 有些 AWS 服务 并非全部可用 AWS 区域。有关区域可用性,请参阅按区域划分的AWS 服务。有关特定端点,请参阅服务端点和配额页面,然后选择相应服务的链接。

架构

下图显示了包含 DEV 账户和 PROD 账户的目标架构。

DEV 账户中的 Lambda VPC 和 PROD 账户中的 Amazon Redshift VPC。

下图显示了如下工作流:

  1. DEV 账户中的 Lambda 函数担任 IAM 角色,访问 PROD 账户中的 Secrets Manager 中的 Amazon Redshift 凭证时,需要使用此角色。

    随后,Lambda 函数将检索 Amazon Redshift 集群密钥。

  2. 开发者账户中的 Lambda 函数使用这些信息通过对等连接到 PROD 账户中的 Amazon Redshift 集群。 VPCs

    接下来,Lambda 函数发送一个卸载命令,以便查询 PROD 账户中的 Amazon Redshift 集群。

  3. PROD 账户中的 Amazon Redshift 集群担任相关的 IAM 角色,以便访问 DEV 账户中的 S3 存储桶。

    Amazon Redshift 集群将查询的数据卸载到 DEV 账户中的 S3 存储桶。

查询来自 Amazon Redshift 的数据

下图显示了用于检索 Amazon Redshift 凭证和连接到 Amazon Redshift 集群的角色。此工作流由 Lambda 函数启动。

用于在不同的账户中担任角色的三步流程。

下图显示了如下工作流:

  1. DEV 账户中的 CrossAccount-SM-Read-Role 在 PROD 账户中担任 SM-Read-Role

  2. SM-Read-Role 角色使用附加的策略,从 Secrets Manager 中检索密钥。

  3. 这些凭证用于访问 Amazon Redshift 集群。

将数据上传到 Amazon S3

下图显示了用于提取数据并将其上传到 Amazon S3 的跨账户读写过程。此工作流由 Lambda 函数启动。此模式将 Amazon Redshift 中的 IAM 角色串联在一起。来自 Amazon Redshift 集群的卸载命令担任 CrossAccount-S3-Write-Role,然后担任 S3-Write-Role。这一角色串联能够授权 Amazon Redshift 访问 Amazon S3。

获取凭证、访问 Amazon Redshift 并将数据上传到 Amazon S3 的那些角色。

此工作流包含以下步骤:

  1. DEV 账户中的 CrossAccount-SM-Read-Role 在 PROD 账户中担任 SM-Read-Role

  2. SM-Read-Role 从 Secrets Manager 中检索 Amazon Redshift 凭证。

  3. Lambda 函数连接到 Amazon Redshift 集群,并发送一个查询。

  4. Amazon Redshift 集群担任 CrossAccount-S3-Write-Role

  5. 在 DEV 账户中,CrossAccount-S3-Write-Role 担任 S3-Write-Role

  6. 查询结果将卸载到 DEV 账户中的 S3 存储桶。

工具

AWS 服务

  • AWS Key Management Service (AWS KMS) 帮助您创建和控制加密密钥以帮助保护您的数据。

  • AWS Lambda 是一项计算服务,可帮助您运行代码,无需预调配或管理服务器。它只在需要时运行您的代码,并自动进行扩展,因此您只需为使用的计算时间付费。

  • Amazon Redshift 是一项在 Amazon Web Services Cloud 中托管的 PB 级数据仓库服务。

  • AWS Secrets Manager 可帮助您将代码中的硬编码凭证(包括密码)替换为对 Secrets Manager 进行的 API 调用,以便以编程方式检索此密钥。

  • Amazon Simple Storage Service(Amazon S3)是一项基于云的对象存储服务,可帮助您存储、保护和检索任意数量的数据。

代码存储库

此模式的代码可在 GitHub unload-redshift-to-s3-python 存储库中找到。

最佳实践

安全免责声明

在实施该解决方案之前,请考虑下面这些重要的安全建议:

  • 请记住,连接开发账户和生产账户可能会导致范围扩大、整体安全状况变差。我们建议只临时部署该解决方案、提取所需的数据部分,然后立即销毁已部署的资源。要销毁资源,您应删除 Lambda 函数、移除为该解决方案创建的任何 IAM 角色和策略,并撤消在多个账户之间授予的任何网络访问权限。

  • 在将任何数据从生产环境复制到开发环境之前,请咨询您的安全和合规团队。通常不应以这种方式复制个人身份信息(PII)、受保护的健康信息(PHI)以及其他机密数据或受监管的数据。只复制公开提供的非机密信息(例如商店前端的公开库存数据)。考虑对数据进行令牌化或匿名化处理,或者生成合成测试数据,而不是尽可能使用生产数据。AWS 安全原则之一是限制对数据的访问。换句话说,开发人员不应在生产账户中执行操作。

  • 限制访问开发账户中的 Lambda 函数,因为此函数会从生产环境中的 Amazon Redshift 集群读取数据。

  • 为了避免生产环境中断,请实施以下建议:

    • 使用单独的专用开发账户来执行测试和开发活动。

    • 实施严格的网络访问控制,并将账户之间的流量限制在仅仅必要的水平。

    • 监控和审核对生产环境和数据来源的访问。

    • 对于所有的相关资源和服务,实施最低权限访问控制。

    • 定期审查和轮换证书,例如 AWS Secrets Manager 密钥和 IAM 角色访问密钥。

  • 对于本文中使用的服务,请参阅如下安全文档:

访问生产数据和资源时,安全性是重中之重。始终遵循最佳实践、实施最低权限访问控制,并定期审查和更新您的安全措施。

操作说明

Task说明所需技能

为 Amazon Redshift 集群创建一个密钥。

要为 Amazon Redshift 集群创建密钥,请执行以下操作:

  1. 在 PROD 账户中,登录并打开 Secrets Manager 控制台 AWS 管理控制台,网址为 https://console.aws.amazon.com/secretsmanager/。

  2. 选择存储新的密钥

  3. 选择 Amazon Redshift 数据仓库的凭证

  4. 对于用户名密码,输入您的实例的值,然后确认,或者为加密密钥选择一个值。

  5. 选择您的密钥要访问的 Amazon Redshift 数据仓库。

  6. 为密钥名称输入 Redshift-Creds-Secret

  7. 使用默认选项完成剩余的创建步骤,然后选择存储

  8. 查看您的密钥,并记下您为识别密钥而生成的密钥 ARN 值。

DevOps 工程师

创建一个用于访问 Secrets Manager 的角色。

要创建此角色,请执行以下操作:

  1. 在 PROD 账户中,打开 IAM 控制台,网址为 https://console.aws.amazon.com/iam/。

  2. 选择策略

  3. 选择创建策略

  4. 选择 JSON 选项卡,然后输入一个 IAM 策略,例如:

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:GetResourcePolicy", "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecretVersionIds" ], "Resource": [ "<Redshift-Creds-Secret-ARN>" ] }, { "Effect": "Allow", "Action": "secretsmanager:ListSecrets", "Resource": "*" } ] }

    Redshift-Creds-Secret-ARN 替换为 Secrets Manager 密钥的 Amazon 资源名称(ARN),此密钥中包含 Amazon Redshift 集群的信息和凭证。

DevOps 工程师
Task说明所需技能

创建用于访问 S3 存储桶的角色

要创建用于访问 S3 存储桶的角色,请执行以下操作:

  1. 在 DEV 账户中,打开 IAM 控制台。

  2.  选择策略

  3. 选择创建策略

  4.  选择 JSON 选项卡,然后输入一个 IAM 策略,例如:

    { "Version": "2012-10-17", "Statement": [ { "Sid": "kmsstmt", "Effect": "Allow", "Action": [ "kms:Decrypt", "kms:Encrypt", "kms:GenerateDataKey" ], "Resource": [ "<kms-key-arn>" ] }, { "Sid": "s3stmt", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:Get*", "s3:List*" ], "Resource": [ "arn:aws:s3:::mybucket", "arn:aws:s3:::mybucket/*" ] } ] }

    mybucket 替换为您要访问的 S3 存储桶的名称。此外,如果 S3 存储桶已加密,请kms-key-arn替换为用于加密 S3 存储桶的 AWS Key Management Service (AWS KMS) 密钥的 ARN。否则,您就不需要政策中的 AWS KMS 章节了。

  5. 选择查看策略,输入 S3-Write-Policy 作为策略名称,然后选择创建策略

  6. 在导航窗格中,选择角色

  7.  选择创建角色

  8. 对于可信实体角色,选择自定义信任策略

  9. 选择下一步:权限,然后选择您创建的 S3-Write-Policy 策略。

  10. 输入 S3-Write-Role 作为角色名称,然后选择创建角色

DevOps 工程师

创建此 Amazon Redshift 角色。

要创建 Amazon Redshift 角色,请执行以下操作:

  1. 在 PROD 账户中,打开 IAM 控制台。

  2. 选择策略

  3. 选择创建策略

  4. 选择 JSON 选项卡,然后输入一个 IAM 策略,例如:

    { "Version": "2012-10-17", "Statement": [ { "Sid": "CrossAccountPolicy", "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "S3-Write-Role-ARN" } ] }

    S3-Write-Role-ARN 替换为 DEV 账户中的 S3-Write-Role 的 ARN。

  5. 选择查看策略,输入 S3-Write-Role-Assume-Policy 作为策略名称,然后选择创建策略

  6. 在导航窗格中,选择角色,然后选择创建角色

  7. 选择 AWS 服务作为您的可信实体类型,然后选择 RedshiftRedshift - 可自定义

  8. 选择下一步:权限,然后选择您创建的 S3-Write-Role-Assume-Policy 策略。

  9. 输入 CrossAccount-S3-Write-Role 作为角色名称,然后选择创建角色

  10. 将 IAM 角色与您的 Amazon Redshift 集群相关联

DevOps 工程师
Task说明所需技能

部署 Lambda 函数。

要在对等的 VPC 中部署 Lambda 函数,请执行以下操作:

  1. 在上打开 Lambda 控制台。 https://console.aws.amazon.com/lambda/

  2. 选择函数

  3. 选择创建函数

  4. 基本信息下方的函数名称中,输入函数的名称。

  5. 对于运行时,选择 Python 3.8

  6. 展开更改默认执行角色,然后执行以下操作:

    1. 选择使用现有角色

    2. 对于现有角色,请选择您之前创建的 CrossAccount-rm-read-role Lambda 角色

  7. 展开高级设置,并执行以下操作:

    1. 选中启用 VPC 复选框。

    2. 对于 VPC,选择 DEV 账户中的对等 VPC。

    3. 对于子网,选择私有子网。

    4. 对于安全组,选择默认安全组。

  8. 选择创建函数

  9. psycopg2 库作为一个添加到 Lambda 函数中。

    注意

    您可以使用 psycopg2-lambda-layer 存储库中的一个已经部署的层。请务必使用基于你 AWS 区域 和 Python 运行时的网址。

DevOps 工程师
Task说明所需技能

导入所需的资源。

要导入所需的资源,请运行以下命令:

import ast import boto3 import psycopg2 import base64 from botocore.exceptions import ClientError
应用程序开发人员

运行 Lambda 处理程序函数。

Lambda 函数使用 AWS Security Token Service (AWS STS) 进行跨账户访问和临时凭证管理。该函数使用 AssumeRole API 操作来临时承担 sm_read_role IAM 角色的权限。

要运行 Lambda 函数,请使用如下示例代码:

def lambda_handler(event, context): sts_client = boto3.client('sts') # Secrets Manager Configurations secret_name = "redshift_creds" sm_region = "eu-west-1" sm_read_role = "arn:aws:iam::PROD_ACCOUNT_NUMBER:role/SM-Read-Role" # S3 Bucket Configurations s3_bucket_path = "s3://mybucket/" s3_bucket_region = "eu-west-1" s3_write_role = "arn:aws:iam::DEV_ACCOUNT_NUMBER:role/S3-Write-Role" # Redshift Configurations sql_query = "select * from category" redshift_db = "dev" redshift_s3_write_role = "arn:aws:iam::PROD_ACCOUNT_NUMBER:role/CrossAccount-S3-Write-Role" chained_s3_write_role = "%s,%s" % (redshift_s3_write_role, s3_write_role) assumed_role_object = sts_client.assume_role( RoleArn=sm_read_role, RoleSessionName="CrossAccountRoleAssumption", ExternalId="YOUR_EXTERNAL_ID", ) credentials = assumed_role_object['Credentials'] secret_dict = ast.literal_eval(get_secret(credentials, secret_name, sm_region)) execute_query(secret_dict, sql_query, s3_bucket_path, chained_s3_write_role, s3_bucket_region, redshift_db) return { 'statusCode': 200 }
应用程序开发人员

获取密钥。

要获取 Amazon Redshift 密钥,请使用如下示例代码:

def get_secret(credentials, secret_name, sm_region): # Create a Secrets Manager client session = boto3.session.Session() sm_client = session.client( service_name='secretsmanager', aws_access_key_id=credentials['AccessKeyId'], aws_secret_access_key=credentials['SecretAccessKey'], aws_session_token=credentials['SessionToken'], region_name=sm_region ) try: get_secret_value_response = sm_client.get_secret_value( SecretId=secret_name ) except ClientError as e: print(e) raise e else: if 'SecretString' in get_secret_value_response: return get_secret_value_response['SecretString'] else: return base64.b64decode(get_secret_value_response['SecretBinary'])
应用程序开发人员

运行卸载命令。

要将数据卸载到 S3 存储桶,请使用如下示例代码。

def execute_query(secret_dict, sql_query, s3_bucket_path, chained_s3_write_role, s3_bucket_region, redshift_db): conn_string = "dbname='%s' port='%s' user='%s' password='%s' host='%s'" \ % (redshift_db, secret_dict["port"], secret_dict["username"], secret_dict["password"], secret_dict["host"]) con = psycopg2.connect(conn_string) unload_command = "UNLOAD ('{}') TO '{}' IAM_ROLE '{}' DELIMITER '|' REGION '{}';" \ .format(sql_query, s3_bucket_path + str(datetime.datetime.now()) + ".csv", chained_s3_write_role, s3_bucket_region) # Opening a cursor and run query cur = con.cursor() cur.execute(unload_command) print(cur.fetchone()) cur.close() con.close()
应用程序开发人员
Task说明所需技能

删除 Lambda 函数。

为了避免产生计划外成本,请移除资源以及 DEV 账户与 PROD 账户之间的连接。

要移除 Lambda 函数,请执行以下操作:

  1. 打开 AWS Lambda 控制台,网址为 https://console.aws.amazon.com/lambda/。

  2. 找到并选择您创建的 Lambda 函数。

  3. 选择操作,然后选择删除

  4. 确认删除操作。

DevOps 工程师

移除 IAM 角色和策略。

从 DEV 账户和 PROD 账户中移除 IAM 角色和策略。

在 DEV 账户中,执行以下操作:

  1. 打开 IAM 控制台。

  2. 删除以下角色:

    • S3-Write-Role

    • CrossAccount-RM-Read-Role(Lambda 角色)

  3. 删除相关的策略:

    • S3-Write-Policy

    • 担任 PROD 账户角色的 CrossAccount 政策

在 PROD 账户中,执行以下操作:

  1. 打开 IAM 控制台。

  2. 删除以下角色:

    • SM-Read-Role

    • CrossAccount-S3-Write-Role

  3. 删除相关的策略:

    • 访问 Secrets Manager 的 CrossAccount 政策

    • S3-Write-Role-Assume-Policy

DevOps 工程师

在 Secrets Manager 中删除密钥。

要删除密钥,请执行以下操作:

  1. 在 PROD 账户中,打开 Secrets Manager 控制台。

  2. 找到并选择名为 Redshift-Creds-Secret 的密钥。

  3. 选择操作,然后选择删除密钥

  4. 确认删除操作。

DevOps 工程师

移除 VPC 对等连接和安全组规则。

要移除 VPC 对等连接和安全组规则,请执行以下操作:

  1. 在 PROD 账户中,打开亚马逊 EC2 控制台,网址为 https://console.aws.amazon.com/ec2/。

  2. 导航到安全组

  3. 查找 Amazon Redshift 集群使用的安全组。

  4. 编辑入站规则,并移除允许来自 DEV 账户 Lambda VPC 的连接的那个规则。

  5. 导航到 VPC 对等连接,然后删除对等连接。

DevOps 工程师

从 S3 存储桶中移除数据。

要从 Amazon S3 中移除数据,请执行以下操作:

  1. 在开发者账户中,打开 Amazon S3 控制台,网址为 https://console.aws.amazon.com/s3/。

  2. 找到您用于存储数据的存储桶。

  3. 删除存储桶内的对象,如果不再需要存储桶,则删除整个存储桶。

DevOps 工程师

清理 AWS KMS 钥匙。

如果您创建了任何用于加密的自定义 AWS KMS 密钥,请执行以下操作:

  1. 打开 AWS KMS 控制台,网址为 https://console.aws.amazon.com/kms/。

  2. 找到为此模式创建的任何密钥。

  3. 计划删除密钥。(必须等待一段时间才会删除密钥)。

DevOps 工程师

查看并删除 Amazon CloudWatch 日志。

要删除日 CloudWatch 志,请执行以下操作:

  1. 打开 CloudWatch 控制台,网址为 https://console.aws.amazon.com/cloudwatch/。

  2. 检查是否存在由您的 Lambda 函数或 Amazon Redshift 集群创建的任何日志组。

  3. 删除不再需要的那些日志组。

DevOps 工程师

相关资源

附加信息

将数据从 Amazon Redshift 卸载到 Amazon S3 之后,您可以使用 Amazon Athena 来分析这些数据。

Amazon Athena 是一项大数据查询服务,当您需要访问大量的数据时会非常有用。您无需预调配服务器或数据库,即可使用 Athena。Athena 支持复杂的查询,您可以在不同的对象上运行 Athena。

与大多数一样 AWS 服务,使用 Athena 的主要好处是,它在运行查询时提供了极大的灵活性,而不会增加复杂性。使用 Athena 时,无需更改数据类型,即可在 Amazon S3 中查询不同的数据类型,例如 CSV 和 JSON。您可以查询来自各种来源的数据,包括外部数据 AWS。Athena 降低了复杂性,因为您不必管理服务器。Athena 直接从 Amazon S3 读取数据,而无需在您运行查询之前加载或更改数据。