繁体   English   中英

AWS ELB:503 服务暂时不可用

[英]AWS ELB: 503 Service Temporarily Unavailable

我正在尝试按照此示例repo将微服务部署到 AWS ECS。 在这里,负载均衡器用于不同 docker 服务之间的网络。 我已经根据我的需要调整了 cloudformation 模板,并且只部署了一项服务,即网络服务器。 我希望公开访问 Web 界面并添加此服务随后与之通信的其他服务。 但是,我目前正在努力使用负载均衡器的 URL 来启动网络服务器。 如果我使用公共 IP 直接访问 EC2 实例,则可以访问该接口。 但是,如果我转到负载均衡器 DNS,则会收到503 Service Temporarily Unavailable 我检查了AWS文档,但Web服务的目标群体表演的注册目标(EC2实例),状态healthy 我错过了什么?

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, "/"]]

谢谢大家! 我终于想通了,我必须做的是在我的服务重定向到/时调整路径。 所以我只使用通配符更改了侦听器规则:

ListenerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      ListenerArn: !Ref LoadBalancerListener
      Priority: 1
      Conditions:
        - Field: path-pattern
          Values:
            - [/*]
      Actions:
        - TargetGroupArn: !Ref TargetGroup
          Type: forward

SG 出口规则

看起来安全组 (SG) 没有定义出口规则。 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

相信你在EC2控制台看SG的出站规则,应该是没有规则的。 如果这是真的,那么原因是流量可以进入 ALB 的 80 端口,但不能从 ALB 出去,

这是我的理论。 所以请添加一个出口规则来验证?

  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.

关于EC2,因为SG是有状态的,流量可以通过80端口到达docker容器的8080端口,响应可以通过SG返回,因为SG知道是传入连接的响应。

而对于 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

但是,如果 EC2 实例需要安装包或创建出站连接,则 EC2 SG 也需要出口规则。

我是

关于 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"]
      }
    }

由于 AWS 现在引入了 Service Linked Role,使用它应该会更好。

  • Amazon ECS 的服务相关角色

    在为 Amazon ECS 引入服务相关角色之前,您需要为 Amazon ECS 服务创建一个 IAM 角色,该角色授予 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