为什么terraform + apt-get会间歇性地失败?

RaG*_*aGe 2 amazon-ec2 apt-get amazon-web-services terraform amazon-ami

我正在使用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"
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

当我说count = 4时,某些节点间歇性地失败,并出现apt-get错误,例如:

aws_instance.myapp.1 (remote-exec): E: Unable to locate package awscli
Run Code Online (Sandbox Code Playgroud)

而其他3个节点发现awcli很好。现在,所有节点都是从同一AMI创建的,使用完全相同的配置命令,为什么只有其中一部分会失败?变化可能来自:

  • 亚马逊上的AMI的多个副本不相同
  • 多个不一样的apt-get镜像

哪个更有可能?还有其他可能性吗?
我是否可以使用apt-get“强制”类型标志来使配置更加可重复?

通过脚本自动配置的全部目的是避免节点之间的这种变化:/

wkl*_*wkl 6

remote-execTerraform的预配功能只是生成上传到新的实例并运行指定的命令shell脚本。您很可能实际上遇到了cloud-init配置为在标准Ubuntu AMI上运行的问题,并且预配程序在运行时cloud-init也尝试运行,因此您遇到了时间安排/冲突。

您可以让脚本等到预配cloud-init完成之后。 cloud-init在中创建一个文件/var/lib/cloud/instance/boot-finished,因此您可以将此内容与您的供应商内联:

until [[ -f /var/lib/cloud/instance/boot-finished ]]; do
  sleep 1
done
Run Code Online (Sandbox Code Playgroud)

另外,您可以利用cloud-init它并为您安装任意软件包。您可以user-data像在Terraform中一样为您的实例指定(从上面的代码段进行修改):

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
    }
}
Run Code Online (Sandbox Code Playgroud)