Amazon web services AWS网络负载平衡器,每个AZ中都没有目标

Amazon web services AWS网络负载平衡器,每个AZ中都没有目标,amazon-web-services,networking,amazon-ec2,nlb,Amazon Web Services,Networking,Amazon Ec2,Nlb,在AWS网络负载平衡器文档中指出,当为目标组指定实例时,它必须在负载平衡器注册的每个AZ中包含一个实例。这是不强制执行的 如果在3个AZ中注册了NLB,但在AZ1中只注册了一个目标EC2实例,那么流量会发生什么变化?如果启用交叉负载平衡,会有什么不同吗 如果在3个AZ中注册了NLB,但在AZ1中只注册了一个目标EC2实例,那么流量会发生什么变化?如果启用交叉负载平衡,会有什么不同吗 在这个特定场景中(3个AZ中的NLB,1个AZ中的单个实例),实际上什么都没有发生。从最终用户的角度来看,有无跨区

在AWS网络负载平衡器文档中指出,当为目标组指定实例时,它必须在负载平衡器注册的每个AZ中包含一个实例。这是不强制执行的

如果在3个AZ中注册了NLB,但在AZ1中只注册了一个目标EC2实例,那么流量会发生什么变化?如果启用交叉负载平衡,会有什么不同吗

如果在3个AZ中注册了NLB,但在AZ1中只注册了一个目标EC2实例,那么流量会发生什么变化?如果启用交叉负载平衡,会有什么不同吗

在这个特定场景中(3个AZ中的NLB,1个AZ中的单个实例),实际上什么都没有发生。从最终用户的角度来看,有无跨区域负载平衡没有明显的差异。在任何一种情况下都可以访问该实例

为了验证这一点,我开发了一个简单的CloudFormation模板,创建NLB,有无跨区域负载平衡,以及1个实例。该模板允许使用NLB、跨区域和实例位置的不同设置进行轻松的实验。我在
us-east-1
区域和默认VPC中使用了该模板

对于您指定的模板,有几个参数,包括:

  • NLBSubnetsIds—用于启用NLB的子网。您必须首先在控制台中检查,哪些子网在哪个AZ中

  • InstanceSubnetId—实例的子网。同样,如果您想使用实例位置,可以检查哪个子网在哪个子网中。您必须确保实例是在为NLB设置的AZs之一中创建的

  • CrossZoneEnabled-为NLB启用或禁用跨区域平衡

从模板和实例运行状况检查通行证创建堆栈后(可能需要1或2分钟),您可以在浏览器中访问NLB DNS以查看实例上托管的示例网页

---

Parameters:

  VpcId:
    Type: AWS::EC2::VPC::Id
    
  NLBSubnetsIds:
    Type: List<AWS::EC2::Subnet::Id>
    
  InstanceSubnetId:
    Type: AWS::EC2::Subnet::Id 
    
  AmazonLinux2AMIId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
    
  CrossZoneEnabled:
    Type: String  
    Default: false
    AllowedValues: [true, false]

Resources:


  BasicSecurityGroup:                                                        
      Type: AWS::EC2::SecurityGroup                                          
      Properties: 
        GroupDescription: Enable www port
        SecurityGroupIngress:
          - IpProtocol: tcp
            FromPort: 80
            ToPort: 80
            CidrIp: 0.0.0.0/0            
        VpcId:  !Ref VpcId

  MyInstance1:
    Type: AWS::EC2::Instance

    CreationPolicy:
        ResourceSignal:
          Timeout: PT5M
                
    Properties:                
      ImageId: !Ref AmazonLinux2AMIId  
      InstanceType: t2.micro        
      Monitoring: false
      SecurityGroupIds: [!Ref BasicSecurityGroup]
      SubnetId: !Ref InstanceSubnetId
      UserData: 
        Fn::Base64: !Sub |
            #!/bin/bash -xe

            yum install -y httpd aws-cfn-bootstrap

            echo "<h2>Hello world from $(hostname -f)</h2>" \
              > /var/www/html/index.html

            systemctl start httpd

            # check if website is working
            curl -s localhost | grep "Hello"

            # Signal the status from cfn-init
            /opt/aws/bin/cfn-signal -e $? \
                --stack ${AWS::StackName} \
                --resource MyInstance1 \
                --region ${AWS::Region}
                
                
  MyNLB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties: 
      IpAddressType: ipv4
      LoadBalancerAttributes:  
        - Key: load_balancing.cross_zone.enabled
          Value: !Ref CrossZoneEnabled
      Scheme: internet-facing 
      Subnets: !Ref NLBSubnetsIds
      Type: network
      
  MyListner1:      
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties: 
      DefaultActions: 
        - TargetGroupArn: !Ref MyTargetGroup
          Type: forward 
      LoadBalancerArn: !Ref MyNLB
      Port: 80 
      Protocol: TCP 

  MyTargetGroup: 
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties: 
      HealthCheckEnabled: true
      HealthCheckIntervalSeconds: 10
      HealthCheckPath: /
      HealthCheckProtocol: HTTP 
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 2
      Port: 80
      Protocol: TCP 
      TargetGroupAttributes: 
        - Key: deregistration_delay.timeout_seconds
          Value: 30
      Targets:
        - Id: !Ref MyInstance1
          Port: 80
      TargetType: instance 
      VpcId: !Ref VpcId
      
      
