AWS design high availability program architecture - ECS Cloudformation

Dependency: This article requires an understanding of the basics of AWS architecture design

AWS Fargate

AWS Fargate is a technology that works with Amazon ECS so that you don't have to manage a server or cluster of Amazon EC2 instances to run containers . With Fargate, you no longer have to provision, provision, or scale a cluster of virtual machines to run containers. This eliminates the need to choose server types, determine when to scale your cluster, and optimize cluster packaging.

AWS ECS

Amazon Elastic Container Service (Amazon ECS) is a highly scalable fast container management service. You can use it to run, stop, and manage containers on your cluster. With Amazon ECS, your containers are defined in task definitions that run individual tasks or tasks within a service. In this context, a service is a configuration that you can use to run and maintain a specified number of tasks concurrently in a cluster. You can run tasks and services on serverless infrastructure managed by AWS Fargate. Or, for greater control over your infrastructure, you can run tasks and services on managed clusters of Amazon EC2 instances.

Create an IAM role

additional strategy

AmazonECSTaskExecutionRolePolicy
AmazonSSMFullAccess
EC2InstanceProfileForImageBuilderECRContainerBuilds
AmazonECS_FullAccess
AmazonS3FullAccess
AmazonSNSFullAccess
CloudWatchFullAccess

trust relationship

