使用 Terraform 管理 Amazon Redshift 预配置集群

在本文中,我们将演示如何利用 Terraform 来管理常见的 Redshift 集群操作,例如:使用 Terraform 代码创建一个新的 Redshift 预配置集群,并向其添加亚马逊云科技身份与访问管理 (AWS Identity and Access Management, IAM) 角色;为 Redshift 集群调度暂停、恢复和调整大小等操作。


Amazon Redshift
教程
亚马逊云科技
Olawale Olaleye
难度
200 - 中级
时间
20 分钟
前提条件

海外区域: 注册 / 登录 亚马逊云科技

上次更新时间
2024 年 7 月 25 日
相关产品

Amazon Redshift 是一个快捷、可扩展、安全、完全托管的云数据仓库,能够以通俗易懂、高性价比的方式使用标准 SQL (结构化查询语言)、现有的抽取、转换和加载 (ETL)、商业智能以及报告工具,对您的所有数据进行分析。每天有数以万计的客户使用 Amazon Redshift 来处理艾字节量级的数据,以支持其商业智能、预测分析和实时流式分析等分析工作负载。

HashiCorp Terraform 是一种基础设施即代码 (IaC) 工具,允许您在人类可读的配置文件中定义云资源,这些配置文件还支持版本控制、复用和共享功能。您可采用一致的工作流,在基础设施的全生命周期对其加以配置和管理。


解决方案概述

下图展示了利用 Terraform 配置 Redshift 集群的方案架构。

除 Amazon Redshift 以外,该解决方案还用到了以下亚马逊云科技服务:

Amazon Elastic Compute Cloud (Amazon EC2) 提供了最具深度和广度的计算平台,拥有超过 750 种实例,可选择最新的处理器、存储设施、网络、操作系统和购买模式,助您完美满足工作负载的需求。在本文中,我们将使用搭载 Windows Server 2022 数据中心版 (Windows Server 2022 Datacenter Edition) 的 m5.xlarge 实例。实例类型和 Windows 操作系统的选择非常灵活;您可选择适合自己用例的配置。

IAM 允许您安全地管理亚马逊云科技服务及资源的身份和访问。我们使用 IAM 角色和策略来安全地访问服务并执行相关的操作。IAM 角色是一个亚马逊云科技身份,通过这一身份,您可获得对亚马逊云科技服务和资源的临时访问权限。每个 IAM 角色都有一组由 IAM 策略定义的权限。这些策略决定了角色可访问哪些操作和资源。

亚马逊云科技机密信息管理器 (AWS Secrets Manager) 允许您安全地存储登录 Amazon Redshift 所需的用户名和密码。

在本文中,我们将演示如何设置环境并连接至亚马逊云科技和 Terraform。具体涉及以下高级别任务:

  1. 在亚马逊云科技中设置一个搭载 Windows 操作系统的 EC2 实例
  2. 在实例上安装 Terraform。
  3. 配置环境变量(Windows 操作系统)。
  4. 定义一个 IAM 策略,获得最低的访问权限,以便对 Redshift 集群执行暂停、恢复和调整大小等操作。
  5. 使用您创建的策略建立一个 IAM 角色
  6. 使用 Terraform 代码创建一个 Redshift 预配置集群。
  7. 将您创建的 IAM 角色附加到 Redshift 集群。
  8. 编写 Terraform 代码,以调度暂停、恢复和调整大小等集群操作。

先决条件

要完成本文所述的操作,需要注册一个亚马逊云科技账户并获得账户管理员权限,以使用关键的亚马逊云科技服务并创建必要的 IAM 角色。


创建 EC2 实例

