Autoscaling for ECS EC2 standalone tasks - amazon-web-services

I am using CDK to run standalone containerized ECS tasks on EC2.
I'm not using ECS service, because my task should be triggered using a request (in this a lambda), so they are not long running (or aways on). I use the following code, which works for one instance of the task:
this.autoScalingGroup = new autoscaling.AutoScalingGroup(this, 'ASG', {
vpc: this.vpc,
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.C5,
ec2.InstanceSize.XLARGE,
),
machineImage: ecs.EcsOptimizedImage.amazonLinux2(),
minCapacity: 1,
maxCapacity: 10,
updatePolicy: UpdatePolicy.rollingUpdate(),
});
const capacityProvider = new ecs.AsgCapacityProvider(
this,
'AsgCapacityProvider',
{
autoScalingGroup: this.autoScalingGroup,
},
);
this.cluster.addAsgCapacityProvider(capacityProvider);
The problem is that I cannot run concurrent instances. So, it doesn't scale up to more instances. It only runs one instance (my container takes up ~80% of the EC2 instance resources). How would I trigger autoscaling such that when multiple tasks are run more instances get added?
p.s. obviosuly if I set minCapacity to x, x number of concurrent tasks can run, but I'd like to only keep 1 instance up and scale up and down.

The CDK-created capacity provider will auto-scale the instances based on standalone task activity. I suspect scaling is not working for you because your run-task invocations are missing a capacity provider strategy that tells ECS what capacity provider to use. There are a couple of ways to fix this:
Option 1: Set a strategy in the run-task call:
aws ecs run-task \
--cluster <cluster-arn> \
--task-definition <task-definition-name> \
--capacity-provider-strategy capacityProvider=<capacity-provider-name>,weight=1,base=1 \
--count 3 \
Option 2: Set the cluster's *default* capacity provider strategy
The CDK's L2 Cluster construct does not set a default capacity provider strategy on your cluster. See this github issue for context and workarounds. The default can also be set in the console.

Related

ECS EC2 service with capacity provider binpack doesnt remove EC2 instances when scaling down

I created a Capacity Provider.
Then, I deployed a Service with that Capacity Provider and with binpack (CPU) strategy.
Service:
Type: AWS::ECS::Service
Properties:
ServiceName: my-service
TaskDefinition: my-td
Cluster: my-cluster
CapacityProviderStrategy:
- CapacityProvider: my-capacity-provider
Weight: 1
PlacementStrategies:
- Type: binpack
Field: cpu
DesiredCount: 1
This also creates the alarms in CW for high and low CPU usage.
When I add 15 tasks, after a while, the high alarm goes on and new EC2 instances are added.
Then, if I update the number of tasks to 6... Nothing happens. The low usage alarm is never triggered and the EC2 instances are not removed.
However, the service deregisters the extra tasks but the required 6 and enters to steady state.
Does anyone have this issue?
What can I do?
I know I could go to ECS Cluster, then in the ECS instances tab select the extra EC2 instances and drain them. However, this manual action would kill the purpose o using CloudFormation.

AWS, ecs alarm metric, there are two memory utilization metric, difference?

There's memory-utilization metric under both of
ClusterName, ServiceName
ClusterName
I can't tell the difference of the two..
ClusterName
This dimension filters the data that you request for all resources in a specified cluster. All Amazon ECS metrics are filtered by ClusterName.
ServiceName
This dimension filters the data that you request for all resources in a specified service within a specified cluster.
Cluster metrics are scoped as ECS > ClusterName and service utilization metrics are scoped as ECS > Cluster

AWS codedeploy blue green deployment

I have setup code pipeline for end to end automatic deployment of revision on EC2 instances using cloudformation template, the deployment group is of type blue/green for codedploy.
But I dont understand how to keep the code deployment group in sync with newly created auto scaling group (green).
Do I have to create new lambda invoke action in pipeline after successful deployment to update the newly created auto scaling group name.
Unfortunately, CloudFormation does not support Blue/Green deployments for EC2 platform:
For blue/green deployments, AWS CloudFormation supports deployments on Lambda compute platforms only.
Support for ECS is very new.
To create deployment group for blue/green for EC2 platform you would have to create a custom resource in CloudFormation .
The custom resource would be based on a lambda function, and in that lambda function you would use create_deployment_group to define blue/green details for your EC2 instances. As part of this process, you will have an option to choose how to deal with AutoScaling group, e.g.
"greenFleetProvisioningOption": {
"action": "COPY_AUTO_SCALING_GROUP"
}
For creation of custom resource, crhelper by AWS is very useful.
Hope this helps and hope Blue/Green for EC2 will be supported by CloudFormation soon.

How to prevent my EC2 instances from automatically rebooting every time one has stopped?

