[英]AWS ELB: 503 Service Temporarily Unavailable
I am trying to deploy microservices to AWS ECS following this example repo .我正在尝试按照此示例repo将微服务部署到 AWS ECS。 Here, a load balancer is utilized for networking between different docker services.
在这里,负载均衡器用于不同 docker 服务之间的网络。 I have adjusted the cloudformation templates to my needs and have only deployed one service yet, the webserver.
我已经根据我的需要调整了 cloudformation 模板,并且只部署了一项服务,即网络服务器。 I want public access to the web interface and add other services this service is talking to subsequently.
我希望公开访问 Web 界面并添加此服务随后与之通信的其他服务。 However, I currently struggle to get the webserver going using the URL of the load balancer.
但是,我目前正在努力使用负载均衡器的 URL 来启动网络服务器。 If I go directly to the EC2 instance using the public IP, I get access to the interface.
如果我使用公共 IP 直接访问 EC2 实例,则可以访问该接口。 However, if I go to the load balancer DNS, I get
503 Service Temporarily Unavailable
.但是,如果我转到负载均衡器 DNS,则会收到
503 Service Temporarily Unavailable
。 I have checked the AWS docs , but the webservice target group shows a registered target (the EC2 instance) with status healthy
.我检查了AWS文档,但Web服务的目标群体表演的注册目标(EC2实例),状态
healthy
。 What am I missing?我错过了什么?
Parameters:
EnvironmentName:
Description: An environment name that will be prefixed to resource names
Type: String
VPC:
Type: AWS::EC2::VPC::Id
Description: Choose which VPC the Application Load Balancer should be deployed to
Subnets:
Description: Choose which subnets the Application Load Balancer should be deployed to
Type: AWS::EC2::Subnet::Id
PublicSubnet:
Description: Choose which public subnet the EC2 instance should be deployed to
Type: AWS::EC2::Subnet::Id
Resources:
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${EnvironmentName}-loadbalancer
GroupDescription: Access to the load balancer that sits in front of ECS
VpcId: !Ref VPC
SecurityGroupIngress:
# Allow access from anywhere to our ECS services
- CidrIp: 0.0.0.0/0
IpProtocol: -1
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-LoadBalancers
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Ref EnvironmentName
Subnets:
- !Ref Subnets
SecurityGroups:
- !Ref LoadBalancerSecurityGroup
Tags:
- Key: Name
Value: !Ref EnvironmentName
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref LoadBalancer
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref DefaultTargetGroup
DefaultTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub ${EnvironmentName}-default
VpcId: !Ref VPC
Port: 80
Protocol: HTTP
ECSHostSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${EnvironmentName}-ecs-hosts
GroupDescription: Access to the ECS hosts and the tasks/containers that run on them
VpcId: !Ref VPC
SecurityGroupIngress:
# Only allow inbound access to ECS from the ELB
- SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup
IpProtocol: -1
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-ECS-Hosts
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Ref EnvironmentName
ECSRole:
Type: AWS::IAM::Role
Properties:
Path: /
RoleName: !Sub ${EnvironmentName}-ecs-role
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role'
- 'arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM'
- 'arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy'
ECSInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref ECSRole
EC2Webserver:
Type: AWS::EC2::Instance
Properties:
AvailabilityZone: eu-central-1a
ImageId: !Ref ECSAMI
InstanceType: !Ref InstanceType
IamInstanceProfile: !Ref ECSInstanceProfile
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
# Add to cluster:
echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
echo ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE=true >> /etc/ecs/ecs.config
SecurityGroupIds:
- !Ref ECSHostSecurityGroup
SubnetId: !Ref PublicSubnet
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}
Service:
Type: AWS::ECS::Service
DependsOn: ListenerRule
Properties:
Cluster: !Ref Cluster
Role: !Ref ServiceRole
DesiredCount: !Ref DesiredCount
TaskDefinition: !Ref TaskDefinitionWebserver
LoadBalancers:
- ContainerName: !Sub ${EnvironmentName}-webserver
ContainerPort: 8080
TargetGroupArn: !Ref TargetGroup
TaskDefinitionWebserver:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Sub ${EnvironmentName}-webserver
ContainerDefinitions:
- Name: !Sub ${EnvironmentName}-webserver
Essential: true
Image: !Ref Image
Memory: 512
PortMappings:
- ContainerPort: 8080
HostPort: 80
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub ${EnvironmentName}-webserver
VpcId: !Ref VPC
Port: 80
Protocol: HTTP
Matcher:
HttpCode: 200-299
HealthCheckIntervalSeconds: 30
HealthCheckPath: /health
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
ListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
ListenerArn: !Ref LoadBalancerListener
Priority: 1
Conditions:
- Field: path-pattern
Values:
- /
Actions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
ServiceRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ecs-service-${AWS::StackName}
Path: /
AssumeRolePolicyDocument: |
{
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": [ "ecs.amazonaws.com" ]},
"Action": [ "sts:AssumeRole" ]
}]
}
Policies:
- PolicyName: !Sub ecs-service-${AWS::StackName}
PolicyDocument:
{
"Version": "2012-10-17",
"Statement":
[
{
"Effect": "Allow",
"Action":
[
"ec2:AuthorizeSecurityGroupIngress",
"ec2:Describe*",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:Describe*",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:RegisterTargets"
],
"Resource": "*"
}
]
}
Outputs:
WebsiteServiceUrl:
Description: The URL endpoint for the website service
Value: !Join ["", [!GetAtt LoadBalancer.DNSName, "/"]]
Thanks everyone!谢谢大家! I finally figured it out, what I had to do was adjusting the path as my service redirects on
/
.我终于想通了,我必须做的是在我的服务重定向到
/
时调整路径。 So I only changed the listener rule using a wildcard:所以我只使用通配符更改了侦听器规则:
ListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
ListenerArn: !Ref LoadBalancerListener
Priority: 1
Conditions:
- Field: path-pattern
Values:
- [/*]
Actions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
It looks the Security Groups (SG) has no egress rule defined.看起来安全组 (SG) 没有定义出口规则。 Both ALB and EC2.
ALB 和 EC2。
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${EnvironmentName}-loadbalancer
GroupDescription: Access to the load balancer that sits in front of ECS
VpcId: !Ref VPC
SecurityGroupIngress:
# Allow access from anywhere to our ECS services
- CidrIp: 0.0.0.0/0
IpProtocol: -1
I believe when you look at the outbound rules of the SG in the EC2 console, there would be no rule.相信你在EC2控制台看SG的出站规则,应该是没有规则的。 If this is true, then the cause would be that traffic can come in to port 80 of ALB, but it cannot go out from ALB,
如果这是真的,那么原因是流量可以进入 ALB 的 80 端口,但不能从 ALB 出去,
This is my theory.这是我的理论。 So please add a egress rule to verify?
所以请添加一个出口规则来验证?
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${EnvironmentName}-loadbalancer
GroupDescription: Access to the load balancer that sits in front of ECS
VpcId: !Ref VPC
SecurityGroupIngress:
# Allow access from anywhere to our ECS services
- CidrIp: 0.0.0.0/0
IpProtocol: -1
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0 # <--- Maybe better change to VPC CIDR or ECS/EC2 subnet CIDR rather than any IP.
Regarding EC2, because SG is stateful, traffic can go through port 80 to reach the port 8080 of the docker container, and the response can go back through the SG because the SG knows it is the response of the incoming connection.关于EC2,因为SG是有状态的,流量可以通过80端口到达docker容器的8080端口,响应可以通过SG返回,因为SG知道是传入连接的响应。
Whereas for ALB, the incoming connection from the Internet is terminated at ALB port 80, then a new outbound connection needs to be established to EC2 instance(s) port 80, hence needs an egress rule defined, if I am correct.而对于 ALB,来自 Internet 的传入连接在 ALB 端口 80 处终止,然后需要建立到 EC2 实例端口 80 的新出站连接,因此需要定义一个出口规则,如果我是正确的。
ECSHostSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${EnvironmentName}-ecs-hosts
GroupDescription: Access to the ECS hosts and the tasks/containers that run on them
VpcId: !Ref VPC
SecurityGroupIngress:
# Only allow inbound access to ECS from the ELB
- SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup
IpProtocol: -1
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
However, if the EC2 instances need to install packages or create an outbound connection, then the EC2 SG needs egress rules too.但是,如果 EC2 实例需要安装包或创建出站连接,则 EC2 SG 也需要出口规则。
Regarding the IAM role for the ECS service, there are pre-defined AWS managed role, so I suppose better to use them?关于 ECS 服务的 IAM 角色,有预定义的 AWS 托管角色,所以我想更好地使用它们?
"Role": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2008-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
},
"ManagedPolicyArns": ["arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceRole"]
}
}
As AWS has introduced Service Linked Role now, it should be even better to use it.由于 AWS 现在引入了 Service Linked Role,使用它应该会更好。
Prior to the introduction of a service-linked role for Amazon ECS, you were required to create an IAM role for your Amazon ECS services which granted Amazon ECS the permission it needed.
在为 Amazon ECS 引入服务相关角色之前,您需要为 Amazon ECS 服务创建一个 IAM 角色,该角色授予 Amazon ECS 所需的权限。 This role is no longer required, however it is available if needed.
不再需要此角色,但可以在需要时使用。 For more information, see Legacy IAM Roles for Amazon ECS.
有关更多信息,请参阅 Amazon ECS 的旧 IAM 角色。
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.