Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(python)-adds schedule scaling policy for ecs #964

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions python/ecs-schedulescaling/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

# Schedule scaling for ecs

This project contains code to deploy ecs cluster with the ability to scale fargate tasks based on day-night schedule.

The `cdk.json` contains context variables for schedule along with minimum and maximum capacity count for day and night schedule.

Use below command to view application auto scaling scheduled actions:
```
aws application-autoscaling describe-scheduled-actions \
--service-namespace ecs
```

Use below command to view descriptive information about the scaling activities:
```
aws application-autoscaling describe-scaling-activities \
--service-namespace ecs
```
10 changes: 10 additions & 0 deletions python/ecs-schedulescaling/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env python3

import aws_cdk as cdk

from schedulescaling.schedulescaling_stack import SchedulescalingStack

app = cdk.App()
SchedulescalingStack(app, "SchedulescalingStack")

app.synth()
65 changes: 65 additions & 0 deletions python/ecs-schedulescaling/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"app": "python3 app.py",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"requirements*.txt",
"source.bat",
"**/__init__.py",
"python/__pycache__",
"tests"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-route53-patters:useCertificate": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
"@aws-cdk/aws-redshift:columnId": true,
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
"@aws-cdk/aws-kms:aliasNameRef": true,
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
"scaling":true,
"daytime": [{"cron":"cron(00 08 * * ? *)"},{"min":2},{"max":3}],
"nightime": [{"cron":"cron(00 18 * * ? *)"},{"min":1},{"max":2}]
}
}
2 changes: 2 additions & 0 deletions python/ecs-schedulescaling/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
aws-cdk-lib==2.111.0
constructs>=10.0.0,<11.0.0
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from aws_cdk import Duration, Stack
from aws_cdk import aws_applicationautoscaling as appscaling
from aws_cdk import aws_ec2 as ec2
from aws_cdk import aws_ecs as ecs
from aws_cdk import aws_ecs_patterns as ecs_patterns
from aws_cdk import aws_iam as iam
from aws_cdk import aws_sns_subscriptions as subs
from constructs import Construct


class SchedulescalingStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)

scaling = self.node.try_get_context("scaling")
dayschedule = self.node.try_get_context("daytime")
nightschedule = self.node.try_get_context("nightime")

min_capacity = 1
max_capacity = 1

# daytime scaling schedule(UTC)
day_schedule = dayschedule[0]["cron"]
day_min = dayschedule[1]["min"]
day_max = dayschedule[2]["max"]

# nighttime scaling schedule(UTC)
night_schedule = nightschedule[0]["cron"]
night_min = nightschedule[1]["min"]
night_max = nightschedule[2]["max"]

vpc = ec2.Vpc(self, "ecsVpc", max_azs=2)

ecs_cluster = ecs.Cluster(
self,
id="ecscluster",
vpc=vpc,
container_insights=True,
enable_fargate_capacity_providers=True,
)

# create task definition
task_definition = ecs.FargateTaskDefinition(self, "taskdef", cpu=256)
image = ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")
container = task_definition.add_container(id="ecs-con-task", image=image)
container.add_port_mappings(ecs.PortMapping(container_port=8080))

# define service
service = ecs.FargateService(
self, "FargateService", cluster=ecs_cluster, task_definition=task_definition
)
# define autoscaling
if scaling:
target = appscaling.ScalableTarget(
self,
"ScalableTarget",
service_namespace=appscaling.ServiceNamespace.ECS,
min_capacity=min_capacity,
max_capacity=max_capacity,
resource_id=f"service/{ecs_cluster.cluster_name}/{service.service_name}",
scalable_dimension="ecs:service:DesiredCount",
)
target.scale_on_schedule(
"daytime",
schedule=appscaling.Schedule.expression(day_schedule),
min_capacity=day_min,
max_capacity=day_max,
)
target.scale_on_schedule(
"nighttime",
schedule=appscaling.Schedule.expression(night_schedule),
min_capacity=night_min,
max_capacity=night_max,
)
Loading