Outputs:
    
  DNSName:
    Value: !GetAtt MyNLB.DNSName
---
参数:
VpcId:
类型:AWS::EC2::VPC::Id
NLBSubnetSID:
类型:不同AZ中的列表。在这种情况下,跨区域平衡允许所有实例获得大致相同的流量。如果没有跨区域的平衡,一个孤立的实例将获得比另一个AZ中的实例集合多得多的流量

您可以使用第二个模板检查区域平衡的效果。模板与以前几乎相同,但现在1个AZ将有3个实例,而另一个将有1个AZ

---

Parameters:

  VpcId:
    Type: AWS::EC2::VPC::Id
    
  NLBSubnetsIds:
    Type: List<AWS::EC2::Subnet::Id>
    
  InstanceSubnetId1:
    Type: AWS::EC2::Subnet::Id 

  InstanceSubnetId2:
    Type: AWS::EC2::Subnet::Id     
    
  AmazonLinux2AMIId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
    
  CrossZoneEnabled:
    Type: String  
    Default: false
    AllowedValues: [true, false]

Resources:


  BasicSecurityGroup:                                                        
      Type: AWS::EC2::SecurityGroup                                          
      Properties: 
        GroupDescription: Enable www port
        SecurityGroupIngress:
          - IpProtocol: tcp
            FromPort: 80
            ToPort: 80
            CidrIp: 0.0.0.0/0            
        VpcId:  !Ref VpcId

  MyInstance1:
    Type: AWS::EC2::Instance

    CreationPolicy:
        ResourceSignal:
          Timeout: PT3M
                
    Properties:                
      ImageId: !Ref AmazonLinux2AMIId  
      InstanceType: t2.micro        
      Monitoring: false
      SecurityGroupIds: [!Ref BasicSecurityGroup]
      SubnetId: !Ref InstanceSubnetId1
      UserData: 
        Fn::Base64: !Sub |
            #!/bin/bash -xe

            yum install -y httpd aws-cfn-bootstrap

            echo "<h2>Hello world from $(hostname -f)</h2>" \
              > /var/www/html/index.html

            systemctl start httpd

            # check if website is working
            curl -s localhost | grep "Hello"

            # Signal the status from cfn-init
            /opt/aws/bin/cfn-signal -e $? \
                --stack ${AWS::StackName} \
                --resource MyInstance1 \
                --region ${AWS::Region}
                

  MyInstance2:
    Type: AWS::EC2::Instance

    CreationPolicy:
        ResourceSignal:
          Timeout: PT3M
                
    Properties:                
      ImageId: !Ref AmazonLinux2AMIId  
      InstanceType: t2.micro        
      Monitoring: false
      SecurityGroupIds: [!Ref BasicSecurityGroup]
      SubnetId: !Ref InstanceSubnetId2
      UserData: 
        Fn::Base64: !Sub |
            #!/bin/bash -xe

            yum install -y httpd aws-cfn-bootstrap

            echo "<h2>Hello2 world from $(hostname -f)</h2>" \
              > /var/www/html/index.html

            systemctl start httpd

            # check if website is working
            curl -s localhost | grep "Hello"

            # Signal the status from cfn-init
            /opt/aws/bin/cfn-signal -e $? \
                --stack ${AWS::StackName} \
                --resource MyInstance2 \
                --region ${AWS::Region}


  MyInstance3:
    Type: AWS::EC2::Instance

    CreationPolicy:
        ResourceSignal:
          Timeout: PT3M
                
    Properties:                
      ImageId: !Ref AmazonLinux2AMIId  
      InstanceType: t2.micro        
      Monitoring: false
      SecurityGroupIds: [!Ref BasicSecurityGroup]
      SubnetId: !Ref InstanceSubnetId2
      UserData: 
        Fn::Base64: !Sub |
            #!/bin/bash -xe

            yum install -y httpd aws-cfn-bootstrap

            echo "<h2>Hello2 world from $(hostname -f)</h2>" \
              > /var/www/html/index.html

            systemctl start httpd

            # check if website is working
            curl -s localhost | grep "Hello"

            # Signal the status from cfn-init
            /opt/aws/bin/cfn-signal -e $? \
                --stack ${AWS::StackName} \
                --resource MyInstance3 \
                --region ${AWS::Region}


  MyInstance4:
    Type: AWS::EC2::Instance

    CreationPolicy:
        ResourceSignal:
          Timeout: PT3M
                
    Properties:                
      ImageId: !Ref AmazonLinux2AMIId  
      InstanceType: t2.micro        
      Monitoring: false
      SecurityGroupIds: [!Ref BasicSecurityGroup]
      SubnetId: !Ref InstanceSubnetId2
      UserData: 
        Fn::Base64: !Sub |
            #!/bin/bash -xe

            yum install -y httpd aws-cfn-bootstrap

            echo "<h2>Hello2 world from $(hostname -f)</h2>" \
              > /var/www/html/index.html

            systemctl start httpd

            # check if website is working
            curl -s localhost | grep "Hello"

            # Signal the status from cfn-init
            /opt/aws/bin/cfn-signal -e $? \
                --stack ${AWS::StackName} \
                --resource MyInstance4 \
                --region ${AWS::Region}                
                
  MyNLB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties: 
      IpAddressType: ipv4
      LoadBalancerAttributes:  
        - Key: load_balancing.cross_zone.enabled
          Value: !Ref CrossZoneEnabled
      Scheme: internet-facing 
      Subnets: !Ref NLBSubnetsIds
      Type: network
      
  MyListner1:      
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties: 
      DefaultActions: 
        - TargetGroupArn: !Ref MyTargetGroup
          Type: forward 
      LoadBalancerArn: !Ref MyNLB
      Port: 80 
      Protocol: TCP 

  MyTargetGroup: 
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties: 
      HealthCheckEnabled: true
      HealthCheckIntervalSeconds: 10
      HealthCheckPath: /
      HealthCheckProtocol: HTTP 
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 2
      Port: 80
      Protocol: TCP 
      TargetGroupAttributes: 
        - Key: deregistration_delay.timeout_seconds
          Value: 30
      Targets:
        - Id: !Ref MyInstance1
          Port: 80
        - Id: !Ref MyInstance2
          Port: 80
        - Id: !Ref MyInstance3
          Port: 80
        - Id: !Ref MyInstance4
          Port: 80                              
      TargetType: instance 
      VpcId: !Ref VpcId
      
      
