2017-02-16 2 views
1

ich Terraforming bin mit mutiple EC2 Knoten auf aws zu erstellen:Warum scheitert Terraform + apt-get intermittierend?

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" 
     ] 
    } 
} 

Wenn ich laufen diese Zählung = 4 sagen mit, wie einige Knoten intermittierend mit fehler apt-get Fehler:

aws_instance.myapp.1 (remote-exec): E: Unable to locate package awscli 

während die anderen 3 Knoten awscli einfach gut gefunden. Jetzt werden alle Knoten vom selben AMI erstellt, verwenden Sie genau die gleichen Provisionierungsbefehle, warum würden nur einige von ihnen scheitern? Die Änderung könnte möglicherweise kommen aus:

  • Mehrere Kopien von Ami auf amazon, die
  • Mehrere apt-get Spiegel nicht identisch sind, die

nicht identisch sind, die wahrscheinlicher ist? Irgendwelche anderen Möglichkeiten, die ich vermisse?
Gibt es ein apt-get "force" -Flag, den ich verwenden kann, um die Bereitstellung wiederholbarer zu machen?

Der ganze Sinn der Bereitstellung über Skripte automatisieren ist diese Art der Variation zwischen den Knoten zu vermeiden:/

Antwort

4

Das remote-exec provisioner Merkmal Terraforming nur eine Shell-Skript erzeugt, das auf die neue Instanz hochgeladen und führt die Befehle, die Sie angeben. Höchstwahrscheinlich stößt man tatsächlich auf Probleme mit cloud-init, die für die Ausführung auf Standard Ubuntu AMIs konfiguriert ist, und der Provisioner versucht zu laufen, während cloud-init läuft auch, so dass Sie in ein Timing/Konflikt geraten.

Sie können Ihr Skript warten lassen, bis nach cloud-init die Bereitstellung abgeschlossen ist. cloud-init erstellt eine Datei in /var/lib/cloud/instance/boot-finished, so können Sie diese inline mit Ihren provisioner setzen:

until [[ -f /var/lib/cloud/instance/boot-finished ]]; do 
    sleep 1 
done 

Alternativ können Sie die Vorteile von cloud-init nehmen und haben es install arbitrary packages for you. Sie können user-data für die Instanz angeben, wie so in Terraforming (modifiziert aus dem Snippet oben):

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 
    } 
} 
+0

warten auf 'boot-finished' scheint für mich zu arbeiten. – RaGe