ecs_shared.yaml
---

Shares ECS CloudFormation Deployment

This CloudFormation template will deploy an ECS cluster to be shared among unrelated docker containers.

AWSTemplateFormatVersion: '2010-09-09' Description: Shared ECS Cluster Metadata: Description: Provides an ECS Cluster with ALB AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Infrastructure Options Parameters: - VPC - LBSubnets - InstanceSubnets - Label: default: ECS/EC2 Instance Configuration Parameters: - SshKeyName - EcsInstanceType - AsgMaxSize - EcsAmi - LaunchTemplateVersion - Label: default: Tagging and Cost Management Parameters: - ServiceTag - EnvironmentTag - ContactNetidTag - AccountNumberTag
  • SubAccountTag
- TicketNumberTag Parameters: VPC: Type: AWS::EC2::VPC::Id Description: The VPC to support ECS ASG instance capacity and ALB SshKeyName: Type: AWS::EC2::KeyPair::KeyName Description: The SSH Keypair for the ECS Instances Default: "uits-general-ecs-prod" InstanceSubnets: Type: List<AWS::EC2::Subnet::Id> Description: The private subnets for the application (2 or more) LBSubnets: Type: List<AWS::EC2::Subnet::Id> Description: private subnets for load balancer (2 or more)

ECS Settings

ECS Specific settings

EcsInstanceType: Description: ECS Instance AWS Server Type Type: String Default: "t2.small" AsgMaxSize: Description: Auto Scaling Group Max Inst Count (Will be used for Desired Count too) Type: String Default: 1 EcsAmi: Description: Parameter Store entry for latest ECS-optimized AMI Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> Default: /aws/service/ecs/optimized-ami/amazon-linux/recommended/image_id AllowedValues: - /aws/service/ecs/optimized-ami/amazon-linux/recommended/image_id LaunchTemplateVersion: Description: Version of the Launch Template to use. Incriment when doing Launch Template updates. Type: String Default: 1

Tags

The following tags are applied to all resources created by this template.

ServiceTag: Type: String Description: Exact name of the Service as defined in the service catalog. EnvironmentTag: Type: String Description: Used to distinguish between development, test, production,etc. environment types. AllowedValues: [dev, tst, prd, trn, stg, cfg, sup, rpt] Default: prd ContactNetidTag: Type: String Description: Used to identify the netid of the person most familiar with the usage of the resource. Default: fischerm AccountNumberTag: Type: String Description: Identifies the financial system account number. Default: 1192660

SubAccountTag: Type: String Description: Identifies the financial system sub account.

TicketNumberTag: Type: String Description: Used to identify the Jira, Cherwell, or other ticketing system ticket number to link to more information about the need for the resource. Resources:

ECS Instance IAM Policy and Role

This is the IAM role that will be applied to the ECS Instances. Any AWS specific permissions that the node might need should be defined here.

EnvInstanceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - sts:AssumeRole Path: "/" ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role

ECS Task IAM Policy and Role

This is the IAM role that will be applied to the ECS Tasks. Any AWS specific permissions that the task might need should be defined here.

InstanceManagedPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: "Grant access to CloudWatch Logs" ManagedPolicyName: !Sub "${AWS::StackName}-logs-access" PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - 'logs:CreateLogStream' - 'logs:PutLogEvents' Resource: '*' Roles: - Ref: "EnvInstanceRole" InstanceSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: 'UITS General Shared ECS instance members' VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: "tcp" FromPort: "22" ToPort: "22" CidrIp: "150.135.112.0/22" Description: "Infradev VPN" - IpProtocol: "tcp" FromPort: "22" ToPort: "22" CidrIp: "10.138.0.0/17" Description: "Mosaic VPN" - IpProtocol: "tcp" FromPort: "22" ToPort: "22" CidrIp: "128.196.130.211/32" Description: "ben.uits bastion host" - IpProtocol: "tcp" FromPort: "31000" ToPort: "61000" SourceSecurityGroupId: !Ref 'EcsAlbSecurityGroup' Description: Inbound Docker ports from ALB Tags: - Key: "Name" Value: !Sub "${AWS::StackName}-inst-sg" - Key: service Value: !Ref ServiceTag - Key: environment Value: !Ref EnvironmentTag - Key: contactnetid Value: !Ref ContactNetidTag - Key: accountnumber Value: !Ref AccountNumberTag - Key: ticketnumber Value: !Ref TicketNumberTag

Instance Profile

EnvInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: "/" Roles: - !Ref EnvInstanceRole

Load Balancer

The load balancer (ALB) constructor along with the Security Group that allows client traffic to the ALB on ports 80 & 443

EcsLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: !Sub "${AWS::StackName}-elbv2" Scheme: internet-facing Subnets: !Ref 'LBSubnets' LoadBalancerAttributes: - Key: idle_timeout.timeout_seconds Value: '50' SecurityGroups: - Ref: EcsAlbSecurityGroup Tags: - Key: Name Value: !Sub "${AWS::StackName}-LoadBalancer" - Key: service Value: !Ref ServiceTag - Key: environment Value: !Ref EnvironmentTag - Key: contactnetid Value: !Ref ContactNetidTag - Key: accountnumber Value: !Ref AccountNumberTag - Key: ticketnumber Value: !Ref TicketNumberTag EcsAlbSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: 'Allow external traffic to load balancer' VpcId: !Ref VPC SecurityGroupIngress: - CidrIp: 0.0.0.0/0 IpProtocol: "tcp" FromPort: "80" ToPort: "80" - CidrIp: 0.0.0.0/0 IpProtocol: "tcp" FromPort: "443" ToPort: "443" Tags: - Key: "Name" Value: !Sub "${AWS::StackName}-alb-sg" - Key: service Value: !Ref ServiceTag - Key: environment Value: !Ref EnvironmentTag - Key: contactnetid Value: !Ref ContactNetidTag - Key: accountnumber Value: !Ref AccountNumberTag - Key: ticketnumber Value: !Ref TicketNumberTag

ECS Cluster

EcsCluster: Type: AWS::ECS::Cluster Properties: ClusterName: !Sub "${AWS::StackName}"

Launch Template

Create an EC2 Launch Template for toolshed hosts

Ec2InstanceLaunchTemplate: Type: "AWS::EC2::LaunchTemplate" Properties: LaunchTemplateName: !Sub "${AWS::StackName}-launchtemplate" LaunchTemplateData: ImageId: !Ref EcsAmi KeyName: !Ref SshKeyName InstanceType: !Ref EcsInstanceType IamInstanceProfile: Name: !Ref EnvInstanceProfile NetworkInterfaces: - AssociatePublicIpAddress: "false" DeviceIndex: "0" Groups: - !Ref InstanceSG TagSpecifications: - ResourceType: volume Tags: - Key: service Value: !Ref ServiceTag - Key: environment Value: !Ref EnvironmentTag - Key: contactnetid Value: !Ref ContactNetidTag - Key: accountnumber Value: !Ref AccountNumberTag - Key: ticketnumber Value: !Ref TicketNumberTag - ResourceType: instance Tags: - Key: service Value: !Ref ServiceTag - Key: environment Value: !Ref EnvironmentTag - Key: contactnetid Value: !Ref ContactNetidTag - Key: accountnumber Value: !Ref AccountNumberTag - Key: ticketnumber Value: !Ref TicketNumberTag UserData: Fn::Base64: !Sub | #!/bin/bash echo ECS_CLUSTER=${AWS::StackName} >> /etc/ecs/ecs.config

Auto Scaling Group

Define the ASG for the ECS Cluster Instances

EcsInstanceAsg: Type: AWS::AutoScaling::AutoScalingGroup DependsOn: EcsCluster Properties: VPCZoneIdentifier: !Ref 'InstanceSubnets' LaunchTemplate: LaunchTemplateId: !Ref Ec2InstanceLaunchTemplate Version: !Ref LaunchTemplateVersion MinSize: '0' MaxSize: !Ref AsgMaxSize DesiredCapacity: !Ref AsgMaxSize Tags: - Key: service Value: !Ref ServiceTag PropagateAtLaunch: False - Key: environment Value: !Ref EnvironmentTag PropagateAtLaunch: False - Key: contactnetid Value: !Ref ContactNetidTag PropagateAtLaunch: False - Key: accountnumber Value: !Ref AccountNumberTag PropagateAtLaunch: False - Key: ticketnumber Value: !Ref TicketNumberTag PropagateAtLaunch: False Outputs: VPCID: Description: The VPC for this Cluster Value: !Ref VPC Export: Name: !Sub "${AWS::StackName}-vpcid" EcsCluster: Description: The ECS Cluster Value: !Ref EcsCluster Export: Name: !Sub "${AWS::StackName}-cluster" EcsLoadBalancer: Description: The ALB itself Value: !Ref EcsLoadBalancer Export: Name: !Sub "${AWS::StackName}-alb" EcsLoadBalancerName: Description: The ALB Internal DNS Name Value: !GetAtt EcsLoadBalancer.DNSName Export: Name: !Sub "${AWS::StackName}-alb-name"