UPDATED
Following the AWS instance scheduler I've been able to setup a scheduler that starts and stops at the beginning and end of the day.
However, the instances keep being terminated and reinstalled.
I have an Amazon Elastic Kubernetes Service (EKS) that returns the following CloudWatch log:
discovered the following log in my CloudWatch
13:05:30
2019-11-21 - 13:05:30.251 - INFO : Handler SchedulerRequestHandler scheduling request for service(s) rds, account(s) 612681954602, region(s) eu-central-1 at 2019-11-21 13:05:30.251936
13:05:30
2019-11-21 - 13:05:30.433 - INFO : Running RDS scheduler for account 612681954602 in region(s) eu-central-1
13:05:31
2019-11-21 - 13:05:31.128 - INFO : Fetching rds Instances for account 612681954602 in region eu-central-1
13:05:31
2019-11-21 - 13:05:31.553 - INFO : Number of fetched rds Instances is 2, number of schedulable resources is 0
13:05:31
2019-11-21 - 13:05:31.553 - INFO : Scheduler result {'612681954602': {'started': {}, 'stopped': {}}}
I don't know if it is my EKS that keeps rebooting my instances, but I really would love to keep them stopped until the next day.
How can I prevent my EC2 instances from automatically rebooting every time one has stopped? Or, even better, how can I deactivate my EKS stack automatically?
Update:
I discovered that EKS has a Cluster Autoscaler. Maybe this could be where the problem lies?
https://docs.aws.amazon.com/eks/latest/userguide/cluster-autoscaler.html
EKS node group would create an auto scaling group to manage the worker nodes. You need specify the minimum, maximum and desired size of worker nodes. Once any instance is stopped, the auto scaling group would create new instance to match the desired instance size.
Check below doc for details,
https://docs.aws.amazon.com/eks/latest/userguide/launch-workers.html

Create and delete EC2 instance with CloudFormation

I am quite new to AWS and want to know how to achieve following task with CloudFormation.
I want to spin up an EC2 instance with tomcat and deploy a java application on it. This java application will perform some operation. Once the operation is done, I want to delete all the resources created by this CloudFormation stack.
All these activities should be automatic. For example -- I will create the CloudFormation stack JSON file. At particular time of a day, a job should be kicked off (I don't know where in AWS to configure such job or how). But I know through Jenkins we can create a CloudFormation stack that will create all resources.
Then, after some time (lets say 2 hrs), another job should kick off and delete all resources created by CloudFormation.
Is this possible in AWS? If yes, any hints on how to do this?
Just to confirm, what you intend to do is have an EC2 instance get created on a schedule, and then have it shut down after 2 hours. The common way of accomplishing that is to use an Auto-Scaling Group (ASG) with a ScheduledAction to scale up and a ScheduledAction to scale down.
ASGs have a "desired capacity" (the number of instances in the ASG). You would want this to be "0" by default, change it to "1" at your desired time, and change it back to "0" two hours after that. What that will do is automatically start and subsequently terminate your EC2 instance on your schedule.
They also use a LaunchConfiguration, which is a template for your EC2 instances that will start on the schedule.
MyASG:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AvailabilityZones: !GetAZs !Ref "AWS::Region"
LaunchConfigurationName: !Ref MyLaunchConfiguration
MaxSize: 1
MinSize: 0
DesiredCapacity: 0
ScheduledActionUp:
Type: AWS::AutoScaling::ScheduledAction
Properties:
AutoScalingGroupName: !Ref MyASG
DesiredCapacity: 1
Recurrence: "0 7 * * *"
ScheduledActionDown:
Type: AWS::AutoScaling::ScheduledAction
Properties:
AutoScalingGroupName: !Ref MyASG
DesiredCapacity: 0
Recurrence: "0 9 * * *"
MyLaunchConfiguration:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: ami-xxxxxxxxx # <-- Specify the AMI ID that you want
InstanceType: t2.micro # <-- Chaneg the instance size if you want
KeyName: my-key # <-- Change to the name of an EC2 SSH key that you've added
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum install -y aws-cfn-bootstrap
# ...
# ... run some commands to set up the instance, if you need to
# ...
Metadata:
AWS::CloudFormation::Init:
config:
files:
"/etc/something/something.conf":
mode: 000600
owner: root
group: root
content: !Sub |
#
# Add the content of a config file, if you need to
#
Depending on what you want your instances to interact with, you might also need to add a Security Group and/or an IAM Instance Profile along with an IAM Role.
If you're using Jenkins to deploy the program that will run, you would add a step to bake an AMI, build and push a docker image, or take whatever other action you need to deploy your application to the place that it will be used by your instance.
I note that in your question you say that you want to delete all of the resources created by CloudFormation. Usually, when you deploy a stack like this, the stack remains deployed. The ASG will remain there until you decide to remove the stack, but it won't cost anything when you're not running EC2 instances. I think I understand your intent here, so the advice that I'm giving aligns with that.
You can use Lambda to execute events on a regular schedule.
Write a Lambda function that calls CloudFormation to create your stack of resources. You might even consider including a termination Lambda function in your CloudFormation stack and configure it to run on a schedule (2 hours after the stack was created) to delete the stack that the termination Lambda function itself is part of (have not tried this, but believe that it will work). Or you could trigger stack deletion from cron on the EC2 instance running your Java app, of course).
If all you want is an EC2 instance, it's probably easier to simply create the EC2 instance rather than a CloudFormation stack.
Something (eg an AWS Lambda function triggered by Amazon CloudWatch Events) calls the EC2 API to create the instance
User Data is passed to the EC2 instance to install the desired software OR use a custom AMI with all software pre-installed
Have the instance terminate itself when it has finished processing -- this could be as simple as calling the Operating System to shutdown the machine, with the EC2 Shutdown Behavior set to Terminate.