为什么 terraform + apt-get 会间歇性地失败?
Why does terraform + apt-get fail, intermittently?
我正在使用 terraform 在 aws 上创建多个 ec2 节点:
resource "aws_instance" "myapp" {
count = "${var.count}"
ami = "${data.aws_ami.ubuntu.id}"
instance_type = "m4.large"
vpc_security_group_ids = ["${aws_security_group.myapp-security-group.id}"]
subnet_id = "${var.subnet_id}"
key_name = "${var.key_name}"
iam_instance_profile = "${aws_iam_instance_profile.myapp_instance_profile.id}"
connection {
user = "ubuntu"
private_key = "${file("${var.key_file_path}")}"
}
provisioner "remote-exec" {
inline = [
"sudo apt-get update",
"sudo apt-get upgrade -y",
"sudo apt-get install -f -y openjdk-7-jre-headless git awscli"
]
}
}
当我 运行 说 count=4 时,一些节点间歇性失败并出现 apt-get 错误,例如:
aws_instance.myapp.1 (remote-exec): E: Unable to locate package awscli
而其他 3 个节点发现 awscli 很好。现在所有节点都是从同一个 AMI 创建的,使用完全相同的配置命令,为什么只有其中一些会失败?变化可能来自:
- 亚马逊上的多个 AMI 副本,它们并不相同
- 多个不相同的 apt-get 镜像
哪个更有可能?还有其他我遗漏的可能性吗?
是否有我可以使用的 apt-get "force" 类型标志,它会使供应更可重复?
通过脚本自动配置的全部意义在于避免节点之间的这种差异:/
Terraform 的 remote-exec
供应器功能仅生成一个 shell 脚本上传到新实例和 运行 您指定的命令。很可能您实际上 运行 遇到了 cloud-init
的问题,它在标准 Ubuntu AMI 上配置为 运行,并且供应商正在尝试 运行 同时cloud-init
也是 运行ning,所以你 运行ning 变成了 timing/conflict。
您可以让您的脚本等到 cloud-init
完成配置之后。 cloud-init
在 /var/lib/cloud/instance/boot-finished
中创建一个文件,因此您可以将其与您的供应商内联:
until [[ -f /var/lib/cloud/instance/boot-finished ]]; do
sleep 1
done
或者,您可以利用 cloud-init
并获得它 install arbitrary packages for you。您可以像在 Terraform 中那样为您的实例指定 user-data
(从上面的代码段修改):
resource "aws_instance" "myapp" {
count = "${var.count}"
ami = "${data.aws_ami.ubuntu.id}"
instance_type = "m4.large"
vpc_security_group_ids = ["${aws_security_group.myapp-security-group.id}"]
subnet_id = "${var.subnet_id}"
key_name = "${var.key_name}"
iam_instance_profile = "${aws_iam_instance_profile.myapp_instance_profile.id}"
user_data = "${data.template_cloudinit_config.config.rendered}"
}
# Standard cloud-init stuff
data "template_cloudinit_config" "config" {
# I've
gzip = false
base64_encode = false
part {
content_type = "text/cloud-config"
content = <<EOF
packages:
- awscli
- git
- openjdk-7-headless
EOF
}
}
我正在使用 terraform 在 aws 上创建多个 ec2 节点:
resource "aws_instance" "myapp" {
count = "${var.count}"
ami = "${data.aws_ami.ubuntu.id}"
instance_type = "m4.large"
vpc_security_group_ids = ["${aws_security_group.myapp-security-group.id}"]
subnet_id = "${var.subnet_id}"
key_name = "${var.key_name}"
iam_instance_profile = "${aws_iam_instance_profile.myapp_instance_profile.id}"
connection {
user = "ubuntu"
private_key = "${file("${var.key_file_path}")}"
}
provisioner "remote-exec" {
inline = [
"sudo apt-get update",
"sudo apt-get upgrade -y",
"sudo apt-get install -f -y openjdk-7-jre-headless git awscli"
]
}
}
当我 运行 说 count=4 时,一些节点间歇性失败并出现 apt-get 错误,例如:
aws_instance.myapp.1 (remote-exec): E: Unable to locate package awscli
而其他 3 个节点发现 awscli 很好。现在所有节点都是从同一个 AMI 创建的,使用完全相同的配置命令,为什么只有其中一些会失败?变化可能来自:
- 亚马逊上的多个 AMI 副本,它们并不相同
- 多个不相同的 apt-get 镜像
哪个更有可能?还有其他我遗漏的可能性吗?
是否有我可以使用的 apt-get "force" 类型标志,它会使供应更可重复?
通过脚本自动配置的全部意义在于避免节点之间的这种差异:/
Terraform 的 remote-exec
供应器功能仅生成一个 shell 脚本上传到新实例和 运行 您指定的命令。很可能您实际上 运行 遇到了 cloud-init
的问题,它在标准 Ubuntu AMI 上配置为 运行,并且供应商正在尝试 运行 同时cloud-init
也是 运行ning,所以你 运行ning 变成了 timing/conflict。
您可以让您的脚本等到 cloud-init
完成配置之后。 cloud-init
在 /var/lib/cloud/instance/boot-finished
中创建一个文件,因此您可以将其与您的供应商内联:
until [[ -f /var/lib/cloud/instance/boot-finished ]]; do
sleep 1
done
或者,您可以利用 cloud-init
并获得它 install arbitrary packages for you。您可以像在 Terraform 中那样为您的实例指定 user-data
(从上面的代码段修改):
resource "aws_instance" "myapp" {
count = "${var.count}"
ami = "${data.aws_ami.ubuntu.id}"
instance_type = "m4.large"
vpc_security_group_ids = ["${aws_security_group.myapp-security-group.id}"]
subnet_id = "${var.subnet_id}"
key_name = "${var.key_name}"
iam_instance_profile = "${aws_iam_instance_profile.myapp_instance_profile.id}"
user_data = "${data.template_cloudinit_config.config.rendered}"
}
# Standard cloud-init stuff
data "template_cloudinit_config" "config" {
# I've
gzip = false
base64_encode = false
part {
content_type = "text/cloud-config"
content = <<EOF
packages:
- awscli
- git
- openjdk-7-headless
EOF
}
}