一、概念
1、Terraform 的“基础设施即代码”是什么
基础设施即代码 (IaC) 工具允许您使用配置文件而非图形用户界面来管理基础设施。通过定义可版本控制、可重用和可共享的资源配置,IaC 允许您以安全、一致且可重复的方式构建、更改和管理您的基础设施。
Terraform 是 HashiCorp 的基础设施即代码工具。它允许您使用易于理解的声明式配置文件定义资源和基础设施,并管理基础设施的生命周期。与手动管理基础设施相比,使用 Terraform 具有以下几个优势:
- Terraform 可以管理多个云平台上的基础设施。
- 通俗易懂的配置语言可帮助您快速编写基础设施代码。
- Terraform 的状态允许您在整个部署过程中跟踪资源变化。
- 您可以将配置提交到版本控制中,以便在基础设施上安全地协作。
2、管理任何基础设施
Terraform 插件允许 Terraform 通过其应用程序编程接口 (API) 与云平台和其他服务进行交互。HashiCorp 和 Terraform 社区已编写了 1,000 多个提供程序,用于管理 Amazon Web Services (AWS)、Azure、Google Cloud Platform (GCP)、Kubernetes、Helm、GitHub、Splunk 和 DataDog 等平台上的资源。您可以在Terraform Registry中找到您已在使用的众多平台和服务的提供程序。如果您找不到所需的提供程序,可以自行编写。
3、标准化部署工作流程
提供商将基础架构的各个单元(例如计算实例或专用网络)定义为资源。您可以将来自不同提供商的资源组合成可重复使用的 Terraform 配置(称为模块),并使用一致的语言和工作流进行管理。
Terraform 的配置语言是声明式的,这意味着它描述了基础架构所需的最终状态,这与需要逐步说明才能执行任务的过程式编程语言不同。Terraform 提供程序会自动计算资源之间的依赖关系,以便按正确的顺序创建或销毁它们。
要使用 Terraform 部署基础设施:
- 范围——确定项目的基础设施。
- 编写——为您的基础设施编写配置。
- 初始化- 安装 Terraform 管理基础设施所需的插件。
- 计划- 预览 Terraform 将进行的更改以匹配您的配置。
- 应用——进行计划的更改。
4、追踪您的基础设施
Terraform 会将你的真实基础架构跟踪到状态文件中,该文件是你环境的真实来源。Terraform 使用状态文件来确定需要对基础架构进行的更改,以使其与你的配置相匹配。
二、安装
环境:CentOS Stream release 9
安装yum-config-manager以管理您的存储库。
$ sudo yum install -y yum-utils
用于yum-config-manager添加官方 HashiCorp RHEL 存储库。
$ sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
从新存储库安装 Terraform。
$ sudo yum -y install terraform
三、构建基础设施
创建名为 的目录learn-terraform-docker-container。
$ mkdir learn-terraform-docker-container
更改到目录。
$ cd learn-terraform-docker-container
创建一个文件来定义您的基础设施。
$ touch main.tf
在文本编辑器中打开main.tf,粘贴以下配置,然后保存文件
terraform {required_providers {docker = {source = "kreuzwerker/docker"version = "~> 3.0.1"}}
}provider "docker" {}resource "docker_image" "nginx" {name = "nginx:latest"keep_locally = false
}resource "docker_container" "nginx" {image = docker_image.nginx.image_idname = "tutorial"ports {internal = 80external = 8000}
}
1、初始化目录
在应用这个配置之前,需要先初始化目录;
$ terraform initInitializing the backend...Initializing provider plugins...
- Finding kreuzwerker/docker versions matching "~> 3.0.1"...
- Installing kreuzwerker/docker v3.0.1...
- Installed kreuzwerker/docker v3.0.1 (self-signed, key ID BD080C4571C6104C)Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
………………
terraform会下载docker提供应用程序并将其安装在当前工作目录的隐藏子目录中。名为.terraform。terraform还会创建一个名为.terraform.lock.hcl的锁文件,其中指定了所使用的提供程序的确切版本。
2、格式化并验证配置
建议在所有配置文件中使用一致的格式。该 terraform fmt命令会自动更新当前目录中的配置,以提高可读性和一致性。
$ terraform fmt
还可以使用该命令确保您的配置在语法上有效且内部一致terraform validate。
$ terraform validate
Success! The configuration is valid.
3、创建基础设施
现在使用以下命令应用配置terraform apply。Terraform 将打印类似如下所示的输出。
$ terraform applyTerraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:+ createTerraform will perform the following actions:# docker_container.nginx will be created+ resource "docker_container" "nginx" {
##...+ ports {+ external = 8000+ internal = 80+ ip = "0.0.0.0"+ protocol = "tcp"}}# docker_image.nginx will be created+ resource "docker_image" "nginx" {+ id = (known after apply)+ keep_locally = false+ latest = (known after apply)+ name = "nginx:latest"+ output = (known after apply)}Plan: 2 to add, 0 to change, 0 to destroy.
在应用任何更改之前,Terraform 都会打印出执行计划 ,该计划描述了 Terraform 为了更改基础设施以匹配配置将采取的操作。
Terraform 现在将暂停并等待您的批准,然后再继续。如果计划中有任何内容看起来不正确或危险,您可以安全地在此中止,并且不会对您的基础架构进行任何更改。
在确认提示下,输入yes键入继续执行。
Enter a value: yesdocker_image.nginx: Creating...
docker_image.nginx: Still creating... [10s elapsed]
docker_image.nginx: Creation complete after 13s [id=sha256:d1a364dc548d5357f0da3268c888e1971bbdb957ee3f028fe7194f1d61c6fdeenginx:latest]
docker_container.nginx: Creating...
docker_container.nginx: Creation complete after 2s [id=2834ad6283372ceb61121739ce71d31cb0237ad50f4dc234e3445c9445439181]Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
查看docker进程,容器已经创建
[root@k8s-10-0-1-189 learn-terraform-docker-container]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
89d5f94dee81 ad5708199ec7 "/docker-entrypoint.…" 4 days ago Up 4 days 0.0.0.0:8088->80/tcp ExampleNginxContainer
4、检查状态
当你应用配置时,Terraform 会将数据写入名为 的文件中 terraform.tfstate。Terraform 将其管理的资源的 ID 和属性存储在此文件中。
Terraform 状态文件是 Terraform 追踪其管理资源的唯一途径,并且通常包含敏感信息,因此您必须安全地存储状态文件,并仅限需要管理基础架构的受信任团队成员访问。
$ terraform show
# docker_container.nginx:
resource "docker_container" "nginx" {attach = falsecommand = ["nginx","-g","daemon off;",]cpu_shares = 0entrypoint = ["/docker-entrypoint.sh",]env = []gateway = "172.17.0.1"hostname = "2834ad628337"id = "2834ad6283372ceb61121739ce71d31cb0237ad50f4dc234e3445c9445439181"image = "sha256:d1a364dc548d5357f0da3268c888e1971bbdb957ee3f028fe7194f1d61c6fdee"init = falseip_address = "172.17.0.2"ip_prefix_length = 16ipc_mode = "private"log_driver = "json-file"……………………
四、改变基础设施
1、更新配置
现在更新容器的外部端口号。通过将ports.external 的值替换为8080 ,
resource "docker_container" "nginx" {image = docker_image.nginx.latestname = "tutorial"hostname = "learn-terraform-docker"ports {internal = 80
- external = 8000
+ external = 8080}
}
此更新会更改容器用于服务 nginx 服务器的端口号。Docker 提供程序知道容器创建后无法更改其端口,因此 Terraform 会销毁旧容器并创建一个新容器。
2、应用更改
更改配置后,terraform apply再次运行以查看 Terraform 如何将此更改应用到现有资源。
$ terraform apply
docker_image.nginx: Refreshing state... [id=sha256:d1a364dc548d5357f0da3268c888e1971bbdb957ee3f028fe7194f1d61c6fdeenginx:latest]
docker_container.nginx: Refreshing state... [id=5896c6cb7ae654503c36562472b573da8f49057fd466927be2870453a3b93e51]Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacementTerraform will perform the following actions:# docker_container.nginx must be replaced
-/+ resource "docker_container" "nginx" {
##...~ ports {~ external = 8000 -> 8080 # forces replacement# (3 unchanged attributes hidden)}}Plan: 1 to add, 0 to change, 1 to destroy.Do you want to perform these actions?Terraform will perform the actions described above.Only 'yes' will be accepted to approve.
该前缀-/+表示 Terraform 将销毁并重新创建资源,而不是就地更新。Terraform 可以就地更新某些属性(~前缀指示),但更改 Docker 容器的端口需要重新创建。
Terraform 再次提示您批准执行计划,然后才能继续。回答yes后即可执行计划中的步骤。
docker_container.nginx: Destroying... [id=5896c6cb7ae654503c36562472b573da8f49057fd466927be2870453a3b93e51]
docker_container.nginx: Destruction complete after 1s
docker_container.nginx: Creating...
docker_container.nginx: Creation complete after 1s [id=b2140f8c6aa79f62c8ac3c3d792f2044bcca8d5a0a08a4598ead1ade7aab7e6e]Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
根据执行计划,Terraform 首先销毁了现有容器,然后在其位置创建了一个新容器。您可以terraform show 再次使用 让 Terraform 打印出与此容器关联的新值。
五、查询带有输出的数据
1、输出 Docker 容器配置
outputs.tf在您的learn-terraform-docker-container目录中创建一个名为的文件。
添加以下配置来outputs.tf定义容器 ID 和图像 ID 的输出。
output "container_id" {description = "ID of the Docker container"value = docker_container.nginx.id
}
2、检查输出值
您必须先重新应用此配置,然后才能使用这些输出值。根据提示输入yes
$ terraform apply
应用配置时,Terraform 会将输出值打印到屏幕上。使用terraform output命令查询输出。
$ terraform output
container_id = "e5fff27c62e26dc9504d21980543f21161225ab483a1e534a98311a677b9453a"
六、删除基础设施
该terraform destroy命令会删除 Terraform 项目管理的资源。它不会删除当前 Terraform 项目未管理的、在其他位置运行的资源。
$ terraform destroy
docker_image.nginx: Refreshing state... [id=sha256:d1a364dc548d5357f0da3268c888e1971bbdb957ee3f028fe7194f1d61c6fdeenginx:latest]
docker_container.nginx: Refreshing state... [id=b2140f8c6aa79f62c8ac3c3d792f2044bcca8d5a0a08a4598ead1ade7aab7e6e]Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:- destroyTerraform will perform the following actions:# docker_container.nginx will be destroyed- resource "docker_container" "nginx" {
##...# docker_image.nginx will be destroyed- resource "docker_image" "nginx" {- id = "sha256:d1a364dc548d5357f0da3268c888e1971bbdb957ee3f028fe7194f1d61c6fdeenginx:latest" -> null- keep_locally = false -> null- latest = "sha256:d1a364dc548d5357f0da3268c888e1971bbdb957ee3f028fe7194f1d61c6fdee" -> null- name = "nginx:latest" -> null}Plan: 0 to add, 0 to change, 2 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:
该-前缀表示该容器将被销毁。与 apply 类似,Terraform 会显示其执行计划,并等待批准后才能进行任何更改。
回答yes执行这个计划并删除这个基础设施。
Enter a value: yesdocker_container.nginx: Destroying... [id=b2140f8c6aa79f62c8ac3c3d792f2044bcca8d5a0a08a4598ead1ade7aab7e6e]
docker_container.nginx: Destruction complete after 2s
docker_image.nginx: Destroying... [id=sha256:d1a364dc548d5357f0da3268c888e1971bbdb957ee3f028fe7194f1d61c6fdeenginx:latest]
docker_image.nginx: Destruction complete after 0sDestroy complete! Resources: 2 destroyed.
七、目录层级
最后让我们来看一下,一个普通的terraform基础设施目录的层级。
[root@k8s-10-0-1-189 learn-terraform-docker-container]# tree -a ./
./
#主配置文件
├── main.tf
#输出的配置文件
├── outputs.tf
#初始化时,安装的程序二进制文件等信息
├── .terraform
│ └── providers
│ └── registry.terraform.io
│ └── kreuzwerker
│ └── docker
│ └── 3.0.2
│ └── linux_amd64
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ └── terraform-provider-docker_v3.0.2
#指定了提供程序的确切版本,避免在更新程序时,下载最新提供程序,而导致不兼容
├── .terraform.lock.hcl
#存储资源ID和属性
├── terraform.tfstate
#变量配置文件
└── variables.tf