如何将现有DigitalOcean资产导入Terraform

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。

介绍

Terraform 是由 HashiCorp 创建的基础架构即代码工具,可帮助开发人员以高效且可扩展的方式部署、更新和删除其基础架构的不同资产。

开发人员可以使用 Terraform 组织不同的环境,通过版本控制跟踪更改,并自动执行重复性工作以限制人为错误。 它还为团队提供了一种通过共享配置协作改进其基础架构的方式。

在本教程中,您将把现有的 DigitalOcean 基础设施导入 Terraform。 在本教程结束时,除了创建新资产外,您将能够将 Terraform 用于所有现有基础设施。

先决条件

本教程使用 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 showterraform 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。

接下来,您将添加防火墙规则。 在我们的示例中,用于入站流量的开放端口是 2280443。 所有端口都为出站流量打开。 您可以根据您的开放端口相应地调整此配置。

打开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 内容更多教程和问答。