resource "aws_launch_configuration" "someapp" {
lifecycle { create_before_destroy = true }
image_id = "${var.ami}"
instance_type = "${var.instance_type}"
key_name = "${var.key_name}"
security_group = ["${var.security_group}"]
}
resource "aws_autoscaling_group" "someapp" {lifecycle { create_before_destroy = true }name = "someapp - ${aws_launch_configuration.someapp.name}"launch_configuration = "${aws_launch_configuration.someapp.name}"desired_capacity = "${var.nodes}"min_size = "${var.nodes}"max_size = "${var.nodes}"min_elb_capacity = "${var.nodes}"availability_zones = ["${split(",", var.azs)}"]vpc_zone_identifier = ["${split(",", var.subnet_ids)}"]load_balancers = ["${aws_elb.someapp.id}"]}
--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
GitHub Issues: https://github.com/hashicorp/terraform/issues
IRC: #terraform-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Terraform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to terraform-too...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/6607b727-0240-4619-a694-4fb7470b57bc%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
resource "aws_autoscaling_group" "foo" {
lifecycle { create_before_destroy = true }# ...
# on replacement, gives new service time to spin up before moving on to destroy
provisioner "local-exec" {
command = "sleep 200"
}
}
resource "aws_autoscaling_group" "foo" {
lifecycle { create_before_destroy = true }# ...
# on replacement, poll until new ASG's instances shows up healthy
provisioner "remote-exec" {
connection {
# some node in your env with scripts+access to check services
host = "${var.health_checking_host}"
user = "${var.health_checking_user}"
}
# script that performs an app-specific check on the new ASG, exits non-0 after timeout
inline = "poll-until-in-service --service foo --asg ${self.id}"
}
}
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/db5e99e9-50c2-41ad-94bc-423b44afac43%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/CAJpeNAMm2o%3DOnnXNayDzeNx%2BfbP14paDg1uQ1u0GpqdduGMOhg%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/CAEuGOZyii9NtOBn6VcNcyufQcq9r-LvC-nuG5fC%3DMNz%2B-bHZRQ%40mail.gmail.com.
Here as dicussed https://github.com/hashicorp/terraform/issues/2183 there are constraints coming from AWS which we need to work around.The solution you suggested seems to solve a specific case rather than being a general solution.
I think that for this specific problem it would be easier if Terraform rather than delete + create new would use for LC the strategy i've suggested.The strategy consist on copying the launch configuration into a new/temporary LC, update the ASG to use the cloned LC, then delete the old LC,at this point you can create a new LC with the new settings and finally update the ASG to use the new LC.This would allow to update the LC without forcing an IMMEDIATE destruction of instances and recreation, which is very important for stateful systems such as databases,and it would allow to implement a rolling restart with much less constraints.
As noted by Matt this can be application specific, for example consider a database which upon startup of a new instance there is a syncronization phase in which
the data from existing one must be replicated to the new nodes before considering the new DB node READY. This operation can take from a few minutes to hours
depending on the data size. Not considering this a ASG update or rolling restart feature would have disastrous consequences (aka. new nodes up without full data, old nodes killed)
The when updating ASG what the user really want is a way to automate the update phase of the cluster (rolling update).
Creating a new cluster all at once and killing the old one is not a suitable solution in all cases (for example for the a DB as explained above)A rolling update must consider the time it takes to the instance to join the set and replicate data, consider possible failures and allow to roll back of new instances.
Some systems such as Zookeeper and Kafka, have unique IDs which must be preserved, so before starting a new instance with id=1 the old instance must be stopped first,
resource "aws_launch_configuration" "foo" {
lifecycle { create_before_destroy = true }
# omit name so it's generated as a unique value
image_id = "${var.ami}"# ...
}
resource "aws_autoscaling_group" "foo" {
launch_configuration = "${aws_launch_configuration.foo.id}"
name = "myapp"# ^^ do not interpolate AMI or launch config name in the name.# this avoids forced ASG replacement on LC change
Given the above config, Terraform's behavior when `var.ami` is changed from `ami-abc123` to `ami-def456` is as follows:}
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/123a86ea-266f-4eb2-a077-1287b337fc03%40googlegroups.com.
> I think you really need some custom code, somewhere, somehow, running in a loop, to determine that a resource is ready for action, or is ready for rollover and destruction.Yep totally. So it's just a matter of how we model a Terraform feature such that it allows a flexible hook for said custom code.
Hi Bruno,> I think that for this specific problem it would be easier if Terraform rather than delete + create new would use for LC the strategy i've suggested.The strategy consist on copying the launch configuration into a new/temporary LC, update the ASG to use the cloned LC, then delete the old LC,at this point you can create a new LC with the new settings and finally update the ASG to use the new LC.You can do this today with Terraform, you'll just need to manage the rolling of your instances via a separate process.resource "aws_launch_configuration" "foo" {lifecycle { create_before_destroy = true }# omit name so it's generated as a unique valueimage_id = "${var.ami}"# ...}resource "aws_autoscaling_group" "foo" {launch_configuration = "${aws_launch_configuration.foo.id}"name = "myapp"# ^^ do not interpolate AMI or launch config name in the name.# this avoids forced ASG replacement on LC changeGiven the above config, Terraform's behavior when `var.ami` is changed from `ami-abc123` to `ami-def456` is as follows:}* create LC with `ami-def456`* update existing ASG with new LC name* delete LC with `ami-abc123`
--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
GitHub Issues: https://github.com/hashicorp/terraform/issues
IRC: #terraform-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Terraform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to terraform-too...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/93f883e6-f382-4ebf-842e-7444b77d23e7%40googlegroups.com.
Hey Paul,Thanks for all the guidance, I really appreciate it. I'm actually wonder if there's a good way to scale in a new ASG while simultaneously scaling down the previous ASG. For example in our situation I have an ASG with 60 servers in it that are queue workers. If we just bring in another 60 it'll blow out connection limits in places (we're working on it) so it'd be nicer if it brought instances in more like "launch new ASG, bringing in X at a time while scaling X down in the old).
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/da6ef9f2-d75c-44a7-b61d-4900f97a6d22%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/854249f3-d4f8-4ca7-aeee-c9272098be8c%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/c4ed1e4f-50c8-445d-ad72-d42ad2e92829%40googlegroups.com.
Thanks for the answer, it's clear and works well, I tried to separate my lc and asg into different module, and use the variable to pass the lc name (still generated by terraform) into asg module, but it stops working, it start to give cycle error, putting asg and lc into same module, everything works fine, any idea why this happen? why lc and asg cannot be in different module?
terraform graph -draw-cycles
provider "aws" {
region = "ap-southeast-2"
}
module "my_elb" {
source = "../modules/elb"
subnets = ["subnet-481d083f", "subnet-303cd454"]
security_groups = ["sg-e8ac308c"]
}
module "my_lc" {
source = "../modules/lc"
subnets = ["subnet-481d083f", "subnet-303cd454"]
security_groups = ["sg-e8ac308c"]
snapshot_id = "snap-00d5e8ef70d1b3e24"
}
module "my_asg" {
source = "../modules/asg"
subnets = ["subnet-481d083f", "subnet-303cd454"]
my_asg_name = "my_asg_${module.my_lc.my_lc_name}"
my_lc_id = "${module.my_lc.my_lc_id}"
my_elb_name = "${module.my_elb.my_elb_name}"
}
data "template_file" "userdata" { template = "${file("${path.module}/userdata.sh")}"
vars { notify_email = "m...@email.co" }}
resource "aws_launch_configuration" "my_lc" { lifecycle { create_before_destroy = true } image_id = "ami-28cff44b" instance_type = "t2.micro" security_groups = ["${var.security_groups}"] user_data = "${data.template_file.userdata.rendered}" associate_public_ip_address = false key_name = "sydney"
root_block_device { volume_size = 20 }
ebs_block_device { device_name = "/dev/sdi" volume_size = 10 snapshot_id = "${var.snapshot_id}" }}
resource "aws_autoscaling_group" "my_asg" { name = "${var.my_asg_name}" lifecycle { create_before_destroy = true } max_size = 1 min_size = 1 vpc_zone_identifier = ["${var.subnets}"] wait_for_elb_capacity = true wait_for_capacity_timeout = "6m" min_elb_capacity = 1 launch_configuration = "${var.my_lc_id}" load_balancers = ["${var.my_elb_name}"] tag { key = "Role" value = "API" propagate_at_launch = true }}
resource "aws_autoscaling_policy" "scale_up" { name = "scale_up" lifecycle { create_before_destroy = true } scaling_adjustment = 1 adjustment_type = "ChangeInCapacity" cooldown = 300 autoscaling_group_name = "${aws_autoscaling_group.my_asg.name}"}
resource "aws_cloudwatch_metric_alarm" "scale_up_alarm" { alarm_name = "high_cpu" lifecycle { create_before_destroy = true } comparison_operator = "GreaterThanThreshold" evaluation_periods = "2" metric_name = "CPUUtilization" namespace = "AWS/EC2" period = "120" statistic = "Average" threshold = "80" insufficient_data_actions = [] alarm_description = "EC2 CPU Utilization" alarm_actions = ["${aws_autoscaling_policy.scale_up.arn}"] dimensions { AutoScalingGroupName = "${aws_autoscaling_group.my_asg.name}" }}
resource "aws_autoscaling_policy" "scale_down" { name = "scale_down" lifecycle { create_before_destroy = true } scaling_adjustment = -1 adjustment_type = "ChangeInCapacity" cooldown = 600 autoscaling_group_name = "${aws_autoscaling_group.my_asg.name}"}
resource "aws_cloudwatch_metric_alarm" "scale_down_alarm" { alarm_name = "low_cpu" lifecycle { create_before_destroy = true } comparison_operator = "LessThanThreshold" evaluation_periods = "5" metric_name = "CPUUtilization" namespace = "AWS/EC2" period = "120" statistic = "Average" threshold = "300" insufficient_data_actions = [] alarm_description = "EC2 CPU Utilization" alarm_actions = ["${aws_autoscaling_policy.scale_down.arn}"] dimensions { AutoScalingGroupName = "${aws_autoscaling_group.my_asg.name}" }}
> can you please clarify what would be behaviour in case the autoscaling group is not attached to a load balancer?> would the old ASG and related instances destroyed before the new ones are fully in service?
I'm also kicking ideas around in the back of my head about how TF can better support this "resource verification" / "poll until healthy" use case first class. Any ideas on design for features like that are welcome!
If Terraform hits its 10m timeout during (3), the new ASG will be marked as "tainted" and the apply will halt, leaving the old ASG in service.
resource "aws_autoscaling_group" "web" { name = "${aws_launch_configuration.web.name}-asg" vpc_zone_identifier = ["${var.web_subnet_id}"] min_size = "${var.autoscaling_min_size}" max_size = "${var.autoscaling_max_size}" wait_for_elb_capacity = false force_delete = true launch_configuration = "${aws_launch_configuration.web.id}" load_balancers = ["${var.web_elb_name}"] lifecycle { create_before_destroy = true } initial_lifecycle_hook { name = "ec2-web-up" default_result = "CONTINUE" heartbeat_timeout = 3600 lifecycle_transition = "autoscaling:EC2_INSTANCE_LAUNCHING" notification_metadata = <<EOF{ "myapp_autoscaling_group_by_terraform": "web",}EOF } tag { key = "Name" value = "myapp-${var.env}-web-server-asg" propagate_at_launch = "true" }}
resource "aws_launch_configuration" "web" { lifecycle { create_before_destroy = true } name_prefix = "myapp-${var.env}-web-lc-" image_id = "ami-5e63d13e" instance_type = "t2.micro" security_groups = ["${aws_security_group.web.id}"] iam_instance_profile = "${aws_iam_instance_profile.myapp_server_role_profile.id}" key_name = "${var.aws_keypair_name}" associate_public_ip_address = false}
create_before_destroy
key can only depend on other resources that also include create_before_destroy
. Referencing a resource that does not include create_before_destroy
will result in a dependency graph cycle.Hi James,Those steps are pretty much exactly how we currently do production rollouts at HashiCorp. :)Here's how we structure things:
resource "aws_launch_configuration" "someapp" {lifecycle { create_before_destroy = true }
If Terraform hits its 10m timeout during (3), the new ASG will be marked as "tainted" and the apply will halt, leaving the old ASG in service.
Hope this helps! Happy to answer any further questions you might have,Paul
--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
GitHub Issues: https://github.com/hashicorp/terraform/issues
IRC: #terraform-tool on Freenode
---
You received this message because you are subscribed to a topic in the Google Groups "Terraform" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/terraform-tool/7Gdhv1OAc80/unsubscribe.
To unsubscribe from this group and all its topics, send an email to terraform-too...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/47f05b3b-90c5-476f-9da3-3f957db1d196%40googlegroups.com.
--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
GitHub Issues: https://github.com/hashicorp/terraform/issues
IRC: #terraform-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Terraform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to terraform-too...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/6607b727-0240-4619-a694-4fb7470b57bc%40googlegroups.com.
On Tue, Sep 1, 2015 at 11:20 PM, James Carr <james...@gmail.com> wrote:
Hi All,Long time lurker, first time poster.One thing I would like to do is phase in a new ASG. For example, when I update a new AMI for an autoscaling group, I want to* Spin up a new ASG with the updated launch config that has new AMI* attach to existing ELB, leave old ASG alone and attached* ones the min healthy hosts are attached from the new ASG, scale down and destroy the old ASGIs there any easy way to accomplish this via terraform? So far the behavior I've observed is it just destroys the previous ASG and LC and creates a new one. Seems rather dangerous in a production environment so I am sure I am missing something here.Thanks!James
--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
GitHub Issues: https://github.com/hashicorp/terraform/issues
IRC: #terraform-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Terraform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to terrafo...@googlegroups.com.