首先创建一个 EC2 实例。创建一个搭载 Windows 操作系统的 EC2 实例,具体步骤如下:

  1. 在 Amazon EC2 控制台上,选择“启动实例” (Launch Instance)
  2. 选择满足您要求的 Windows Server Amazon Machine Image (AMI)。
  3. 为您的用例选择合适的实例类型。
  4. 配置实例的详细信息:
    1. 选择要启动该实例的虚拟私有云(VPC)和子网。
    2. 启用“自动分配公网 IP 地址” (Auto-assign Public IP)
    3. 在“添加存储” (Add storage) 项配置实例所需的存储选项。
    4. 为实例添加必要的标签。
  5. 在“配置安全组” (Configure security group) 时,选择或创建一个安全组,以放行您的实例所需的入站和出站流量。
  6. 检查实例配置,点击“启动” (Launch) 以启动实例创建流程。
  7. 在“选择现有密钥对或创建新密钥对” (Select an existing key pair or create a new key pair) 项选择现有的密钥对或创建新的密钥对。
  8. 点击“启动实例” (Launch instance)
  9. 实例进入运行状态后,利用 Remote Desktop Protocol (RDP) 以及从“获取 Windows 密码” (Get Windows password) 中获得的管理员密码连接到该实例。

在 EC2 实例上安装 Terraform

在 Windows EC2 实例上安装 Terraform,具体步骤如下:

1. 通过 RDP 进入您创建的 EC2 实例。

2. 在 EC2 实例上安装 Terraform

您需要更新环境变量,将其指向 Terraform 可执行文件所在的目录。

3. 在“系统属性” (System Properties) 面板的“高级” (Advanced) 选项卡中,选择“环境变量” (Environment Variables)

4.  选择“路径” (Path) 变量。

5. 点击“新建” (New) 并输入 Terraform 的安装路径。在本文中,该路径设在 C 盘目录下。

6. 输入以下命令,以验证 Terraform 是否安装成功:

terraform -v

还可使用 Visual Studio Code (VS Code) 等编辑器添加 Terraform 扩展。


创建用户,以通过代码(AWS CLI 和 Terraform)访问亚马逊云科技服务

接下来,我们在 IAM 中创建一个管理员用户,通过 Terraform 和 AWS Command Line Interface (AWS CLI) 执行亚马逊云科技上的操作。具体步骤如下:

1. 创建一个新的 IAM 用户

2. 在 IAM 控制台中,下载并保存访问密钥 (access key) 和用户密钥 (user key)。

3. 安装 AWS CLI

4. 启动AWS CLI并运行 aws configure ,传递访问密钥 ID (access key ID)、机密信息访问密钥 (secret access key) 和默认的亚马逊云科技区域 (default AWS Region)。

这样亚马逊云科技用户名和密码就不会在 Terraform 代码中以纯文本显示出来,并防止代码提交到代码库时意外暴露用户名和密码。


创建用户,以通过代码 (Terraform) 访问 Redshift

创建 Redshift 集群和后续操作期间,需要在代码中调用所需的管理员用户名和密码(不同于我们之前创建的、用于登录 AWS Management Console 的管理员角色)。为了安全地做到这一点,我们使用机密信息管理器(Secrets Manager)来存储用户名和密码。我们在 Terraform 中编写代码,以便在创建集群期间访问这些凭证。完成以下步骤:

1. 在机密信息管理器控制台的导航窗格中选择“机密信息” (Secrets)

2. 选择“存储新机密信息” (Store a new secret)

3. 在“机密信息类型”项 (Secret type) 选择“Amazon Redshift 数据仓库凭证” (Credentials for Amazon Redshift data warehouse)。

4. 输入您的凭证。


设置 Terraform

设置 Terraform 的具体步骤如下:

1. 创建一个文件夹或目录来存放所有 Terraform 代码。

2. 打开 VS Code 编辑器,浏览您的文件夹。

