如何将现有DigitalOcean资产导入Terraform
作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。
介绍
Terraform 是由 HashiCorp 创建的基础架构即代码工具,可帮助开发人员以高效且可扩展的方式部署、更新和删除其基础架构的不同资产。
开发人员可以使用 Terraform 组织不同的环境,通过版本控制跟踪更改,并自动执行重复性工作以限制人为错误。 它还为团队提供了一种通过共享配置协作改进其基础架构的方式。
在本教程中,您将把现有的 DigitalOcean 基础设施导入 Terraform。 在本教程结束时,除了创建新资产外,您将能够将 Terraform 用于所有现有基础设施。
先决条件
- DigitalOcean 个人访问令牌,您可以通过 DigitalOcean 控制面板创建它。 您可以在 DigitalOcean 产品文档中找到说明,如何创建个人访问令牌。
- 带有标签的 DigitalOcean Droplet。 您可以使用以下关于 如何从 DigitalOcean 控制面板 创建 Droplet 的指南。 本教程使用标签
terraform-testing
。 - 应用于您的 Droplet 的 DigitalOcean 云防火墙。 您可以使用指南 如何创建防火墙 。 防火墙名称
testing-terraform-firewall
用于本教程的目的。 - DigitalOcean 命令行客户端安装在您的本地机器上,您可以按照 doctl GitHub 页面 上的安装说明进行操作。 如需更多指导,您可以阅读教程 如何使用 Doctl,官方 DigitalOcean 命令行客户端 。
本教程使用 Terraform 1.0.10 进行了测试。
第 1 步 — 在本地安装 Terraform
在这第一步中,您将在本地计算机上安装 Terraform。 此步骤详细说明了在 Linux 发行版上安装 Terraform。 如果您使用 Windows 或 MacOS,您可以查看 Terraform 网站上的 下载 Terraform 页面。
HashiCorp 网站 上描述了安装步骤。
注意:在同一命令中直接管道/运行从互联网下载的对象/可执行文件通常是不好的做法,但由于 HashiCorp 是受信任的来源,我们将在此例外。 如果您对此感到不自在,请先下载该对象,检查它,然后在一切正常的情况下继续前进。
在 Ubuntu 20.04 上安装
HashiCorp 对他们的存储库进行了数字签名,因此您需要添加他们的 GNU Privacy Guard (GPG) 密钥。 这提供了一个合理的保证,即存储库实际上由 HashiCorp 拥有和维护:
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
将官方 HashiCorp 存储库添加到系统:
sudo apt-add-repository "deb [arch=$(dpkg --print-architecture)] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
安装 Terraform:
sudo apt update; sudo apt install terraform=1.0.10
在 Fedora 34 上安装
为了添加 HashiCorp 存储库,您需要将其添加到存储库列表中。 核心 DNF 插件 config-manager
用于此目的,由 dnf-plugins-core
包提供。 安装需要的 dnf
插件:
sudo dnf install -y dnf-plugins-core
将官方 HashiCorp 存储库添加到系统:
sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/fedora/hashicorp.repo
安装 Terraform:
sudo dnf install terraform-1.0.10-1
按照您的操作系统的安装说明进行操作后,通过检查版本来检查 Terraform 是否已正确安装:
terraform version
输出将类似于以下内容:
OutputTerraform v1.0.10 on linux_amd64
您已将 Terraform 安装到本地计算机。 接下来,您将准备配置文件。
第 2 步 — 准备 Terraform 配置文件
在此步骤中,您将通过创建项目目录和编写配置文件将现有资产导入 Terraform。 由于 Terraform 目前不支持从导入命令生成配置 [1] ,因此您需要手动创建这些配置。
运行以下命令来创建您的项目目录:
mkdir -p do_terraform_import
然后进入该目录:
cd do_terraform_import
初始化一个新的 Terraform 工作区:
terraform workspace new do_terraform_import
检查您是否正在使用新创建的工作区:
terraform workspace list
输出将与此类似:
Output default * do_terraform_import
在此步骤中,您将创建三个包含所需配置的附加文件。 此项目的目录结构如下所示:
├── digitalocean_droplet.tf ├── digitalocean_firewall.tf ├── provider.tf ├── .terraform └── terraform.tfstate.d
首先,您将创建文件 provider.tf
以将您的 DigitalOcean 访问令牌定义为环境变量,而不是将其硬编码到您的配置中。
警告:您的访问令牌可以无限制地访问您的完整基础架构,因此请这样对待。 确保您是唯一有权访问存储该令牌的机器的人。
除了访问令牌之外,您还将指定要使用的提供程序。 在本教程中,即 digitalocean
。 有关具有 Terraform 的 DigitalOcean 可用数据源和资源的完整列表,请访问其网站 上的 Providers 页面。
使用以下命令创建和编辑 provider.tf
:
nano provider.tf
在provider.tf
文件中添加如下内容:
提供者.tf
terraform { required_providers { digitalocean = { source = "digitalocean/digitalocean" version = "2.15.0" } } } variable "do_token" {} provider "digitalocean" { token = var.do_token }
在此文件中,您将 DigitalOcean 访问令牌添加为变量,Terraform 将使用该变量作为 DigitalOcean API 的标识。 您还可以指定 DigitalOcean 提供程序插件的版本。 Terraform 建议您指定您使用的提供程序的版本,以便将来的更新不会破坏您当前的设置。
保存并关闭文件。
现在您将创建 digitalocean_droplet.tf
文件。 在这里,您将指定要使用的资源,在本例中为:droplet
。
此文件应复制现有资源,以便在后续步骤中成功将其导入 Terraform 状态。
使用以下命令创建文件:
nano digitalocean_droplet.tf
添加以下配置,在必要时更新以匹配您预先存在的资源:
digitalocean_droplet.tf
resource "digitalocean_droplet" "do_droplet" { name = "testing-terraform" region = "fra1" tags = ["terraform-testing"] count = "1" }
在这里,您指定了四个应该与您预先存在的资源相匹配的参数:
name
:Droplet 名称。region
:Droplet 所在的区域。tags
:应用于此 Droplet 的标签列表。count
:此配置所需的资源数量。
保存并关闭文件。
接下来,您将为防火墙创建一个配置文件。 使用以下命令创建文件 digitalocean_firewall.tf
:
nano digitalocean_firewall.tf
将以下内容添加到文件中:
digitalocean_firewall.tf
resource "digitalocean_firewall" "do_firewall" { name = "testing-terraform-firewall" tags = ["terraform-testing"] }
您可以在此处指定要导入的防火墙的名称以及应用防火墙规则的 Droplet 的标签。
保存并关闭文件。
注意:您也可以在digitalocean_droplet.tf
文件中包含防火墙资源; 但是,如果您有多个环境,其中多个 Droplet 共享同一个防火墙,最好将它们分开,以防您只想删除单个 Droplet。 这将使防火墙不受影响。
现在是时候初始化这些更改,以便 Terraform 可以下载所需的依赖项。 为此,您将使用 terraform init
命令,这将允许您初始化包含 Terraform 配置文件的工作目录。
从您的项目目录运行此命令:
terraform init
您将看到以下输出:
OutputTerraform has been successfully initialized!
Terraform 通过下载插件、搜索模块等成功地准备了工作目录。 接下来,您将开始将资产导入 Terraform。
第 3 步 - 将您的资产导入 Terraform
在此步骤中,您会将 DigitalOcean 资产导入 Terraform。 在导入资产之前,您将使用 doctl
来查找 Droplet 的 ID 号。 然后,您将使用 terraform show
和 terraform plan
命令检查导入配置。
首先,您需要将 DigitalOcean 访问令牌导出为环境变量,然后在运行时将其注入 Terraform。
使用以下命令将其作为环境变量导出到当前的 shell 会话中:
export DO_TOKEN="YOUR_TOKEN"
为了导入您现有的 Droplet 和防火墙,您需要他们的 ID 号。 您可以使用 doctl
,DigitalOcean API 的命令行界面。
运行以下命令列出您的 Droplet 并访问它们的 ID:
doctl compute droplet list
您将看到类似于以下内容的输出:
OutputID Name Public IPv4 DROPLET-ID DROPLET-NAME DROPLET-IPv4 DROPLET-ID DROPLET-NAME DROPLET-IPv4 DROPLET-ID DROPLET-NAME DROPLET-IPv4
记下您要导入的资源的 Droplet ID,因为您将在稍后的命令中使用它。
接下来,运行以下命令来列出您的防火墙并访问它们的 ID:
doctl compute firewall list
您将看到类似于以下内容的输出:
OutputID Name Status FIREWALL-ID FIREWALL-NAME succeeded
记下您要导入的资源的防火墙 ID,因为您将在稍后的命令中需要它。
将现有的 Droplet 导入 Terraform,将 DROPLET-ID 替换为 Droplet 的 ID:
terraform import -var "do_token=${DO_TOKEN}" digitalocean_droplet.do_droplet DROPLET-ID
您使用 -var
标志来指定您之前导出到 shell 会话的 DigitalOcean 访问令牌值。 这是必需的,以便 DigitalOcean API 可以验证您的身份并将更改应用于您的基础架构。
现在为您的防火墙运行相同的命令,将 FIREWALL ID 替换为您的防火墙的 ID:
terraform import -var "do_token=${DO_TOKEN}" digitalocean_firewall.do_firewall FIREWALL-ID
您将使用 terraform show
命令检查导入是否成功。 此命令提供基础设施状态的人类可读输出。 它可用于检查计划以确保将执行所需的更改,或检查 Terraform 看到的当前状态。
在这种情况下,state 指的是您的 DigitalOcean 资产到您编写的 Terraform 配置的映射以及元数据的跟踪。 这使您可以确认要导入的现有 DigitalOcean 资产与 Terraform 正在跟踪的资产之间没有区别:
terraform show
输出将类似于以下内容:
Output. . . # digitalocean_droplet.do_droplet: resource "digitalocean_droplet" "do_droplet" { backups = false created_at = "2020-02-03T16:12:02Z" disk = 25 id = "DROPLET-ID" image = "DROPLET-IMAGE" ipv4_address = "DROPLET-IP" ipv6 = false locked = false memory = 1024 monitoring = false name = "testing-terraform-0" price_hourly = 0.00744 price_monthly = 5 private_networking = false region = "fra1" resize_disk = true size = "s-1vcpu-1gb" status = "active" tags = [ "terraform-testing", ] urn = "DROPLET-URN" vcpus = 1 volume_ids = [] . . . }
您将在输出中看到两个资源及其属性。
将 Droplet 和防火墙导入 Terraform 状态后,您需要确保配置代表导入资产的当前状态。 为此,您将指定 Droplet 的 image
及其 size
。 您可以在 digitalocean_droplet.do_droplet
资源的 terraform show
输出中找到这两个值。
打开digitalocean_droplet.tf
文件:
nano digitalocean_droplet.tf
在本教程中:
- 现有 Droplet 使用的操作系统映像为
ubuntu-20-04-x64
。 - Droplet所在的区域是
fra1
。 - 现有 Droplet 的 Droplet 标签是
terraform-testing
。
注意:您的操作系统、区域、Droplet 大小和其他资源可能会有所不同,请务必更新文件以反映您的值。
为了确保 digitalocean_droplet.tf
中的配置与导入的 Droplet 的当前状态相匹配,需要将其更新为如下所示:
digitalocean_droplet.tf
resource "digitalocean_droplet" "do_droplet" { image = "ubuntu-20-04-x64" name = "testing-terraform" region = "fra1" size = "s-1vcpu-1gb" tags = ["terraform-testing"] }
在相关的情况下,更新配置以匹配您导入的 Droplet。
接下来,您将添加防火墙规则。 在我们的示例中,用于入站流量的开放端口是 22
、80
和 443
。 所有端口都为出站流量打开。 您可以根据您的开放端口相应地调整此配置。
打开digitalocean_firewall.tf
:
nano digitalocean_firewall.tf
添加以下配置:
digitalocean_firewall.tf
resource "digitalocean_firewall" "do_firewall" { name = "testing-terraform-firewall" tags = ["terraform-testing"] inbound_rule { protocol = "tcp" port_range = "22" source_addresses = ["0.0.0.0/0", "::/0"] } inbound_rule { protocol = "tcp" port_range = "80" source_addresses = ["0.0.0.0/0", "::/0"] } inbound_rule { protocol = "tcp" port_range = "443" source_addresses = ["0.0.0.0/0", "::/0"] } outbound_rule { protocol = "tcp" port_range = "all" destination_addresses = ["0.0.0.0/0", "::/0"] } outbound_rule { protocol = "udp" port_range = "all" destination_addresses = ["0.0.0.0/0", "::/0"] } outbound_rule { protocol = "icmp" destination_addresses = ["0.0.0.0/0", "::/0"] } }
这些规则复制现有示例防火墙的状态。 如果您想将流量限制到不同的 IP 地址、不同的端口或不同的协议,您可以调整文件以复制现有的防火墙。
保存并关闭文件。
更新 Terraform 文件后,您将使用 plan
命令查看您所做的更改是否复制了 DigitalOcean 上现有资产的状态。
terraform plan
命令用作试运行。 使用此命令,您可以检查 Terraform 将要进行的更改是否是您要进行的更改。 在应用更改之前始终运行此命令进行确认是个好主意。
使用以下命令运行 terraform plan
:
terraform plan -var "do_token=$DO_TOKEN"
如果未检测到任何更改,则输出将类似于以下内容:
OutputNo changes. Infrastructure is up-to-date.
如果检测到更改,Terraform 输出将显示它们以供您查看和相应调整。
您已在 Terraform 中成功导入现有 DigitalOcean 资产,现在您可以通过 Terraform 对基础架构进行更改,而不会出现意外删除或修改现有资产的风险。
第 4 步 - 通过 Terraform 创建新资产
在此步骤中,您将向现有基础架构添加两个额外的 Droplet。 以这种方式将资产添加到您现有的基础架构可能很有用,例如,如果您有一个实时网站并且不想在处理该网站时对该网站进行任何潜在的破坏性更改。 相反,您可以添加一个 Droplet 以用作开发环境,并在与生产 Droplet 相同的环境中处理您的项目,而没有任何潜在风险。
打开 digitalocean_droplet.tf
为您的新液滴添加规则:
nano digitalocean_droplet.tf
将突出显示的行添加到您的文件中:
digitalocean_droplet.tf
resource "digitalocean_droplet" "do_droplet" { image = "ubuntu-20-04-x64" name = "testing-terraform" region = "fra1" size = "s-1vcpu-1gb" tags = ["terraform-testing"] count = "1" } resource "digitalocean_droplet" "do_droplet_new" { image = "ubuntu-20-04-x64" name = "testing-terraform-${count.index}" region = "fra1" size = "s-1vcpu-1gb" tags = ["terraform-testing"] count = "2" }
您可以使用 count
元参数告诉 Terraform 需要多少具有相同规格的 Droplet。 当您指定与防火墙相同的标签时,这些新的 Droplet 也将添加到您现有的防火墙中。
应用这些规则来检查您在 digitalocean_droplet.tf
中指定的更改:
terraform plan -var "do_token=$DO_TOKEN"
验证您要进行的更改是否已复制到此命令的输出中。
您将看到类似于以下内容的输出:
. . . [secondary_label Output] # digitalocean_droplet.do_droplet_new[1] will be created + resource "digitalocean_droplet" "do_droplet_new" { + backups = false + created_at = (known after apply) + disk = (known after apply) + id = (known after apply) + image = "ubuntu-20-04-x64" + ipv4_address = (known after apply) + ipv4_address_private = (known after apply) + ipv6 = false + ipv6_address = (known after apply) + ipv6_address_private = (known after apply) + locked = (known after apply) + memory = (known after apply) + monitoring = false + name = "testing-terraform-1" + price_hourly = (known after apply) + price_monthly = (known after apply) + private_networking = true + region = "fra1" + resize_disk = true + size = "s-1vcpu-1gb" + status = (known after apply) + tags = [ + "terraform-testing", ] + urn = (known after apply) + vcpus = (known after apply) + volume_ids = (known after apply) } Plan: 2 to add, 1 to change, 0 to destroy.
对输出感到满意后,使用 terraform apply
命令将您指定的更改应用于配置状态:
terraform apply -var "do_token=$DO_TOKEN"
通过在命令行输入 yes
确认更改。 成功执行后,您将看到类似以下的输出:
Output. . . digitalocean_droplet.do_droplet_new[1]: Creating... digitalocean_droplet.do_droplet_new[0]: Creating... digitalocean_firewall.do_firewall[0]: Modifying... [id=FIREWALL-ID] digitalocean_firewall.do_firewall[0]: Modifications complete after 1s [id=FIREWALL-ID] digitalocean_droplet.do_droplet_new[0]: Still creating... [10s elapsed] digitalocean_droplet.do_droplet_new[1]: Still creating... [10s elapsed] digitalocean_droplet.do_droplet_new[0]: Creation complete after 16s [id=DROPLET-ID] digitalocean_droplet.do_droplet_new[1]: Still creating... [20s elapsed] digitalocean_droplet.do_droplet_new[1]: Creation complete after 22s [id=DROPLET-ID] Apply complete! Resources: 2 added, 1 changed, 0 destroyed.
您将在 DigitalOcean Web 面板中看到两个新的 Droplet:
您还将看到它们附加到您现有的防火墙:
您已使用现有资产通过 Terraform 创建了新资产。 要了解如何销毁这些资产,您可以选择完成下一步。
第 5 步 — 销毁导入和创建的资产(可选)
在此步骤中,您将使用 Terraform 的 destroy
选项销毁已导入和创建的资产。
要销毁由 Terraform 处理的资产,请执行以下命令:
terraform destroy -var "do_token=${DO_TOKEN}"
Terraform 将要求您确认是否要销毁 Droplet 和防火墙。 这将破坏您通过 Terraform 导入和创建的所有资产,因此请确保您希望在键入 yes
之前继续。
输出将类似于以下内容:
Output. . . digitalocean_droplet.do_droplet[0]: Destroying... [id=YOUR-DROPLET-ID]] digitalocean_droplet.do_droplet_new[0]: Destroying... [id=YOUR-DROPLET-ID] digitalocean_droplet.do_droplet_new[1]: Destroying... [id=YOUR-DROPLET-ID] digitalocean_firewall.do_firewall[0]: Destroying... [id=YOUR-FIREWALL-ID] digitalocean_firewall.do_firewall[0]: Destruction complete after 1s digitalocean_droplet.do_droplet_new[1]: Still destroying... [id=YOUR-DROPLET-ID, 10s elapsed] digitalocean_droplet.do_droplet[0]: Still destroying... [id=YOUR-DROPLET-ID, 10s elapsed] digitalocean_droplet.do_droplet_new[0]: Still destroying... [id=YOUR-DROPLET-ID, 10s elapsed] digitalocean_droplet.do_droplet_new[1]: Still destroying... [id=YOUR-DROPLET-ID, 20s elapsed] digitalocean_droplet.do_droplet_new[0]: Still destroying... [id=YOUR-DROPLET-ID, 20s elapsed] digitalocean_droplet.do_droplet[0]: Still destroying... [id=YOUR-DROPLET-ID, 20s elapsed] digitalocean_droplet.do_droplet_new[1]: Destruction complete after 22s digitalocean_droplet.do_droplet[0]: Destruction complete after 22s digitalocean_droplet.do_droplet_new[0]: Destruction complete after 22s Apply complete! Resources: 0 added, 0 changed, 4 destroyed.
您已成功删除 Terraform 管理的所有资产。
结论
在本教程中,您安装了 Terraform,导入了现有资产,创建了新资产,并有选择地销毁了这些资产。 您可以将此工作流扩展到更大的项目,例如部署生产就绪的 Kubernetes 集群。 使用 Terraform,您可以管理所有节点、DNS 条目、防火墙、存储和其他资产,还可以使用版本控制来跟踪更改并与团队协作。
要探索其他 Terraform 功能,请阅读他们的 文档。 你也可以阅读 DigitalOcean 的 Terraform 内容更多教程和问答。