使用 Terraform 实现基础设施即代码:从入门到实践
1. gcloud CLI 凭证管理
gcloud CLI 管理着两种不同的凭证:
- 当执行 gcloud 命令时,gcloud 使用的是运行
gcloud auth login
时保存的凭证。
- 当通过软件中的客户端库或像 Terraform 这样的应用程序与 Google Cloud 进行交互时,会使用应用程序默认凭证,这些凭证是在运行
gcloud auth application-default login
时保存的。
2. 最小示例入门
在安装好 Terraform CLI 并确保其已通过身份验证可以与 Google Cloud 通信后,就可以开始编写配置了。下面将展示一个在 Cloud Run 上部署 “Hello World” 服务的最小示例。
2.1 配置文件编写
首先创建
main.tf
文件,内容如下:
provider google {
project = var.project_id
version = "~> 3.0"
}
variable "project_id" {
type = string
description = "The Google Cloud Project ID to use"
}
这个文件告诉 Terraform 要使用特定版本的 Google 提供程序,并引用了一个保存项目 ID 的输入变量。
接着,在包含
main.tf
文件的目录中打开 shell,执行
terraform init
命令来初始化工作目录。成功执行后,输出应类似于:
$: terraform init
Initializing the backend...
Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "google" (hashicorp/google) 3.24.0...
Terraform has been successfully initialized!
2.2 提供程序介绍
执行
terraform init
时,Terraform 会下载 Google 提供程序,它是一个插件。在项目目录的
.terraform
文件夹中可以看到,这个提供程序插件实际上是一个二进制可执行文件。
Terraform 支持多种不同的提供程序,Google 提供程序只是其中一个示例,它允许 Terraform 在 Google Cloud 上创建和管理资源。其他提供程序还包括 AWS、Azure、OpenStack 等。基本上,任何具有管理资源 API 的服务都可以在 Terraform 中拥有对应的提供程序。
2.3 变量作为参数
main.tf
文件中的第二个块是输入变量声明。在 Terraform 中,变量可以看作是参数或输入值。在规划和应用更改时,需要提供这些参数,可以通过命令行、环境变量或变量定义文件来提供。
2.4 添加第一个资源声明
接下来,添加第一个由 Terraform 管理的资源,即一个 Cloud Run 服务,它将部署一个返回 “Hello World” 的容器。创建一个名为
service-hello.tf
的新文件,内容如下:
resource google_cloud_run_service "hello" {
name = "hello-terraform"
location = "us-central1"
template {
spec {
containers {
image = "gcr.io/cloud-run-book/inspect"
}
}
}
}
在这个示例中,
google_cloud_run_service
是资源类型,
"hello"
是该资源在 Terraform 中的 “本地名称”,用于定义资源之间的依赖关系。而
name
属性用于设置资源在基础设施中的实际名称。
2.5 Terraform 配置语言
上述配置文件使用的是 Terraform 配置语言 HashiCorp Configuration Language (HCL)。HCL 是一种声明式配置语言,具有有限的 “编程语言” 特性,如创建循环、传递参数和创建模块等。
需要注意的是,HCL 不是编程语言,资源块不是函数,它是一种配置语言,这使得配置更容易理解。资源类型由提供程序提供,不同的提供程序具有不同的资源类型,因此 Terraform 代码高度依赖于提供程序,不同提供程序之间的代码不能互换。
另外,文件名在 Terraform 中没有意义,Terraform 会在文件夹中查找所有以
.tf
结尾的文件。
3. 部署服务准备:创建计划
此时,应该有一个
main.tf
文件引用了提供程序和输入变量
project_id
,以及一个
service-hello.tf
文件包含要部署的 Cloud Run 服务。
执行
terraform plan -out tfplan
命令创建计划,输出如下(简略编辑):
$: terraform plan -out tfplan
var.project-id
The Google Cloud Project ID to use
Enter a value: [YOUR PROJECT ID]
An execution plan has been generated and is shown below.
Terraform will perform the following actions:
# google_cloud_run_service.hello will be created
+ resource "google_cloud_run_service" "hello" {
+ template {
+ spec {
+ containers {
+ image = "gcr.io/cloud-run-book/inspect"
}
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
This plan was saved to: tfplan
To perform exactly these actions, run the following command to apply:
terraform apply tfplan
第一次执行
terraform plan
时,Terraform 会读取配置并确定创建资源的顺序,即创建一个计划。这里的计划显示将创建
google_cloud_run_service.hello
资源。
使用
-out tfplan
参数将计划保存到文件中,现在目录中应该有一个
tfplan
文件,它是一个压缩存档,可以使用
terraform show
命令查看其内容。
3.1 保存输入变量
Terraform 会提示输入
project_id
变量的值。为了避免每次运行命令时都输入该值,可以创建一个
terraform.tfvars
文件,内容如下:
project_id="[YOUR PROJECT ID]"
也可以使用命令行参数或环境变量来提交输入变量。
4. 部署服务:应用计划
创建好
tfplan
文件后,使用
terraform apply tfplan
命令应用计划,输出如下:
$: terraform apply tfplan
google_cloud_run_service.hello: Creating...
google_cloud_run_service.hello: Still creating... [10s elapsed]
google_cloud_run_service.hello: Creation complete after 13s
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.
State path: terraform.tfstate
Terraform 会告知应用完成,成功添加了一个资源,即部署了
hello
服务。但 Terraform 不会显示服务的 URL,可以通过执行
gcloud run services list
来查找。打开服务 URL 时会出现 “Your client does not have permission to get URL / from this server” 错误,这意味着服务已成功部署,但需要设置 IAM 访问策略。
5. Terraform 状态
执行
terraform apply
命令时,输出会提及保存的状态文件。可以使用
terraform show
命令检查状态文件,它包含了 Terraform 当前管理的资源列表及其属性,这些属性可能包含敏感信息,如 API 密钥、数据库用户密码和服务器证书等,因此共享状态文件时要确保其安全性。
还可以使用
terraform console
命令查询状态,例如输入
google_cloud_run_service.hello.status
会得到一个包含服务状态的数组。
6. Terraform 工作流程
在对基础设施进行更改时,主要会使用
plan
和
apply
命令,它们的工作流程如下:
graph LR
A[更改配置文件] --> B[运行 terraform plan]
B --> C{比较配置文件和 Terraform 状态}
C --> D[确定要执行的操作(创建、更新、删除)]
D --> E[生成计划]
E --> F[运行 terraform apply]
F --> G[应用计划,修改云资源和 Terraform 状态]
具体步骤如下:
1. Terraform 通过读取配置文件了解基础设施的期望状态。
2. 将期望状态与实际(存储)状态进行比较,实际状态由
apply
命令维护。如果第一次运行
plan
命令,Terraform 会认为状态为空,将创建配置文件中的所有资源。
3. 为了将实际状态更改为期望状态,Terraform 需要执行一系列创建、更新和删除操作,这些操作的列表就是计划。
在应用计划之前,一定要仔细研究计划中的更改列表,避免意外删除重要资源。尽量使每次更改尽可能小,一次只处理一个问题,这样更易于审查。
7. 使用 Terraform 进行更改:添加访问策略
为了让服务允许公共流量,从而在浏览器中看到 “Hello World”,需要添加一个访问策略。在
service-hello.tf
文件中追加以下内容:
data google_iam_policy "run_invoke_all_users" {
binding {
role = "roles/run.invoker"
members = [
"allUsers",
]
}
}
resource google_cloud_run_service_iam_policy "hello_all_users" {
service = google_cloud_run_service.hello.name
location = google_cloud_run_service.hello.location
policy_data = data.google_iam_policy.run_invoke_all_users.policy_data
}
这里创建了一个策略,将
allUsers
成员绑定到
roles/run.invoker
角色,该角色具有
run.routes.invoke
权限。使用
google_cloud_run_service_iam_policy
资源将该策略添加到
hello
服务中。
追加这些行后,可以生成计划并应用它,也可以直接运行
terraform apply
命令。执行该命令时,Terraform 会先在内存中生成计划,然后提示确认操作,输出如下:
$: terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# google_cloud_run_service_iam_policy.hello_all_users will be created
+ resource "google_cloud_run_service_iam_policy" "hello_all_users" {
...
}
Plan: 1 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
google_cloud_run_service_iam_policy.hello_all_users: Creating...
google_cloud_run_service_iam_policy.hello_all_users: Creation complete after 2s
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
现在打开 Cloud Run 服务的 URL 就可以看到 “Hello World” 了。由于 IAM API 有时会有延迟,如果没有立即看到 403 错误消失,可以等待一分钟后重试。
8. 通过引用表达依赖关系
大多数使用 Terraform 管理的云资源之间都存在相互关系。例如,在上面的示例中,IAM 策略依赖于 Cloud Run 服务的存在,因为为不存在的资源创建策略是没有意义的。
另一个例子是数据库用户,
google_sql_user
资源用于在 Cloud SQL 数据库上创建用户,但首先需要有一个数据库才能创建用户。这体现了资源之间的依赖关系,在 Terraform 中可以通过引用资源的本地名称来定义这些依赖关系,确保资源按正确的顺序创建和管理。
综上所述,通过以上步骤,我们可以使用 Terraform 在 Google Cloud 上实现基础设施即代码,从创建简单的服务到添加访问策略,逐步掌握 Terraform 的使用和工作流程。同时,要注意资源之间的依赖关系和状态文件的管理,以确保基础设施的稳定和安全。
使用 Terraform 实现基础设施即代码:从入门到实践
9. 资源依赖关系的重要性及管理
资源依赖关系在 Terraform 中起着至关重要的作用。以下是依赖关系的一些关键要点和管理方法:
-
确保资源按顺序创建
:如前面提到的 IAM 策略依赖于 Cloud Run 服务,Terraform 会根据资源之间的引用关系,确保先创建依赖的资源。例如在添加访问策略时,
google_cloud_run_service_iam_policy
依赖于
google_cloud_run_service
,Terraform 会先创建
google_cloud_run_service
。
-
避免循环依赖
:循环依赖会导致 Terraform 无法确定资源的创建顺序,从而报错。在编写配置时,要仔细检查资源之间的引用,确保不会形成循环。
-
使用依赖元参数
:在某些情况下,可以使用
depends_on
元参数来明确指定资源之间的依赖关系。例如:
resource "google_cloud_run_service" "hello" {
# 资源配置
}
resource "google_cloud_run_service_iam_policy" "hello_all_users" {
service = google_cloud_run_service.hello.name
location = google_cloud_run_service.hello.location
policy_data = data.google_iam_policy.run_invoke_all_users.policy_data
depends_on = [google_cloud_run_service.hello]
}
10. Terraform 工作流程总结
为了更清晰地理解 Terraform 的工作流程,我们可以将其总结为以下表格:
| 步骤 | 命令 | 说明 |
| ---- | ---- | ---- |
| 初始化 |
terraform init
| 初始化工作目录,下载所需的提供程序插件 |
| 创建计划 |
terraform plan -out tfplan
| 读取配置文件,比较期望状态和实际状态,生成计划并保存到文件 |
| 应用计划 |
terraform apply tfplan
或
terraform apply
| 应用计划,修改云资源和 Terraform 状态 |
| 查看状态 |
terraform show
| 查看 Terraform 状态文件的内容 |
| 查询状态 |
terraform console
| 交互式查询 Terraform 状态 |
11. 常见错误及解决方法
在使用 Terraform 过程中,可能会遇到一些常见的错误,以下是一些常见错误及解决方法:
-
凭证错误
:如果遇到凭证相关的错误,可能是
gcloud auth login
或
gcloud auth application-default login
未正确执行。重新执行相应的命令,确保凭证正确保存。
-
资源冲突
:当尝试创建已经存在的资源时,会出现资源冲突错误。检查配置文件,确保资源名称的唯一性。
-
计划错误
:如果
terraform plan
命令报错,可能是配置文件存在语法错误或资源引用错误。仔细检查配置文件,确保语法正确,资源引用无误。
12. 最佳实践建议
为了更高效地使用 Terraform,以下是一些最佳实践建议:
-
模块化设计
:将常用的配置封装成模块,提高代码的复用性。例如,可以将创建 Cloud Run 服务的配置封装成一个模块,在不同的项目中重复使用。
-
版本控制
:将 Terraform 配置文件纳入版本控制系统,如 Git。这样可以方便团队协作,记录配置的变更历史。
-
状态文件管理
:状态文件包含敏感信息,要妥善管理。可以使用远程状态存储,如 Google Cloud Storage 或 Terraform Cloud,确保状态文件的安全性。
-
小步变更
:每次只进行小的更改,便于审查和调试。避免一次性进行大量的更改,减少出错的风险。
13. 扩展应用:多提供程序支持
Terraform 支持多种云服务提供商,除了 Google Cloud,还可以结合 AWS、Azure 等。以下是一个简单的示例,展示如何在一个代码库中同时使用 Google Cloud 和 AWS 提供程序:
# Google Cloud 提供程序配置
provider "google" {
project = var.project_id
version = "~> 3.0"
}
# AWS 提供程序配置
provider "aws" {
region = "us-west-2"
}
# Google Cloud 资源
resource "google_cloud_run_service" "hello" {
name = "hello-terraform"
location = "us-central1"
template {
spec {
containers {
image = "gcr.io/cloud-run-book/inspect"
}
}
}
}
# AWS 资源
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
通过这种方式,可以在一个代码库中统一管理多个云服务提供商的基础设施。
14. 总结与展望
通过以上内容,我们详细介绍了使用 Terraform 实现基础设施即代码的过程,包括凭证管理、资源创建、计划生成、应用计划、状态管理、添加访问策略以及资源依赖关系等方面。同时,我们还总结了工作流程、常见错误及解决方法、最佳实践建议,并展示了多提供程序的支持。
在未来,随着云计算技术的不断发展,Terraform 作为一种强大的基础设施管理工具将发挥更大的作用。可以进一步探索 Terraform 的高级功能,如数据资源、动态块、条件表达式等,以满足更复杂的基础设施管理需求。同时,结合持续集成/持续部署(CI/CD)工具,实现基础设施的自动化部署和更新,提高开发和运维效率。
总之,掌握 Terraform 的使用,能够帮助我们更高效、更安全地管理云计算基础设施,实现基础设施即代码的目标。
超级会员免费看
5499

被折叠的 条评论
为什么被折叠?