3. 点击“新建文件” (New File0 并为文件命名,扩展名应为 .tf。

现在我们准备开始编写代码,先从定义提供商开始。定义提供商是 Terraform 获取所需 API 并与亚马逊云科技服务交互的一种方式。

4. 为 Terraform 配置提供商:

terraform {
required_providers {
aws = {
source  = "hashicorp/aws"
version = "5.53.0"
}
}
}

# Configure the AWS Provider
provider "aws" {
region = "us-east-1"
}

5. 访问 Amazon Redshift 管理员用户的凭证:

data "aws_secretsmanager_secret_version" "creds" {
# Fill in the name you gave to your secret
secret_id = "terraform-creds"
}
/*json decode to parse the secret*/
locals {
terraform-creds = jsondecode(
data.aws_secretsmanager_secret_version.creds.secret_string
)
}

创建 Redshift 集群

要创建 Redshift 集群,请使用 aws_redshift_cluster 资源:

# Create an encrypted Amazon Redshift cluster

resource "aws_redshift_cluster" "dw_cluster" {
cluster_identifier = "tf-example-redshift-cluster"
database_name      = "dev"
master_username    = local.terraform-creds.username
master_password    = local.terraform-creds.password
node_type          = "ra3.xlplus"
cluster_type       = "multi-node"
publicly_accessible = "false"
number_of_nodes    = 2
encrypted         = true
kms_key_id        = local.RedshiftClusterEncryptionKeySecret.arn
enhanced_vpc_routing = true
cluster_subnet_group_name="<<your-cluster-subnet-groupname>>"
}

在本示例中,我们创建了一个名为 tf-example-redshift-cluster 的 Redshift 集群,使用了 ra3.xlplus 节点类型的 2 型节点集群。我们利用 Secrets Manager 中的凭证和 jsondecode 来访问这些值,以确保用户名和密码不会以纯文本形式进行传输。


向集群添加 IAM 角色

由于我们在集群创建期间没有关联 IAM 角色的选项,因此现在可通过以下代码进行添加:

resource "aws_redshift_cluster_iam_roles" "cluster_iam_role" {
cluster_identifier = aws_redshift_cluster.dw_cluster.cluster_identifier
iam_role_arns      = ["arn:aws:iam::yourawsaccountId:role/service-role/yourIAMrolename"]
}

启用 Redshift 集群操作

可按照计划对 Redshift 集群执行调整大小、暂停和恢复等操作,这提供了一种更为实用的操作方式。因此,我们创建两个策略:一个允许 Amazon Redshift 启用计划服务,另一个允许集群执行暂停、恢复和调整大小等操作。然后我们再创建一个附加了这两个策略的角色。

可直接在控制台中执行这些步骤,再在 Terraform 代码中引用。以下示例代码片段演示了如何创建策略和角色、再将策略附加到角色。

1. 创建 Amazon Redshift 计划调度程序策略文档,并创建承担此策略的角色:

#define policy document to establish the Trust Relationship between the role and the entity (Redshift scheduler)

data "aws_iam_policy_document" "assume_role_scheduling" {
statement {
effect = "Allow"
principals {
type        = "Service"
identifiers = ["scheduler.redshift.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}

#create a role that has the above trust relationship attached to it, so that it can invoke the redshift scheduling service
resource "aws_iam_role" "scheduling_role" {
name               = "redshift_scheduled_action_role"
assume_role_policy = data.aws_iam_policy_document.assume_role_scheduling.json
}

2. 创建 Amazon Redshift 操作的策略文档和策略:

/*define the policy document for other redshift operations*/

data "aws_iam_policy_document" "redshift_operations_policy_definition" {
statement {
effect = "Allow"
actions = [
"redshift:PauseCluster",
"redshift:ResumeCluster",
"redshift:ResizeCluster",
]
resources = ["arn:aws:redshift:*:youraccountid:cluster:*"]
}
}

/*create the policy and add the above data (json) to the policy*/
resource "aws_iam_policy" "scheduling_actions_policy" {
name   = "redshift_scheduled_action_policy"
policy = data.aws_iam_policy_document.redshift_operations_policy_definition.json
}

3. 将策略附加到 IAM 角色:

/*connect the policy and the role*/
resource "aws_iam_role_policy_attachment" "role_policy_attach" {
policy_arn = aws_iam_policy.scheduling_actions_policy.arn
role       = aws_iam_role.scheduling_role.name
}

4. 暂停 Redshift 集群:

#pause a cluster
resource "aws_redshift_scheduled_action" "pause_operation" {
name     = "tf-redshift-scheduled-action-pause"
schedule = "cron(00 22 * * ? *)"
iam_role = aws_iam_role.scheduling_role.arn
target_action {
pause_cluster {
cluster_identifier = aws_redshift_cluster.dw_cluster.cluster_identifier
}
}
}

在上述示例中,我们创建了一个名为 tf-redshift-scheduled-action-pause 的计划操作,每晚 10:00 暂停集群以节省成本。

5. 恢复 Redshift 集群:

name     = "tf-redshift-scheduled-action-resume"
schedule = "cron(15 07 * * ? *)"
iam_role = aws_iam_role.scheduling_role.arn
target_action {
resume_cluster {
cluster_identifier = aws_redshift_cluster.dw_cluster.cluster_identifier
}
}
}

在上述示例中,我们创建了一个名为 tf-redshift-scheduled-action-resume 的计划操作,每天早上 7:15 及时恢复集群,以便业务运营启用 Redshift 集群。

6. 调整 Redshift 集群的大小:

#resize a cluster
resource "aws_redshift_scheduled_action" "resize_operation" {
name     = "tf-redshift-scheduled-action-resize"
schedule = "cron(15 14 * * ? *)"
iam_role = aws_iam_role.scheduling_role.arn
target_action {
resize_cluster {
cluster_identifier = aws_redshift_cluster.dw_cluster.cluster_identifier
cluster_type = "multi-node"
node_type = "ra3.xlplus"
number_of_nodes = 4 /*increase the number of nodes using resize operation*/
classic = true /*default behavior is to use elastic resizeboolean value if we want to use classic resize*/
}
}
}

在上述示例中,我们创建了一个名为 tf-redshift-scheduled-action-resize 的计划操作,将节点数量从 2 增加到了 4。您还可以执行其他操作,例如更改节点类型。默认情况下,集群大小是弹性调整的,但如果您想使用经典方式,则必须传递参数 classic = true ,具体如上述代码中所示。这可以是一个事先考虑高峰时段需求的计划操作,可在高峰时段适时地调整大小。在非高峰时段,您还可使用类似的代码缩小集群大小。


方案测试

我们执行以下代码来测试该解决方案。相应地修改资源的详细信息,例如账户 ID 和区域名称。

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.53.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = "us-east-1"
}

# access secrets stored in secret manager
data "aws_secretsmanager_secret_version" "creds" {
  # Fill in the name you gave to your secret
  secret_id = "terraform-creds"
}

/*json decode to parse the secret*/
locals {
  terraform-creds = jsondecode(
    data.aws_secretsmanager_secret_version.creds.secret_string
  )
}

#Store the arn of the KMS key to be used for encrypting the redshift cluster

data "aws_secretsmanager_secret_version" "encryptioncreds" {
  secret_id = "RedshiftClusterEncryptionKeySecret"
}
locals {
  RedshiftClusterEncryptionKeySecret = jsondecode(
    data.aws_secretsmanager_secret_version.encryptioncreds.secret_string
  )
}

# Create an encrypted Amazon Redshift cluster
resource "aws_redshift_cluster" "dw_cluster" {
  cluster_identifier = "tf-example-redshift-cluster"
  database_name      = "dev"
  master_username    = local.terraform-creds.username
  master_password    = local.terraform-creds.password
  node_type          = "ra3.xlplus"
  cluster_type       = "multi-node"
  publicly_accessible = "false"
  number_of_nodes    = 2
  encrypted         = true
  kms_key_id        = local.RedshiftClusterEncryptionKeySecret.arn
  enhanced_vpc_routing = true
  cluster_subnet_group_name="redshiftclustersubnetgroup-yuu4sywme0bk"
}

#add IAM Role to the Redshift cluster

resource "aws_redshift_cluster_iam_roles" "cluster_iam_role" {
  cluster_identifier = aws_redshift_cluster.dw_cluster.cluster_identifier
  iam_role_arns      = ["arn:aws:iam::youraccountid:role/service-role/yourrolename"]
}

#for audit logging please create an S3 bucket which has read write privileges for Redshift service, this example does not include S3 bucket creation.

resource "aws_redshift_logging" "redshiftauditlogging" {
  cluster_identifier   = aws_redshift_cluster.dw_cluster.cluster_identifier
  log_destination_type = "s3"
  bucket_name          = "your-s3-bucket-name"
}

#to do operations like pause, resume, resize on a schedule we need to first create a role that has permissions to perform these operations on the cluster

#define policy document to establish the Trust Relationship between the role and the entity (Redshift scheduler)

data "aws_iam_policy_document" "assume_role_scheduling" {
  statement {
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["scheduler.redshift.amazonaws.com"]
    }

    actions = ["sts:AssumeRole"]
  }
}

#create a role that has the above trust relationship attached to it, so that it can invoke the redshift scheduling service
resource "aws_iam_role" "scheduling_role" {
  name               = "redshift_scheduled_action_role"
  assume_role_policy = data.aws_iam_policy_document.assume_role_scheduling.json
}

/*define the policy document for other redshift operations*/

data "aws_iam_policy_document" "redshift_operations_policy_definition" {
  statement {
    effect = "Allow"
    actions = [
      "redshift:PauseCluster",
      "redshift:ResumeCluster",
      "redshift:ResizeCluster",
    ]

    resources =  ["arn:aws:redshift:*:youraccountid:cluster:*"]
  }
}

/*create the policy and add the above data (json) to the policy*/

resource "aws_iam_policy" "scheduling_actions_policy" {
  name   = "redshift_scheduled_action_policy"
  policy = data.aws_iam_policy_document.redshift_operations_policy_definition.json
}

/*connect the policy and the role*/

resource "aws_iam_role_policy_attachment" "role_policy_attach" {
  policy_arn = aws_iam_policy.scheduling_actions_policy.arn
  role       = aws_iam_role.scheduling_role.name
}

#pause a cluster

resource "aws_redshift_scheduled_action" "pause_operation" {
  name     = "tf-redshift-scheduled-action-pause"
  schedule = "cron(00 14 * * ? *)"
  iam_role = aws_iam_role.scheduling_role.arn
  target_action {
    pause_cluster {
      cluster_identifier = aws_redshift_cluster.dw_cluster.cluster_identifier
    }
  }
}

#resume a cluster

resource "aws_redshift_scheduled_action" "resume_operation" {
  name     = "tf-redshift-scheduled-action-resume"
  schedule = "cron(15 14 * * ? *)"
  iam_role = aws_iam_role.scheduling_role.arn
  target_action {
    resume_cluster {
      cluster_identifier = aws_redshift_cluster.dw_cluster.cluster_identifier
    }
  }
}

#resize a cluster

resource "aws_redshift_scheduled_action" "resize_operation" {
  name     = "tf-redshift-scheduled-action-resize"
  schedule = "cron(15 14 * * ? *)"
  iam_role = aws_iam_role.scheduling_role.arn
  target_action {
    resize_cluster {
      cluster_identifier = aws_redshift_cluster.dw_cluster.cluster_identifier
      cluster_type = "multi-node"
      node_type = "ra3.xlplus"
      number_of_nodes = 4 /*increase the number of nodes using resize operation*/
      classic = true /*default behavior is to use elastic resizeboolean value if we want to use classic resize*/
    }
  }
}

运行 terraform plan 命令以查看待更改项,截图如下所示。

检查更改项后,使用 terraform apply 来创建您所定义的资源。

在 Terraform 开始创建资源之前,系统会要求您输入 yes 或 no。

可在 Amazon Redshift 控制台中确认集群是否正在创建中。

集群创建完毕后,添加执行暂停、恢复和调整大小等操作的 IAM 角色和计划,截图如下所示。

也可在 Amazon Redshift 控制台中查看这些计划操作。


清理

如果您通过运行 terraform apply 部署了 Redshift 集群和 IAM 角色或其他关联资源,为避免您的亚马逊云科技账户产生费用,请运行 terraform destroy 释放这些资源并清理环境。


总结

Terraform 提供了一种强大而又灵活的解决方案,可利用声明式方法管理基础设施即代码,不仅具有云无关的特性和资源编排能力,还提供了强大的社区支持。本文提供了一份综合性指南,介绍了如何使用 Terraform 来部署 Redshift 集群并对集群执行调整大小、恢复和暂停等重要操作。借助基础设施即代码以及 Workflow Studio、VS Code 和 Terraform等合适的工具,可构建出可扩展、可维护的分布式应用程序,并实现流程的自动化。


Olawale Olaleye
相关教程
 如何使用 Terraform 为 Amazon GuardDuty 发现配置自动事件响应  使用 Terraform 实现自动化管理多个环境  让关系型数据库与 Amazon Redshift 无缝集成