依赖:本文需要了解AWS 架构设计基础知识
AWS Fargate
AWS Fargate 是可与 Amazon ECS 结合使用的技术,使您在运行容器时不必管理 Amazon EC2 实例的服务器或集群。使用 Fargate,您不必再预配置、配置或扩展虚拟机集群即可运行容器。这样一来,您就无需再选择服务器类型、确定扩展集群的时间和优化集群打包。
AWS ECS
Amazon Elastic Container Service(Amazon ECS)是一个高度可扩展的快速容器管理服务。您可以使用它来运行、停止和管理集群上的容器。使用 Amazon ECS,您的容器是在用于运行单个任务或服务内任务的任务定义中定义的。在此上下文中,服务是一种配置,您可以使用它在集群中同时运行和维护指定数量的任务。您可以在由 AWS Fargate 托管的无服务器基础设施上运行任务和服务。或者,为了更好地控制您的基础设施,您可以在托管的 Amazon EC2 实例集群上运行任务和服务。
附加策略
AmazonECSTaskExecutionRolePolicy
AmazonSSMFullAccess
EC2InstanceProfileForImageBuilderECRContainerBuilds
AmazonECS_FullAccess
AmazonS3FullAccess
AmazonSNSFullAccess
CloudWatchFullAccess
信任关系
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ecs-tasks.amazonaws.com",
"apigateway.amazonaws.com",
"ecs.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
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
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
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"