Outputs:
    
  DNSName:
    Value: !GetAtt MyNLB.DNSName
---
参数:
VpcId:
类型:AWS::EC2::VPC::Id
NLBSubnetSID:

类型:列出您的场景不需要启用跨区域负载平衡。正如Marcin所指出的,这对你毫无帮助。事实上,解析您的NLB的DNS,您将看到它只为每个在所有NLB的目标组中聚合了一个健康实例的AZ返回一个A记录。Marcin的反应非常适合深度潜水

有些人在这里说:“是的,但我们仍然有超时。”。这是因为您的场景比OP更复杂。简言之,您可能有一个NLB,其中有多个AZ中存在不同目标的多个目标组。启用跨区域负载平衡将解决您的次优配置问题,但会增加您账单上的数据传输费用。鸭胶带和口香糖包装在AWS VPC中工作

更多信息:

NLB是DNS的“智能”,因为他们的VIP将只解析到具有健康目标的记录(在及时的原因内)。如果一个NLB有几个目标组,在三个AZ上有不同的实例,那么您将得到三个返回的A记录(每个AZ有一个健康的目标)。这就是NLB+RR DNS的工作原理

但是,如果您的目标组在单个AZ中包含EC2实例,那么DNS循环解析正确AZ的几率为33%(给定三个AZ)

最好的解决方案是启用跨区域负载平衡。这增加了数据传输成本,但与打破NLB的替代方案相比,它不那么复杂。请注意,启用跨区域负载平衡需要几分钟的时间。不要启用它,立即启动telnet,当它不工作时感到悲伤。等待5-10分钟,然后启动远程登录


资料来源:与AWS和janky EC2解决方案合作的轶事和实践经验。

Wow。真希望我能给你一个更大的赏金,让你得到如此惊人的回答。你没有看到从AZ2向LB发送请求的流量损失,只有一个实例在AZ1中注册?@Gandalf没问题。一切如期进行。NLB将“看到”只有一个实例,并且只在这一个AZs中使用节点。尽管如此,您还是可以慢慢来,不必急于使用提供的模板进行测试。该模板可以很容易地测试这个或类似的场景(例如,当实例在AZ中时会发生什么,NLB没有启用)。我不确定这个答案是否正确。我最近遇到了一个问题,在通过NLB主机名进行通信时,内部通信量没有到达单个目标。当NLB主机名解析为可用性区域A(具有目标)中NLB的IP地址时,请求成功。当NLB主机名解析为区域B中的IP时,请求超时。此处的文档状态>默认情况下,每个负载平衡器节点仅在其可用性区域中的注册目标之间分配流量。如果启用跨区域负载平衡,则每个负载平衡器节点将在所有启用的可用性区域中的注册目标之间分配流量。有关更多信息,请参阅《弹性负载平衡用户指南》中的跨区域负载平衡@RhysMadigan不知道你说的不正确是什么意思。跨区域平衡不会将流量分配到未为负载平衡器启用的区域。这也是你引用的文档所说的。