是否可以使用 terraform 创建 GCP 资源而无需每次更改 main.tf & varaible.tf?

Is it possible to create GCP resources using terraform without changing main.tf & varaible.tf everytime?

共享示例用于创建 GCP VM。这里的目标是在一个项目中创建 5 个不同的虚拟机,而不是每次都更改 main.tf & varaible.tf。当我第一次申请 terraform 时,我能够使用以下模块成功创建一个 VM,但是要创建另一个 VM - 我正在做的是更新 new VM “名称” 在 variables.tfvars。然后当我应用 terraform 时,TF 正在删除在第一个 运行 中创建的现有 VM,然后尝试创建一个新的 VM。但我的目标是拥有一个模块,我不应该每次都更改 main.tf & varaible.tf 并创建不同的虚拟机。这可以通过 terraform 或任何可能的解决方案实现吗?

main.tf

resource "google_compute_instance" "default" {
  project      = var.project
  name         = var.name
  machine_type = var.machine-type
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-9"
      }
      disk_encryption_key_raw = "5DPzBhkLSfXk8kg="
}

  network_interface {
    subnetwork_project = var.host_project_id
    subnetwork = var.subnet_name
  }

  metadata = {
    block-project-ssh-keys = true,
    enable-oslogin         = true,
    serial-port-enable     = false
  }

  metadata_startup_script = "sudo apt-get update && sudo apt-get install apache2 -y && echo '<!doctype html><html><body><h1>our collaborative problem-solving ability, and the warm professionalism of our teams.!</h1></body></html>' | sudo tee /var/www/html/index.html"

  // Apply the firewall rule to allow external IPs to access this instance
  tags = ["http-server"]
}

variable.tf

variable "name" {
  type = string
  description = "Name of the instance"
}

variable "machine-type" {
  type        = string
  description = "Machine type of the instance"
}

variable "region" {
  type = string
  description = "Region in which the instance has to be created"
}

variable "zone" {
  type        = string
  description = "Zone in which the instance has to be created"
}

variable "project" {
  type = string
  description = "Name of the project"
}

variable "network" {
  type = string
  description = "Name of the subnet"
}

variable "host_project_id" {
  type = string
  description = "Name of the host project for network"
}

variable "subnet_name" {
  type = string
  description = "Name of the subnet"
}

variables.tfvars

name            = "test-2"
machine-type    = "n1-standard-4"
region          = "us-east4"
zone            = "us-east4-a"
project         = "demoapp"
network         = "https://www.googleapis.com/compute/v1/projects/network-dev/global/networks/vpc-1"
host_project_id = "network-dev"
subnet_name     = "subnet-1"

根据以下评论创建了文件夹结构模块,但在删除过程中遇到问题。

project
|-- sa-01
|   `-- variable.tfvars
|-- sa-02
|   `-- variable.tfvars
|-- main.tf
`-- variables.tf

sa-01/variables.tfvars

sa_name         = ["sa-test1","sa-test2","sa-test3"]

sa_dis_name     = ["sa-test1","sa-test2","sa-test3"]

sa-02/variables.tfvars

sa_name         = ["sa-test1","sa-test2","sa-test3"]

sa_dis_name     = ["sa-test1","sa-test2","sa-test3"]

main.tf

resource "google_service_account" "sa_npe_policy" {
  count        = "${length(var.sa_name)}"
  project      = "tools-npe"
  account_id   = "${element(var.sa_name, count.index)}"
  display_name = "${element(var.sa_dis_name, count.index)}"
}

variables.tf

variable sa_name {
    type        = list(string)
    description = "SA Name"
}

variable sa_dis_name {
    type        = list(string)
    description = "SA Display Name"
}

有多种方法可以实现这一点,每种方法各有利弊...

多个.tfvars个文件和多个.tfstate个文件

您定义了多个变量文件,一个用于您的每个 VM 也就是环境。应用 terraform 定义时,必须指定要使用的变量文件以及存储此 terraform 配置的状态文件的位置:

terraform apply -var-file=./env1/terraform.tfvars -state ./env1/env1.tfstate

我建议将每个环境的变量文件和状态文件一起存储在一个专用文件夹中。在这种情况下,您最终会得到如下文件夹结构:

project
|-- env1
|   |-- env1.tfstate
|   `-- terraform.tfvars
|-- env2
|   |-- env2.tfstate
|   `-- terraform.tfvars
|-- env3
|   |-- env3.tfstate
|   `-- terraform.tfvars
|-- main.tf
`-- variables.tf

专业版

  • 接近我所理解的您的要求。
  • 可能适合 KISS solution 家庭使用。

Con

  • 在上述设置中,您会将所有 VM 的变量定义与模块定义(您的 *.tf 文件)一起存储在一个存储库中。
  • 虽然您当然可以将游览变量文件存储在单独的存储库中而不是子文件夹中,但我想这种结构很快就会变得混乱。

注意事项:如果您在 terraform 中使用本地后端,这很有效。我没有用远程后端测试它,但我认为它需要进一步改进。


使用模块

您只用 main.tfvariables.tf 创建了一个模块文件夹,但没有 variables.tfvars。您为每个虚拟机创建一个单独的文件夹,每个虚拟机都有自己的 main.tf,其中包括您的模块,如下所示:

module "vm" {
  source = "../path/to/your/module"
  # or: source = "git::https://github.com/yourorg/yourrepo//path/to/your/module"


  name            = "test-2"
  machine-type    = "n1-standard-4"
  region          = "us-east4"
  zone            = "us-east4-a"
  project         = "demoapp"
  network         = "https://www.googleapis.com/compute/v1/projects/network-dev/global/networks/vpc-1"
  host_project_id = "network-dev"
  subnet_name     = "subnet-1"
}

专业版

  • 立即与远程后端一起工作。
  • 您可以将不同 vms/environments/projects 的基础参数彼此分开,并与模块定义分开。

Con

  • 可能会偏离您的预期解决方案。

Terraform 工作区

总的来说Terraform Workspaces也可能是解决这个问题的一种手段,所以为了完整起见,我只是想提一下。但是,我认为它们更适合您需要在不同阶段(开发、测试、生产)或区域等管理等效环境的用例。