Skip to content

Instantly share code, notes, and snippets.

@btotharye
Last active September 6, 2019 21:36
Show Gist options
  • Save btotharye/d9de3ed45b17cc4ba87ea7d902b8ec65 to your computer and use it in GitHub Desktop.
Save btotharye/d9de3ed45b17cc4ba87ea7d902b8ec65 to your computer and use it in GitHub Desktop.
ECS Fargate Setup with Multi Stack
#!/usr/bin/env python3
from aws_cdk import core
from cdk.vpc_stack import VpcStack
from cdk.ecs_stack import EcsStack
app = core.App()
# Params and stage info
stage = app.node.try_get_context('stage')
props = app.node.try_get_context(stage)
service = app.node.try_get_context('serviceName')
app_id = app.node.try_get_context('appId')
cost_centre = app.node.try_get_context('costCentre')
dcl = app.node.try_get_context('dcl')
region = app.node.try_get_context(stage)['region']
account = app.node.try_get_context(stage)['account']
# Build out stack
VpcStack(app, "{0}-{1}".format(service, stage), props=props, env={'region': region, 'account': account})
# Tagging
core.Tag.add(app, 't_environment', stage.upper())
core.Tag.add(app, 't_AppID', app_id)
core.Tag.add(app, 't_cost_centre', cost_centre)
core.Tag.add(app, 't_dcl', dcl)
core.Tag.add(app, 'Application', service)
# Synth the CF template
app.synth()
from aws_cdk import (
aws_ec2 as ec2,
aws_ecs as ecs,
aws_ecr as ecr,
aws_iam as iam,
aws_logs as logs,
aws_elasticloadbalancingv2 as elbv2,
aws_route53 as route53,
aws_route53_targets,
core,
)
class EcsStack(core.Stack):
def __init__(
self,
scope: core.Construct,
id: str,
props,
vpc: ec2.Vpc,
execution_role: iam.Role,
task_role: iam.Role,
log_group: logs.LogGroup,
**kwargs) -> None:
super().__init__(scope, id, **kwargs)
vpn_connection = ec2.Peer.ipv4(
'0.0.0.0/16'
)
# Props Setup
stage = scope.node.try_get_context('stage')
my_service_name = scope.node.try_get_context('serviceName')
region = scope.node.try_get_context(stage)['region']
account = scope.node.try_get_context(stage)['account']
# Default Target Group
fargate_tg = elbv2.ApplicationTargetGroup(
self,'DefaultTargetGroup',
port=8443,
protocol=elbv2.ApplicationProtocol.HTTP,
vpc=vpc
)
# Setup Fargate Task Definition
fargate_taskdef = ecs.FargateTaskDefinition(
self,'ECSFargateTask',
memory_limit_mib=8192,
cpu=2048,
execution_role=execution_role,
task_role=task_role,
family="{0}-{1}-taskdef".format(my_service_name, stage)
)
api_repo = ecr.Repository.from_repository_arn(
self,'AppImage',
repository_arn="arn:aws:ecr:us-east-1:x:repository/x"
)
# Add Container Info to Task
ecs_container = fargate_taskdef.add_container(
"MyFargateTask",
image=ecs.EcrImage(
repository=api_repo, tag="latest"
),
logging=ecs.LogDriver.aws_logs(
stream_prefix="{0}-{1}-api".format(my_service_name, stage),
log_group=log_group
)
)
# Setup ECS Cluster
ecs_cluster = ecs.Cluster(
self,
'ECSCluster',
vpc=vpc,
cluster_name="{0}-{1}".format(my_service_name, stage)
)
from aws_cdk import (
aws_ec2 as ec2,
aws_ecs as ecs,
aws_ecr as ecr,
aws_iam as iam,
aws_logs as logs,
aws_elasticloadbalancingv2 as elbv2,
aws_route53 as route53,
aws_route53_targets,
core,
)
from .ecs_stack import EcsStack
class VpcStack(core.Stack):
def __init__(self, scope: core.Construct, id: str, props, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
vpn_connection = ec2.Peer.ipv4(
'0.0.0.0/16'
)
# Props Setup
stage = scope.node.try_get_context('stage')
my_service_name = scope.node.try_get_context('serviceName')
region = scope.node.try_get_context(stage)['region']
account = scope.node.try_get_context(stage)['account']
# Setup IAM user for logs
vpc_flow_role = iam.Role(
self, 'FlowLog',
assumed_by=iam.ServicePrincipal('vpc-flow-logs.amazonaws.com')
)
# Create Cloudwatch log group
log_group = logs.LogGroup(
self, 'LogGroup',
log_group_name=my_service_name,
retention=logs.RetentionDays('ONE_YEAR'),
removal_policy=core.RemovalPolicy('DESTROY')
)
# Setup VPC resource
vpc = ec2.Vpc(
self, '{0}-{1}-vpc'.format(my_service_name, stage),
cidr=props['cidr'],
max_azs=props['vpcAzCount']
)
# Setup VPC flow logs
vpc_log = ec2.CfnFlowLog(
self, 'FlowLogs',
resource_id=vpc.vpc_id,
resource_type='VPC',
traffic_type='ALL',
deliver_logs_permission_arn=vpc_flow_role.role_arn,
log_destination_type='cloud-watch-logs',
log_group_name=log_group.log_group_name
)
# Setup Security Group in VPC
vpc_sg = ec2.SecurityGroup(
self,
'EcSSG',
vpc=vpc,
allow_all_outbound=None,
description="Security Group for vpc",
security_group_name="{0}-{1}-vpc-sg".format(my_service_name, stage)
)
# Add Rules to Security Group
vpc_sg.add_ingress_rule(
peer=pearson_vpn_connection,
connection=ec2.Port.tcp(22)
)
# ALB Security Group
alb_sg = ec2.SecurityGroup(
self,
'AlbSG',
vpc=vpc,
allow_all_outbound=None,
description="Security group for ALB",
security_group_name="{0}-{1}-alb-sg".format(my_service_name,stage)
)
alb_sg.add_ingress_rule(
peer=vpn_connection,
connection=ec2.Port.tcp(443)
)
# Setup ALB
alb = elbv2.ApplicationLoadBalancer(
self,'ALB',
vpc=vpc,
internet_facing=True,
security_group=alb_sg
)
core.CfnOutput(self,
'VPCId',
value=vpc.vpc_id
)
# ECS Execution Role - Grants ECS agent to call AWS APIs
ecs_execution_role = iam.Role(
self, 'ECSExecutionRole',
assumed_by=iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
role_name="{0}-{1}-execution-role".format(my_service_name, stage)
)
# Setup Role Permissions
ecs_execution_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
'elasticloadbalancing:DeregisterInstancesFromLoadBalancer',
'elasticloadbalancing:DeregisterTargets',
'elasticloadbalancing:Describe*',
'elasticloadbalancing:RegisterInstancesWithLoadBalancer',
'elasticloadbalancing:RegisterTargets',
'ec2:Describe*',
'ec2:AuthorizeSecurityGroupIngress',
'sts:AssumeRole',
'ssm:GetParameters'
],
resources=["*"]
)
)
# ECS Task Role - Grants containers in task permission to AWS APIs
ecs_task_role = iam.Role(
self, 'ECSTaskRole',
assumed_by=iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
role_name="{0}-{1}-task-role".format(my_service_name, stage)
)
# Setup Role Permissions
ecs_task_role.add_to_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
'ecr:GetAuthorizationToken',
'ecr:BatchCheckLayerAvailability',
'ecr:GetDownloadUrlForLayer',
'ecr:BatchGetImage',
'logs:CreateLogStream',
'logs:PutLogEvents',
'dynamodb:Query',
'dynamodb:ListTables'
],
resources=["*"]
)
)
EcsStack(self, "{0}-{1}-ecs".format(
my_service_name,
stage
),
props=props,
vpc=vpc,
execution_role=ecs_execution_role,
task_role=ecs_task_role,
log_group=log_group,
env={
'region': region,
'account': account
}
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment