简体   繁体   English

AWS ELB:503 服务暂时不可用

[英]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

SG egress rules SG 出口规则

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 也需要出口规则。

IAM我是

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,使用它应该会更好。

  • Service-Linked Role for Amazon ECS Amazon ECS 的服务相关角色

    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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM