当前位置: 首页 > 知识库问答 >
问题:

Terraform:如何多次运行远程执行?

鲁涵意
2023-03-14

我注意到terraform只会在资源上运行“file”、“remote exec”或“local exec”一次。一旦资源被调配,如果“远程执行”中的命令被更改,或者调配器“文件”中的文件被更改,则terraform将不会对实例进行任何更改。那么,如何让terraform在每次运行terraform应用时都运行provisioner“file”、“remote exec”或“local exec”?

有关更多详细信息:

通常,由于“remote exec”的错误导致terraform停止(主要是因为我在编写脚本时输入了错误的命令),我会部分配置资源。在此之后再次运行terraform将导致先前创建的资源被破坏,并迫使terraform从头开始创建新资源。这也是我可以在资源上运行“远程执行”两次的唯一方法。。。通过从头开始创建。

这确实是terraform相对于ansible的一个缺点,ansible可以做与terraform相同的工作,只是它是完全幂等的。当将Ansible与“ec2”、“shell”和“copy”等任务一起使用时,我可以实现与terraform相同的任务,但这些任务中的每一个都是幂等的。Ansible将自动识别何时不需要进行更改,在何处进行更改,因此它可以在不破坏一切并从头开始的情况下,重新选择失败的Ansible剧本。Terraform缺少此功能。

这里是一个简单的地形资源块,用于同时使用“远程执行”和“文件”供应器的ec2实例:

resource "aws_instance" "test" {

count = ${var.amt}
ami = "ami-2d39803a"
instance_type = "t2.micro"
key_name = "ansible_aws"
tags {
  name = "test${count.index}"
}

#creates ssh connection to consul servers
connection {
  user = "ubuntu"
  private_key="${file("/home/ubuntu/.ssh/id_rsa")}"
  agent = true
  timeout = "3m"
} 

provisioner "remote-exec" {
  inline = [<<EOF

    sudo apt-get update
    sudo apt-get install curl unzip
    echo hi

  EOF
  ]
}

#copying a file over
provisioner "file" {
  source = "scripts/test.txt"
  destination = "/path/to/file/test.txt"
}

}

共有3个答案

洪浩
2023-03-14

您可以使用“污染”命令将资源标记为已污染,强制在下一次应用时将其销毁并重新创建。

贡烨烁
2023-03-14

Terraform明确规定,它将基本引导的供应器的使用视为一次性任务,不应将其用作适当配置管理工具的替代品,例如Ansible:

供应器仅在创建资源时运行。它们不是配置管理和更改已经运行的服务器的软件的替代品,而是引导服务器的一种方式。对于配置管理,您应该使用Terraform配置来调用真正的配置管理解决方案。

如果资源成功创建但在提供过程中失败,Terraform将出错并将资源标记为“受污染”已实际创建受污染的资源,但由于资源调配失败,因此不能认为该资源是安全的。

当您生成下一个执行计划时,Terraform将删除任何受污染的资源并创建新资源,尝试再次预配。它不会尝试重新启动同一资源的预配,因为它不能保证是安全的。

当失败发生时,Terraform不会在应用过程中自动回滚并销毁资源,因为这将违反执行计划:执行计划会说将创建一个资源,但不会说它将被删除。但是,如果您使用受污染的资源创建了一个执行计划,该计划将清楚地说明该资源将被破坏,因为它受到污染。

预配对于能够引导实例很重要。作为另一个提醒,它不能替代配置管理。它旨在简单地引导机器。如果您使用配置管理,您应该使用预配作为引导配置管理实用程序的一种方式。

将供应器视为类似于EC2用户数据脚本,因为它在创建时只运行一次,如果失败,则需要销毁实例并重试。

这样做的好处是Terraform不需要了解如何在操作系统上使更改幂等,因为Terraform在比实例本身更高的级别上工作,更多的是在配置整个数据中心。

如果您需要更大的灵活性,那么可以考虑使用Terraform调用配置管理系统来正确配置实例(然后允许重试,如果它失败,则与Terraform配置阶段分离),或者使用编排工具(如Jenkins)包装Terraform和替代配置管理工具(如Ansible)。

另一种选择是沿着不可变基础设施的路线走得更远,使用Packer使用Anable或其他工具创建AMI,然后只需使用Terraform按原样部署AMI,而无需进一步配置实例。

洪浩
2023-03-14

在我的搜索中遇到了这条线索,并最终找到了解决方案:

resource "null_resource" "ansible" {

  triggers {
    key = "${uuid()}"
  }

  provisioner "local-exec" {
  command = "ansible-playbook -i /usr/local/bin/terraform-inventory -u ubuntu playbook.yml --private-key=/home/user/.ssh/aws_user.pem -u ubuntu"
  }
}

您可以使用对每个地形运行都是唯一的uuid()来触发空资源或预配器。

 类似资料:
  • 问题内容: 如何执行网站上的python脚本?例如,以下似乎有效。但这是正确的方法吗? 我想知道是否可以从python命令提示符>>>导入网页。 问题答案: 好吧,你可以这样做: 但是,如果您确实在执行此操作,则将它或将其导入本地计算机肯定更有意义,然后正常导入该模块。

  • 问题内容: 防止Linux程序/守护程序在给定时间多次执行的最佳方法是什么? 问题答案: 最常见的方法是创建PID文件:定义文件将要到达的位置(在/ var / run内部很常见)。成功启动后,您会将PID写入此文件。在决定是否启动时,请阅读文件并检查以确保所引用的进程不存在(或者如果存在,则它不是守护程序的实例:在Linux上,您可以查看)。关机时,您可以删除文件,但这不是绝对必要的。 有一些脚

  • 问题内容: 我想使用Python连接到远程服务器并在其上执行一个过程。我希望能够获得该过程的返回码和stderr(如果有)。以前有没有人做过这样的事情。我已经用ssh完成了,但是我想从Python脚本中完成。 干杯。 问题答案: 好吧,您可以从python调用ssh …

  • 我有一个TestNG XML,格式如下: 这个套件有两个类,每个类都有一些@Test方法。现在我想让我的套件以同样的顺序再运行3次,就像它运行一样,即所有的class1方法,然后是class2方法。我怎样才能做到这一点?我正在使用Selenium WebDriver和核心Java来运行我的自动化套件。

  • 问题内容: 我有一些关于jsfiddle的演示: HTML: JavaScript: 输入更改(甚至复选框)时,将调用日志过滤器。 仅当文本输入更改时,如何更改它并触发日志过滤器? 问题答案: 这是因为即使范围中的一个变量发生更改,Angular也会运行并更新所有范围属性。这称为“脏污检查”。 了解有关角度工作原理的更多信息:http : //www.sitepoint.com/understan