diff --git a/terraform/example.tf b/terraform/example.tf index 9c50490..eb5d092 100644 --- a/terraform/example.tf +++ b/terraform/example.tf @@ -43,7 +43,7 @@ data "aws_ami" "linux2" { variable "instance_key" { description = "Name of EC2 Keypair" - default = "lifecycled-example" + default = "lifecycled-example" } module "example" { diff --git a/terraform/modules/example/cloud-config.yml b/terraform/modules/example/cloud-config.yml index 3064cf2..67fd326 100644 --- a/terraform/modules/example/cloud-config.yml +++ b/terraform/modules/example/cloud-config.yml @@ -1,7 +1,4 @@ #cloud-config -package_update: true -packages: - - aws-cfn-bootstrap write_files: - path: "/etc/systemd/system/lifecycled.service" permissions: "0644" @@ -23,23 +20,6 @@ write_files: [Install] WantedBy=multi-user.target - - path: "/usr/local/scripts/cloudformation-signal.sh" - permissions: "0744" - owner: "root" - content: | - #! /usr/bin/bash - - set -euo pipefail - - function await_unit() { - echo -n "Waiting for $1..." - while ! systemctl is-active $1 > /dev/null; do - sleep 1 - done - echo "Done!" - } - - await_unit lifecycled.service - path: "/usr/local/scripts/lifecycle-handler.sh" permissions: "0744" owner: "root" @@ -52,13 +32,10 @@ write_files: sleep 120 echo "goodbye from the handler" runcmd: - - | + - | aws s3 cp s3://${artifact_bucket}/${artifact_key} /usr/local/bin/lifecycled chmod +x /usr/local/bin/lifecycled chown root:root /usr/local/bin/lifecycled echo "lifecycled ${artifact_etag} installed" - | systemctl enable lifecycled.service --now - - | - /usr/local/scripts/cloudformation-signal.sh - /opt/aws/bin/cfn-signal -e $? --stack ${stack_name} --resource AutoScalingGroup --region ${region} diff --git a/terraform/modules/example/main.tf b/terraform/modules/example/main.tf index 6517f4e..8b23789 100644 --- a/terraform/modules/example/main.tf +++ b/terraform/modules/example/main.tf @@ -36,30 +36,61 @@ data "template_file" "main" { } } -# The autoscaling group -module "asg" { - source = "telia-oss/asg/aws" - version = "0.2.0" - - name_prefix = "${var.name_prefix}" - user_data = "${data.template_file.main.rendered}" - vpc_id = "${var.vpc_id}" - subnet_ids = "${var.subnet_ids}" - await_signal = "true" - pause_time = "PT5M" - health_check_type = "EC2" - instance_policy = "${data.aws_iam_policy_document.permissions.json}" - min_size = "${var.instance_count}" - instance_type = "${var.instance_type}" - instance_ami = "${var.instance_ami}" - instance_key = "${var.instance_key}" - tags = "${var.tags}" +resource "aws_launch_configuration" "main" { + name_prefix = "${var.name_prefix}" + image_id = "${var.instance_ami}" + instance_type = "${var.instance_type}" + key_name = "${var.instance_key}" + iam_instance_profile = "${aws_iam_instance_profile.ec2.name}" + security_groups = ["${aws_security_group.main.id}"] + + user_data = "${data.template_file.main.rendered}" + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_autoscaling_group" "main" { + name = "${var.name_prefix}-${aws_launch_configuration.main.name}" + launch_configuration = "${aws_launch_configuration.main.id}" + vpc_zone_identifier = ["${var.subnet_ids}"] + + min_size = "0" + desired_capacity = "${var.instance_count}" + max_size = "1" + + lifecycle { + create_before_destroy = true + } + + initial_lifecycle_hook { + name = "${var.name_prefix}-lifecycle" + default_result = "CONTINUE" + heartbeat_timeout = 60 + lifecycle_transition = "autoscaling:EC2_INSTANCE_TERMINATING" + notification_target_arn = "${aws_sns_topic.main.arn}" + role_arn = "${aws_iam_role.lifecycle_hook.arn}" + } +} + +resource "aws_security_group" "main" { + name = "${var.name_prefix}-sg" + description = "Allow access to lifecycled instances" + vpc_id = "${var.vpc_id}" + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } } # Allow SSH ingress if a EC2 key pair is specified. resource "aws_security_group_rule" "ssh_ingress" { count = "${var.instance_key != "" ? 1 : 0}" - security_group_id = "${module.asg.security_group_id}" + security_group_id = "${aws_security_group.main.id}" type = "ingress" protocol = "tcp" from_port = 22 @@ -147,31 +178,48 @@ data "aws_iam_policy_document" "permissions" { } } +resource "aws_iam_instance_profile" "ec2" { + name = "${var.name_prefix}-ec2-instance-profile" + role = "${aws_iam_role.ec2.name}" +} + +resource "aws_iam_role" "ec2" { + name = "${var.name_prefix}-ec2-role" + assume_role_policy = "${data.aws_iam_policy_document.ec2_assume.json}" +} + +resource "aws_iam_role_policy" "ec2" { + name = "${var.name_prefix}-ec2-permissions" + role = "${aws_iam_role.ec2.id}" + policy = "${data.aws_iam_policy_document.permissions.json}" +} + +data "aws_iam_policy_document" "ec2_assume" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["ec2.amazonaws.com"] + } + } +} + # SNS topic for the lifecycle hook resource "aws_sns_topic" "main" { name = "${var.name_prefix}-lifecycle" } -# Lifecycle hook -resource "aws_autoscaling_lifecycle_hook" "main" { - name = "${var.name_prefix}-lifecycle" - autoscaling_group_name = "${module.asg.id}" - lifecycle_transition = "autoscaling:EC2_INSTANCE_TERMINATING" - default_result = "CONTINUE" - heartbeat_timeout = "60" - notification_target_arn = "${aws_sns_topic.main.arn}" - role_arn = "${aws_iam_role.lifecycle.arn}" -} - # Execution role and policies for the lifecycle hook -resource "aws_iam_role" "lifecycle" { +resource "aws_iam_role" "lifecycle_hook" { name = "${var.name_prefix}-lifecycle-role" assume_role_policy = "${data.aws_iam_policy_document.asg_assume.json}" } -resource "aws_iam_role_policy" "lifecycle" { - name = "${var.name_prefix}-lifecycle-permissions" - role = "${aws_iam_role.lifecycle.id}" +resource "aws_iam_role_policy" "lifecycle_hook" { + name = "${var.name_prefix}-lifecycle-asg-permissions" + role = "${aws_iam_role.lifecycle_hook.id}" policy = "${data.aws_iam_policy_document.asg_permissions.json}" }