如今的开发团队越来越多的采用 DevOps 原则,例如持续集成和持续交付 (CI/CD)。因此,管理基础设施即代码 (IaC) 已成为任何云服务的必备功能。 IaC 工具允许您使用配置文件而不是图形用户界面来管理基础设施。IaC 通过定义可以版本化、重用和共享的资源配置,使您能够以安全、一致且可重复的方式构建、更改和管理基础设施。
HashiCorp Terraform 是 IaC 领域的一款领先工具,它通过其提供商和模块云基础设施自动化生态系统支持主要的云提供商和服务,用于任何云、基础设施和服务的供应、合规性和管理
Terraform 是一款开源的 IaC 软件工具,它提供一致的 CLI 工作流来管理数百个云服务。Terraform 将云 API 编纂成声明性配置文件,这些配置文件可以与团队成员共享,作为代码对待,进行编辑、审查和版本控制。它使您能够安全且可预测地创建、更改和改进基础设施。
Redis 为 Redis Cloud 开发了一个 Terraform 提供商。 HashiCorp Terraform Redis Cloud 提供商允许客户轻松地以代码形式在任何云提供商上部署和管理 Redis Cloud 订阅、数据库和网络对等。它是 Terraform 的一个插件,允许 Redis Cloud Flexible 客户管理其订阅和相关 Redis 数据库的整个生命周期。
Redis Cloud 提供商用于与 Redis Cloud 支持的资源进行交互。在使用该提供商之前,需要使用正确的凭据进行配置。使用左侧的导航阅读有关可用提供商资源和数据源的信息。
在我们开始实现之前,让我们花点时间更好地理解 Terraform 配置。Terraform 配置是在 Terraform 语言中的完整文档,它告诉 Terraform 如何管理给定的基础设施集合。一个配置可以包含多个文件和目录。Terraform 分为三个主要部分
提供商是在任何项目中在 Terraform 配置文件中需要定义的第一个资源。该提供商使您可以访问您将与之交互的 API 以创建资源。一旦提供商被配置并经过身份验证,大量资源现在可供创建。Terraform 为其提供的 100 多个云提供商提供服务。
提供商定义特定基础设施(例如 AWS)的资源和数据。如下所示,terraform 块 {} 包含 terraform 设置,包括 Terraform 用于配置基础设施所需的提供商(例如,rediscloud 提供商)。
terraform {
required_providers {
rediscloud = {
source = "RedisLabs/rediscloud"
version = "0.2.2"
}
}
}
provider {} 块配置特定提供商。在以下示例中,它是 AWS。
cloud_provider {
provider = "AWS"
cloud_account_id = 1
region {
region = "us-east-1"
networking_deployment_cidr = "10.0.0.0/24"
preferred_availability_zones = ["us-east-1a"]
}
}
资源是 Terraform 语言中最重要的元素。在这里,您描述要创建的基础设施部分,这可以从计算实例到定义特定权限等等。
如下所示,resource {} 块用于定义基础设施的组件。资源可能是物理或虚拟组件,例如 EC2,也可能是逻辑组件,例如 Heroku 应用程序。
resource "random_password" "passwords" {
count = 2
length = 20
upper = true
lower = true
number = true
}
resource {} 块在块之前有两个字符串:资源类型和资源名称。类型的首字母缩写映射到提供商的名称。例如,资源类型“random_password”和资源名称“passwords”形成了资源的唯一标识符。Terraform 使用此 ID 来识别资源。
数据源允许 Terraform 使用在 Terraform 之外定义的信息,由另一个独立的 Terraform 配置定义,或由函数修改。每个提供商可能在其资源类型集合旁边提供数据源。数据源通过一种特殊类型的资源访问,称为数据资源,使用 data 块声明。
data "rediscloud_payment_method" "card" {
card_type = "Visa"
last_four_numbers = "XXXX"
}
data 块请求 Terraform 从给定的数据源 (“rediscloud_payment_method”) 读取并将结果导出到给定的本地名称 (“card”) 下。该名称用于从同一个 Terraform 模块中的其他地方引用此资源,但在模块的范围之外没有任何意义。
在块主体({ 和 } 之间)中,由数据源定义的查询约束。本节中的大多数参数取决于数据源,实际上在本例中,card_type 和 last_four_numbers 都是专门为 rediscloud_payment_method 数据源定义的参数。
为了设置与 Redis Cloud 提供商的身份验证,必须为 Redis Cloud 生成一个编程 API 密钥。Redis Cloud 文档包含创建和管理密钥以及 IP 访问的最新的说明。
灵活和年度 Redis Cloud 订阅可以利用 RESTful API,该 API 允许对各种资源(包括服务器、服务和相关基础设施)进行操作。REST API 不支持固定或免费订阅。
provider "rediscloud" { } # Example resource configuration
resource "rediscloud_subscription" "example" { # ... }
使用 Homebrew 在 macOS 上安装 Terraform,如下所示
brew install terraform
按照本教程 注册免费的 Redis Cloud 帐户。
如果你有灵活(或年度)Redis Cloud 订阅,你可以使用 REST API 以编程方式管理你的订阅。Redis Cloud REST API 仅对灵活或年度订阅可用。它不支持固定或免费订阅。
出于安全原因,Redis Cloud API 默认情况下处于禁用状态。要启用 API
如果 API 帐户密钥右侧出现“复制”按钮,则表示 API 已启用。此按钮会将帐户密钥复制到剪贴板。
如果你看到“启用 API”按钮,请选中它以启用 API 并生成你的 API 帐户密钥。
要对 REST API 调用进行身份验证,你需要将 API 帐户密钥与 API 用户密钥结合起来才能进行 API 调用。
现在是时候创建一个空的“main.tf”文件并开始添加提供程序、资源和数据源,如下所示
terraform {
required_providers {
rediscloud = {
source = "RedisLabs/rediscloud"
version = "0.2.2"
}
}
}
# Provide your credit card details
data "rediscloud_payment_method" "card" {
card_type = "Visa"
last_four_numbers = "XXXX"
}
# Generates a random password for the database
resource "random_password" "passwords" {
count = 2
length = 20
upper = true
lower = true
number = true
special = false
}
resource "rediscloud_subscription" "rahul-test-terraform" {
name = "rahul-test-terraform"
payment_method_id = data.rediscloud_payment_method.card.id
memory_storage = "ram"
cloud_provider {
provider = "AWS"
cloud_account_id = 1
region {
region = "us-east-1"
networking_deployment_cidr = "10.0.0.0/24"
preferred_availability_zones = ["us-east-1a"]
}
}
database {
name = "db-json"
protocol = "redis"
memory_limit_in_gb = 1
replication = true
data_persistence = "aof-every-1-second"
module {
name = "RedisJSON"
}
throughput_measurement_by = "operations-per-second"
throughput_measurement_value = 10000
password = random_password.passwords[1].result
}
}
Terraform plan 命令会创建一个执行计划,它允许你预览 Terraform 计划对你的基础设施进行的更改。默认情况下,当 Terraform 创建计划时,它会读取任何已存在的远程对象的当前状态以确保 Terraform 状态是最新的。然后它将当前配置与先前状态进行比较,然后提出应使远程对象与配置匹配的一组更改操作。
% terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# random_password.passwords[0] will be created
+ resource "random_password" "passwords" {
+ id = (known after apply)
+ length = 20
+ lower = true
+ min_lower = 0
+ min_numeric = 0
+ min_special = 0
+ min_upper = 0
+ number = true
+ result = (sensitive value)
+ special = false
+ upper = true
}
# random_password.passwords[1] will be created
+ resource "random_password" "passwords" {
+ id = (known after apply)
+ length = 20
+ lower = true
+ min_lower = 0
+ min_numeric = 0
+ min_special = 0
+ min_upper = 0
+ number = true
+ result = (sensitive value)
+ special = false
+ upper = true
}
# rediscloud_subscription.rahul-test-terraform will be created
+ resource "rediscloud_subscription" "rahul-test-terraform" {
+ id = (known after apply)
+ memory_storage = "ram"
+ name = "rahul-test-terraform"
+ payment_method_id = "XXXX"
+ persistent_storage_encryption = true
+ cloud_provider {
+ cloud_account_id = "1"
+ provider = "AWS"
+ region {
+ multiple_availability_zones = false
+ networking_deployment_cidr = "10.0.0.0/24"
+ networks = (known after apply)
+ preferred_availability_zones = [
+ "us-east-1a",
]
+ region = "us-east-1"
}
}
+ database {
# At least one attribute in this block is (or was) sensitive,
# so its contents will not be displayed.
}
}
Plan: 3 to add, 0 to change, 0 to destroy.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
:::note
You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
:::
Terraform apply 命令会执行 Terraform 计划中提出的操作。
terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# random_password.passwords[0] will be created
+ resource "random_password" "passwords" {
+ id = (known after apply)
+ length = 20
+ lower = true
+ min_lower = 0
+ min_numeric = 0
+ min_special = 0
+ min_upper = 0
+ number = true
+ result = (sensitive value)
+ special = false
+ upper = true
}
# random_password.passwords[1] will be created
+ resource "random_password" "passwords" {
+ id = (known after apply)
+ length = 20
+ lower = true
+ min_lower = 0
+ min_numeric = 0
+ min_special = 0
+ min_upper = 0
+ number = true
+ result = (sensitive value)
+ special = false
+ upper = true
}
# rediscloud_subscription.rahul-test-terraform will be created
+ resource "rediscloud_subscription" "rahul-test-terraform" {
+ id = (known after apply)
+ memory_storage = "ram"
+ name = "rahul-test-terraform"
+ payment_method_id = "XXXX"
+ persistent_storage_encryption = true
+ cloud_provider {
+ cloud_account_id = "1"
+ provider = "AWS"
+ region {
+ multiple_availability_zones = false
+ networking_deployment_cidr = "10.0.0.0/24"
+ networks = (known after apply)
+ preferred_availability_zones = [
+ "us-east-1a",
]
+ region = "us-east-1"
}
}
+ database {
# At least one attribute in this block is (or was) sensitive,
# so its contents will not be displayed.
}
}
Plan: 3 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
random_password.passwords[0]: Creating...
random_password.passwords[1]: Creating...
random_password.passwords[1]: Creation complete after 0s [id=none]
random_password.passwords[0]: Creation complete after 0s [id=none]
rediscloud_subscription.rahul-test-terraform: Creating...
rediscloud_subscription.rahul-test-terraform: Still creating... [10s elapsed]
rediscloud_subscription.rahul-test-terraform: Still creating... [20s elapsed]
rediscloud_subscription.rahul-test-terraform: Creation complete after 8m32s [id=1649277]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
你现在可以验证在名为“db-json”的订阅下创建的新数据库。
使用 Terraform 在 AWS 上部署包含 JSON 和 [其他](Redis Stack ) 功能的 Redis 数据库
terraform {
required_providers {
rediscloud = {
source = "RedisLabs/rediscloud"
version = "0.2.2"
}
}
}
# Provide your credit card details
data "rediscloud_payment_method" "card" {
card_type = "Visa"
last_four_numbers = "XXXX"
}
# Generates a random password for the database
resource "random_password" "passwords" {
count = 2
length = 20
upper = true
lower = true
number = true
special = false
}
resource "rediscloud_subscription" "rahul-test-terraform" {
name = "rahul-test-terraform"
payment_method_id = data.rediscloud_payment_method.card.id
memory_storage = "ram"
cloud_provider {
provider = "AWS"
cloud_account_id = 1
region {
region = "us-east-1"
networking_deployment_cidr = "10.0.0.0/24"
preferred_availability_zones = ["us-east-1a"]
}
}
database {
name = "db-json"
protocol = "redis"
memory_limit_in_gb = 1
replication = true
data_persistence = "aof-every-1-second"
module {
name = "RedisJSON"
}
throughput_measurement_by = "operations-per-second"
throughput_measurement_value = 10000
password = random_password.passwords[1].result
}
}
Terraform destroy 命令是销毁特定 Terraform 配置管理的所有远程对象的便捷方法。虽然你通常不希望在生产环境中销毁长期存在的对象,但 Terraform 有时用于管理用于开发目的的临时基础设施,在这种情况下,你可以使用 terraform destroy’ 来方便地清理所有这些临时对象,一旦你完成了工作。
% terraform destroy
random_password.passwords[0]: Refreshing state... [id=none]
random_password.passwords[1]: Refreshing state... [id=none]
rediscloud_subscription.rahul-test-terraform: Refreshing state... [id=1649277]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# random_password.passwords[0] will be destroyed
- resource "random_password" "passwords" {
- id = "none" -> null
- length = 20 -> null
- lower = true -> null
- min_lower = 0 -> null
- min_numeric = 0 -> null
- min_special = 0 -> null
- min_upper = 0 -> null
- number = true -> null
- result = (sensitive value)
- special = false -> null
- upper = true -> null
}
# random_password.passwords[1] will be destroyed
- resource "random_password" "passwords" {
- id = "none" -> null
- length = 20 -> null
- lower = true -> null
- min_lower = 0 -> null
- min_numeric = 0 -> null
- min_special = 0 -> null
- min_upper = 0 -> null
- number = true -> null
- result = (sensitive value)
- special = false -> null
- upper = true -> null
}
# rediscloud_subscription.rahul-test-terraform will be destroyed
- resource "rediscloud_subscription" "rahul-test-terraform" {
- id = "1649277" -> null
- memory_storage = "ram" -> null
- name = "rahul-test-terraform" -> null
- payment_method_id = "XXXX" -> null
- persistent_storage_encryption = true -> null
- cloud_provider {
- cloud_account_id = "1" -> null
- provider = "AWS" -> null
- region {
- multiple_availability_zones = false -> null
- networking_deployment_cidr = "10.0.0.0/24" -> null
- networks = [
- {
- networking_deployment_cidr = "10.0.0.0/24"
- networking_subnet_id = "subnet-0055e8e3ee3ea796e"
- networking_vpc_id = ""
},
] -> null
- preferred_availability_zones = [
- "us-east-1a",
] -> null
- region = "us-east-1" -> null
}
}
- database {
# At least one attribute in this block is (or was) sensitive,
# so its contents will not be displayed.
}
}
Plan: 0 to add, 0 to change, 3 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
rediscloud_subscription.rahul-test-terraform: Destroying... [id=1649277]
…
rediscloud_subscription.rahul-test-terraform: Destruction complete after 1m34s
random_password.passwords[0]: Destroying... [id=none]
random_password.passwords[1]: Destroying... [id=none]
random_password.passwords[0]: Destruction complete after 0s
random_password.passwords[1]: Destruction complete after 0s
Destroy complete! Resources: 3 destroyed.