Terraform 和更新

Terraform and Updates

能够在单个 Terraform 文件中捕获基础设施具有明显的优势。但是,我不清楚如何 - 例如,一旦创建了虚拟机 - 后续 更新是如何处理的。

所以,提供一个具体的场景。假设我们使用 Terraform 设置了一个带有 SQL Server 2014 的 Azure 虚拟机。然后,一个月后我们决定我们应该使用 SQL Server 2014 的最新服务包更新该虚拟机,它刚刚被释放。

我们更新 Terraform 配置文件并重新应用是推荐的做法吗?

Terraform 不适合此类任务。 Terraform 是一种基础架构管理工具,而不是配置管理工具。

你应该使用chef、puppet、ansible等工具来处理系统的配置。

如果您必须为此任务使用 terraform;您可以创建一个 template_file 资源并放置在安装 SQL 服务器所需的配置中,以及如何在出现不同版本时进行升级。参考:here

将该代码放在 null_resource 资源下的 provisioner 中。参考:here.
触发器可能是包含 SQL 版本的变量。因此,当您提供不同版本的 SQL 时,它将在每个实例上执行该配置程序以升级版本。

Terraform 是一种基础设施配置工具,configuration/deployment 工具将是:

  • 厨师
  • 盐堆
  • ansible
  • 等等,

由于我与 Chef 一起工作,所以基本上,我通过 Terraform 提供服务器实例,然后 Terraform (terraform provisioner) 将控制权交给 Chef 以进行系统配置和部署。

目前terraform无法删除chef server中的node/client,所以在你terraform destroy之后,你需要自己删除它们。

我不同意其他两个回答。 Terraform 可以很好地处理基础设施更新。然而,要了解的关键是 Terraform 在很大程度上遵循 不可变基础架构 范例,这意味着对于 "update" 资源,您删除旧资源并创建新资源替换它。这很像函数式编程,其中变量是不可变的,"update" 某些东西,你实际上创建了一个新变量。

Terraform 的典型模式是使用它来部署 服务器映像 ,例如虚拟机 (VM) 映像(例如 Amazon Machine Image (AMI)) or a Container Image (e.g. a Docker Image)。当你想要 "update" 某些东西时,你可以创建一个新版本的图像,将其部署到新服务器上,然后取消部署旧服务器。

这是一个工作原理示例:

假设您正在 Rails 应用上构建一个 Ruby。您让应用程序在开发中运行,是时候部署到生产环境了。第一步是将应用程序打包为 AMI。您可以使用像 Packer 这样的工具来完成此操作。现在您有一个 ID 为 ami-1234 的 AMI。

这是一个 Terraform 模板,您可以使用它在服务器上部署此 AMI(EC2 Instance) in AWS with an Elastic IP Address 附加到它:

resource "aws_instance" "example" {
  ami = "ami-1234"
  instance_type = "t2.micro"
}

resource "aws_eip" "example" {
  instance = "${aws_instance.example.id}"
}

当您 运行 terraform apply 时,Terraform 部署服务器,为其附加一个 IP 地址,现在当用户访问该 IP 时,他们将看到您的 Rails 应用程序的 v1 .

一段时间后,您更新了 Rails 应用并希望部署新版本 v2。为此,您构建一个新的 AMI(即您再次 运行 Packer)以获得 ID 为 "ami-5678" 的 ami。您相应地更新您的 Terraform 模板:

resource "aws_instance" "example" {
  ami = "ami-5678"
  instance_type = "t2.micro"
}

当您 运行 terraform apply 时,Terraform 取消部署旧服务器(它可以找到因为 Terraform records the state of your infrastructure),使用新 AMI 部署新服务器,现在用户将看到您的代码在同一 IP 的 v2。

当然,这里有一个问题:在 Terraform 取消部署 v1 和部署 v2 之间,您的用户会看到停机时间。要解决此问题,您可以使用 Terraform 的 create_before_destroy 生命周期设置:

resource "aws_instance" "example" {
  ami = "ami-5678"
  instance_type = "t2.micro"

  lifecycle {
    create_before_destroy = true
  }
}

create_before_destroy 设置为 true,Terraform 将首先创建替换服务器,将 IP 切换到它,然后删除旧服务器。这允许您使用不可变的基础设施进行零停机部署(注意:零停机部署与可以进行健康检查的负载平衡器比简单的 IP 地址更有效,特别是如果您的服务器需要很长时间才能启动)。

有关这方面的更多信息,请查看本书 Terraform: Up & Running. The code samples for the book include an example of a zero-downtime deployment with a cluster of servers and a load balancer: https://github.com/brikis98/terraform-up-and-running-code