一、概念
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