我注意到terraform只会在资源上运行一次“file”,“remote-exec”或“local-exec”。一旦资源被配置,如果“remote-exec”中的命令被更改或者来自供应者“file”的文件被更改,则terraform将不会对实例进行任何更改。那么每次运行terraform时,如何让terraform运行供应商“file”,“remote-exec”或“local-exec”?
有关详细信息:
由于“remote-exec”错误导致terraform停止(部分由于我在编写脚本时输入了错误的命令),我经常部署资源。在此之后再次运行terraform将导致先前创建的资源被破坏并强制terraform从头开始创建新资源。这也是我可以在资源上运行两次“remote-exec”的唯一方法......从头开始创建它。
对于terraform来说,这确实是一个缺点,而不是ansible,它可以做与terraform完全相同的工作,除了它完全是幂等的。当使用Ansible执行诸如“ec2”,“shell”和“copy”之类的任务时,我可以完成与terraform相同的任务,只有每个任务都是幂等的。 Ansible会自动识别何时不需要进行更改,它会在何处进行更改,因此可以自动识别失败的ansible-playbook停止的位置而不会破坏所有内容并从头开始。 Terraform缺乏此功能。
这里是一个简单的terraform资源块,供ec2实例使用“remote-exec”和“file”配置器:
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"
}
}
答案 0 :(得分:19)
在我的搜索中遇到了这个帖子并最终找到了解决方案:
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"
}
}
您可以使用每个terraform运行独有的uuid()来触发空资源或配置器。
答案 1 :(得分:6)
Terraform docs on provisioning显式地认为使用供应商进行基本引导作为一次性任务,并且它不应该用作替代适当的配置管理工具,例如Ansible:
仅在创建资源时运行配置程序。他们不是 替换配置管理和更改软件 一个已经运行的服务器,而只是作为一种方式 引导服务器。对于配置管理,您应该使用 Terraform配置以调用实际配置管理 溶液
和
如果资源成功创建但在提供期间失败, Terraform将出错并将资源标记为“受污染”。资源 被污染的是物理创造的,但不能被考虑 由于配置失败,因此可以安全使用。
当您生成下一个执行计划时,Terraform将删除任何计划 污染资源并创造新资源,试图提供资源 再次。它不会尝试重新启动配置 资源,因为它不能保证安全。
Terraform不会自动回滚并销毁资源 在失败发生时的申请期间,因为那会发生 反对执行计划:执行计划会说a 将创建资源,但不会说它将被删除。 但是,如果您使用受污染的资源创建执行计划,则计划 将清楚地说明资源将被销毁,因为它是 污点。
配置对于能够引导实例非常重要。如 另一个提醒,它不是配置的替代品 管理。它只是为了引导机器。如果你使用 配置管理,您应该使用配置作为一种方式 引导配置管理实用程序。
将配置程序视为类似于EC2用户数据脚本,因为它只在创建时运行一次,如果失败,则需要销毁该实例并重试。
这样做的好处是,Terraform不需要知道如何在操作系统上使更改具有幂等性,因为Terraform的工作级别高于实例本身,而且更多的是配置整个数据中心。 / p>
如果您需要比此更多的灵活性,那么考虑使用Terraform调用配置管理系统来正确配置实例(如果失败则允许重试,与Terraform配置阶段分离)或使用业务流程工具例如Jenkins用于包装Terraform和另一种配置管理工具,例如Ansible。
另一个选择是更多地沿着不可变基础设施的路线,并使用Packer使用Ansible或其他工具创建AMI,然后只需使用Terraform按原样部署AMI,而无需进一步提供实例。
答案 2 :(得分:2)
您可以使用taint
命令将资源标记为受污染,强制将其销毁并在下次应用时重新创建。
答案 3 :(得分:0)
Chris Holmes 的类似答案,但使用时间戳,您需要从 Chris 的答案中删除 UUID 或 timestamp() 周围的 ${""},因为现在您将收到以下消息:< /p> <块引用>
警告:不推荐使用仅插值表达式
除非您使用 Terraform 0.11 或更早版本。
clip.resize(1920,1080)