Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Kgirthofer committed Aug 9, 2017
0 parents commit 4606a1a
Show file tree
Hide file tree
Showing 11 changed files with 1,466 additions and 0 deletions.
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# service_shuffler

A Terraform module that shuffles AWS ECS services using lambda during autoscaling events.
It will spin up a lambda and all underlying resources so that when an autoscaling group scales up or down your defined service will automatically adjust to the required number - keeping a predetermained number of tasks running on each host. Useful for tasks like fluentd where you need to have it running on the host before launching other tasks that will require it!
Shuffle your AWS ECS Services on scale up and down!

## Usage

```hcl
module "container_service_cluster" {
source = "https://github.com/kgirthofer/service_shuffler?ref=0.1.0"
cluster_name = "test-cluster"
autoscaling_group_name = "testClusterASG"
lambda_name = "test-shuffler"
region = "us-east-1"
}
```

## Variables

- `cluster_name` - ECS Cluster name
- `autoscaling_group_name` - Name of the ASG you want to monitor for scale events
- `lambda_name` - What you want your lambda function to be
- `region` - region for everything
58 changes: 58 additions & 0 deletions cloudwatch_event.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Scale Up

resource "aws_cloudwatch_event_rule" "scale_up" {
name = "${var.cluster_name}-asg-scale-up"
description = "Capture each scale up"

event_pattern = <<PATTERN
{
"source": [
"aws.autoscaling"
],
"detail-type": [
"EC2 Instance Launch Successful"
],
"detail": {
"AutoScalingGroupName": [
"${var.auto_scaling_group_name}"
]
}
}
PATTERN
}

resource "aws_cloudwatch_event_target" "lambdaTriggerUp" {
rule = "${aws_cloudwatch_event_rule.scale_up.name}"
target_id = "lamdaFunction"
arn = "${aws_lambda_function.lambda_shuffler.arn}"
}

# Scale Down

resource "aws_cloudwatch_event_rule" "scale_down" {
name = "${var.cluster_name}-asg-scale-down"
description = "Capture each scale down"

event_pattern = <<PATTERN
{
"source": [
"aws.autoscaling"
],
"detail-type": [
"EC2 Instance Terminate Successful"
],
"detail": {
"AutoScalingGroupName": [
"${var.auto_scaling_group_name}"
]
}
}
PATTERN
}

resource "aws_cloudwatch_event_target" "lambdaTriggerDown" {
rule = "${aws_cloudwatch_event_rule.scale_down.name}"
target_id = "lamdaFunction"
arn = "${aws_lambda_function.lambda_shuffler.arn}"
}

34 changes: 34 additions & 0 deletions iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
data "aws_iam_policy_document" "cloudwatchAccess" {
statement {
sid = "1"

actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
resources = ["arn:aws:logs:*:*:*"]
}
statement {
sid = "2"

actions = [
"ecs:DescribeServices",
"ecs:UpdateService",
"autoscaling:DescribeAutoScalingGroups"
]
resources = ["*"]
}
}

resource "aws_iam_policy" "cloudwatchAccess" {
name = "${var.lambda_name}-policy"
path = "/"
policy = "${data.aws_iam_policy_document.cloudwatchAccess.json}"
}

resource "aws_iam_policy_attachment" "attachment" {
name = "ecs-attachment"
roles = ["${aws_iam_role.lambda_shuffler_role.name}"]
policy_arn = "${aws_iam_policy.cloudwatchAccess.arn}"
}
54 changes: 54 additions & 0 deletions lambda.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
resource "aws_iam_role" "lambda_shuffler_role" {
name = "${var.lambda_name}_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

resource "aws_lambda_function" "lambda_shuffler" {
function_name = "${var.lambda_name}"
handler = "shuffler.lambda_handler"
runtime = "python2.7"
filename = "shuffler.zip"
role = "${aws_iam_role.lambda_shuffler_role.arn}"
source_code_hash = "${base64sha256(file("shuffler.zip"))}"
environment {
variables = {
REGION = "${var.region}"
ASG_NAME = "${var.auto_scaling_group_name}"
CLUSTER_NAME = "${var.cluster_name}"
SERVICE_NAME = "${var.service_name}"
}
}
}

# Scale Up Trigger
resource "aws_lambda_permission" "allow_cloudwatch_up" {
statement_id = "AllowExecutionFromCloudWatchUp"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.lambda_shuffler.function_name}"
principal = "events.amazonaws.com"
source_arn = "${aws_cloudwatch_event_rule.scale_up.arn}"
}

# Scale Down Trigger
resource "aws_lambda_permission" "allow_cloudwatch_down" {
statement_id = "AllowExecutionFromCloudWatchDown"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.lambda_shuffler.function_name}"
principal = "events.amazonaws.com"
source_arn = "${aws_cloudwatch_event_rule.scale_down.arn}"
}

3 changes: 3 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
provider "aws" {
region = "${var.region}"
}
27 changes: 27 additions & 0 deletions shuffler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from __future__ import print_function
import boto3
import os

region = os.environ['REGION']
asg_name = os.environ['ASG_NAME']
service_name = os.environ['SERVICE_NAME']
cluster_name = os.environ['CLUSTER_NAME']

ecs = boto3.client('ecs', region)
asg = boto3.client('autoscaling')

def lambda_handler(event, context):
print('Getting the current ASG Desired Capacity')
total = asg.describe_auto_scaling_groups(
AutoScalingGroupNames=[
asg_name
]
)['AutoScalingGroups'][0]['DesiredCapacity']
print('Desired Capacity: {}'.format(total))
print('Adjsitng Service to Desired Capacity')
response = ecs.update_service(
cluster=cluster_name,
service=service_name,
desiredCount=total
)
return total
Binary file added shuffler.zip
Binary file not shown.
Loading

0 comments on commit 4606a1a

Please sign in to comment.