我注意到terraform只会在资源上运行一次“file”,“remote-exec”或“local-exec” . 一旦资源被配置,如果“remote-exec”中的命令被更改或者来自供应者“file”的文件被更改,则terraform将不对该实例进行任何更改 . 那么每次运行terraform时,如何让terraform运行供应商“file”,“remote-exec”或“local-exec”?
For more details:
由于“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"
}
}
3 回答
Terraform docs on provisioning明确表示它认为使用供应商进行基本引导作为一次性任务,并且它不应该用作适当的配置管理工具(如Ansible)的替代品:
和
将配置器视为类似于EC2用户数据脚本,因为它只在创建时运行一次,如果失败,则需要销毁该实例并再次尝试 .
这样做的好处是,Terraform不需要知道如何在操作系统上使更改具有幂等性,因为Terraform的工作级别高于实例本身,而且更多的是配置整个数据中心 .
如果您需要比此更多的灵活性,那么考虑使用Terraform调用配置管理系统来正确配置实例(然后允许重试,如果失败,与Terraform配置阶段分离)或使用诸如Jenkins之类的编排工具包装Terraform和替代配置管理工具,如Ansible .
另一个选择是沿着不可变基础设施的路线前进,并使用Packer使用Ansible或其他工具创建AMI,然后只使用Terraform按原样部署AMI,而无需进一步配置实例 .
在我的搜索中遇到了这个帖子并最终找到了一个解决方案:
您可以使用每个terraform运行独有的uuid()来触发空资源或配置器 .
您可以使用taint命令将资源标记为受污染,强制将其销毁并在下一次应用时重新创建 .