{
    
    
    "Version": "2012-10-17",
    "Statement": [
        {
    
    
            "Effect": "Allow",
            "Principal": {
    
    
                "Service": [
                    "ecs-tasks.amazonaws.com",
                    "apigateway.amazonaws.com",
                    "ecs.amazonaws.com"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

Create ECR

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  Environment:
        Type: String
        Default: DEV
  EnvironmentName:
    Type: String
    Default: d
  CustomerName:
    Description: The name of the customer
    Type: String
    #TODO:
    Default: your-company-name
  ProjectName:
    Description: The name of the project
    Type: String
    #TODO:
    Default: your-project-name
Resources:
  Repository:
    Type: AWS::ECR::Repository
    Properties:
      RepositoryName:
        !Join [ "-", [ !Ref CustomerName, !Ref ProjectName, your-Repository-name, !Ref EnvironmentName, "ecr", ], ]
      Tags:
        - Key: ApplName
          Value: your-app-name

Create a Cluster

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  Environment:
    Type: String
    Default: DEV
  EnvironmentName:
    Type: String
    Default: d
  CustomerName:
    Description: The name of the customer
    Type: String
    #TODO:
    Default:  your-company-name
  ProjectName:
    Description: The name of the project
    Type: String
    #TODO:
    Default: your-project-name
  ContainerInsights:
    Type: String
    AllowedValues:
      - enabled
      - disabled
    #HACK:Development environment is disabled, production environment is enabled
    Default: disabled
Resources:
  Cluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterSettings:
        - Name: containerInsights
          Value: !Ref ContainerInsights
      ClusterName: !Join [ '-', [ !Ref CustomerName, !Ref ProjectName, !Ref EnvironmentName, 'cluster'] ]
      Tags:
        - Key: ApplName
          Value: your-app-name

Create ECS

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  Environment:
    Type: String
    Default: DEV
  EnvironmentName:
    Type: String
    AllowedValues:
    Default: d
  SubProjectName:
    Description: The name of the sub project
    Type: String
    #TODO:
    Default: your-subsystem-name
  CustomerName:
    Description: The name of the customer
    Type: String
    #TODO:
    Default: your-company-name
  ProjectName:
    Description: The name of the project
    Type: String
    #TODO:
    Default: your-project-name
  ProjectType:
    Type: String
    #TODO:
    Default: your-domain-name
  HostedZoneName:
    Description: The name of route53 hosted
    Type: String
    #TODO:
    Default: dev.xxx.cn.
  ServiceSubnetIds:
    Description: The subnet ids of the ECS service
    Type: List<AWS::EC2::Subnet::Id>
    #TODO:
    Default: subnet-xxxxxxx,subnet-xxxxxxx
  VPCID:
    Type: AWS::EC2::VPC::Id
    #TODO:
    Default: vpc-xxxxxxxx
  FargateSecurityGroups:
    Description: security groups for fargate
    Type: List<AWS::EC2::SecurityGroup::Id>
    #TODO:
    Default: sg-xxxxxxxx
  S3BktName:
    Type: String
    Default: ""
  Cpu:
    Type: Number
    Default: 512
  Memory:
    Type: Number
    Default: 1024
  CFDomain:
    Type: String
    #TODO:
    Default: "https://www.xxxx.com.cn/"
  ALBSubnetsIds:
    Description: The subnet ids of the ALB
    Type:
      List<AWS::EC2::Subnet::Id>
    #TODO: 
    Default: subnet-xxxxxxx, subnet-xxxxxxxx
  AlbSecurityGroups:
    Description: Security group for ALB
    Type:
      List<AWS::EC2::SecurityGroup::Id>
      #TODO:
    Default: sg-xxxxxxxx
  AutoScalingRoleARN:
    Type: String
    Default: AWSServiceRoleForApplicationAutoScaling_xxxxxxx
  Certificate:
    Type:
      String
      #TODO:
    Default: xxxxx-xxxx-xxxx-xxxx-xxxxxxxxx
Resources:
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub '/ecs/${CustomerName}-${ProjectName}-${SubProjectName}-${EnvironmentName}-task'
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Tags:
        - Key: ApplName
          Value: your-app-name
      Family:
        !Join [ "-", [ !Ref CustomerName, !Ref ProjectName, !Ref SubProjectName, !Ref EnvironmentName, "task", ], ]
      Cpu: !Ref Cpu
      Memory: !Ref Memory
      NetworkMode: awsvpc
      ExecutionRoleArn: !Sub arn:aws-cn:iam::${
    
    AWS::AccountId}:role/${
    
    CustomerName}-${
    
    ProjectName}-ecs-task-role-${
    
    EnvironmentName}-iamr
      TaskRoleArn: !Sub arn:aws-cn:iam::${
    
    AWS::AccountId}:role/${
    
    CustomerName}-${
    
    ProjectName}-ecs-task-role-${
    
    EnvironmentName}-iamr
      ContainerDefinitions:
        - Name:
            !Join [ "-", [ !Ref CustomerName, !Ref ProjectName, !Ref SubProjectName,  !Ref EnvironmentName, "container", ],  ]
          Image: !Sub ${
    
    AWS::AccountId}.dkr.ecr.${
    
    AWS::Region}.amazonaws.com.cn/${
    
    CustomerName}-${
    
    ProjectName}-${
    
    SubProjectName}-${
    
    EnvironmentName}-ecr:latest
          PortMappings:
            - ContainerPort: 80
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-region: !Ref 'AWS::Region'
              awslogs-group:  !Ref LogGroup
              awslogs-stream-prefix: ecs
          Environment:
            - Name: ECS_ROLE_ARN
              Value: !Sub arn:aws-cn:iam::${
    
    AWS::AccountId}:role/${
    
    CustomerName}-${
    
    ProjectName}-ecs-task-role-${
    
    EnvironmentName}-iamr
            - Name: S3_BKT_NAME
              Value: !Ref S3BktName
            - Name: CF_DOMAIN
              Value: !Ref CFDomain
      RequiresCompatibilities:
        - FARGATE
  Service:
    Type: AWS::ECS::Service
    DependsOn:
      - LoadBalancerListenerHTTP
      - LoadBalancerListenerHTTPS
    Properties:
      Tags:
        - Key: ApplName
          Value: your-app-name
      PropagateTags: TASK_DEFINITION
      ServiceName:
        !Join [ "-", [ !Ref CustomerName, !Ref ProjectName, !Ref SubProjectName, !Ref EnvironmentName, "service", ], ]
      Cluster: !Sub arn:aws-cn:ecs:${
    
    AWS::Region}:${
    
    AWS::AccountId}:cluster/${
    
    CustomerName}-${
    
    ProjectName}-${
    
    EnvironmentName}-cluster
      TaskDefinition: !Ref TaskDefinition
      DeploymentConfiguration:
        MinimumHealthyPercent: 100
        MaximumPercent: 200
        #CircuitBreaker Use
        DeploymentCircuitBreaker:
          Enable: True
          Rollback: True
      DesiredCount: 1
      LaunchType: FARGATE
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: DISABLED
          Subnets: !Ref ServiceSubnetIds
          SecurityGroups: !Ref FargateSecurityGroups
      LoadBalancers:
        - ContainerName: !Join [ "-",  [ !Ref CustomerName, !Ref ProjectName, !Ref SubProjectName, !Ref EnvironmentName, "container", ], ]
          ContainerPort: 80
          TargetGroupArn: !Ref TargetGroup
  AutoScalingTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MinCapacity: 1
      MaxCapacity: 5
      ResourceId: !Sub service/${
    
    CustomerName}-${
    
    ProjectName}-${
    
    EnvironmentName}-cluster/${
    
    Service.Name}
      ScalableDimension: ecs:service:DesiredCount
      ServiceNamespace: ecs
      RoleARN: !Sub arn:aws-cn:iam::${
    
    AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/${
    
    AutoScalingRoleARN}
  AutoScalingPolicyCPU:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    DependsOn: AutoScalingTarget
    Properties:
      PolicyName:
        !Join [ "-", [ !Ref CustomerName, !Ref ProjectName, !Ref SubProjectName, !Ref EnvironmentName, "autoscaling-policy-cpu", ], ]
      PolicyType: TargetTrackingScaling
      ScalingTargetId: !Ref AutoScalingTarget
      TargetTrackingScalingPolicyConfiguration:
        PredefinedMetricSpecification:
          PredefinedMetricType: ECSServiceAverageCPUUtilization
        ScaleInCooldown: 10
        ScaleOutCooldown: 10
        TargetValue: 50
  AutoScalingPolicyMemory:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    DependsOn: AutoScalingTarget
    Properties:
      PolicyName: !Join [ "-", [ !Ref CustomerName, !Ref ProjectName, !Ref SubProjectName, !Ref EnvironmentName, "autoscaling-policy-mem", ], ]
      PolicyType: TargetTrackingScaling
      ScalingTargetId: !Ref AutoScalingTarget
      TargetTrackingScalingPolicyConfiguration:
        PredefinedMetricSpecification:
          PredefinedMetricType: ECSServiceAverageMemoryUtilization
        ScaleInCooldown: 10
        ScaleOutCooldown: 10
        TargetValue: 50
  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Join [ "-", [ !Ref CustomerName, !Ref ProjectName, !Ref SubProjectName, !Ref EnvironmentName, "group", ], ]
      HealthCheckEnabled: true
      HealthCheckIntervalSeconds: 60
      HealthCheckPath: /healthcheck
      HealthCheckPort: 80
      HealthCheckProtocol: HTTP
      Port: 80
      Protocol: HTTP
      HealthCheckTimeoutSeconds: 30
      HealthyThresholdCount: 3
      Tags:
        - Key: ApplName
          Value: your-app-name
      TargetType: ip
      VpcId: !Ref VPCID
  LoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Tags:
        - Key: ApplName
          Value: your-app-name
      Name: !Join [ "-", [ !Ref CustomerName, !Ref ProjectName, !Ref SubProjectName, !Ref EnvironmentName, "alb", ], ]
      Subnets: !Ref ALBSubnetsIds
      SecurityGroups: !Ref AlbSecurityGroups
  LoadBalancerListenerHTTP:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref LoadBalancer
      Port: 80
      Protocol: HTTP
      DefaultActions:
        - Type: "redirect"
          RedirectConfig:
            Protocol: "HTTPS"
            Port: 443
            Host: "#{host}"
            Path: "/#{path}"
            Query: "#{query}"
            StatusCode: "HTTP_301"
  LoadBalancerListenerHTTPS:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref TargetGroup
          Type: forward
      LoadBalancerArn: !Ref LoadBalancer
      Port: 443
      Protocol: HTTPS
      SslPolicy: ELBSecurityPolicy-TLS-1-2-2017-01
      Certificates:
        - CertificateArn: !Sub arn:aws-cn:acm:${
    
    AWS::Region}:${
    
    AWS::AccountId}:certificate/${
    
    Certificate}
  Rount53DNSRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneName: !Ref HostedZoneName
      Comment: subsystem DNS.
      Name: !Sub ${
    
    ProjectName}${
    
    ProjectType}.${
    
    HostedZoneName}
      Type: A
      AliasTarget:
        HostedZoneId: !GetAtt "LoadBalancer.CanonicalHostedZoneID"
        DNSName: !GetAtt "LoadBalancer.DNSName"

Guess you like

Origin blog.csdn.net/black0707/article/details/124981984