AWS Network Load Balancer без цели в каждой зоне доступности

В документации по AWS Network Load Balancer говорится, что при указании экземпляров для целевой группы он должен включать экземпляр в каждую зону доступности, в которой зарегистрирован Load Balancer. Это не является обязательным.

Что произойдет с трафиком, если у вас есть NLB, зарегистрированный в 3 зонах доступности, но только один целевой инстанс EC2 в зоне доступности 1? Что, если вы включите балансировку нагрузки между зонами доступности, какая разница?


person Gandalf    schedule 16.09.2020    source источник


Ответы (2)


Что произойдет с трафиком, если у вас есть NLB, зарегистрированный в 3 зонах доступности, но только один целевой инстанс EC2 в зоне доступности 1? Что, если вы включите балансировку нагрузки между зонами доступности, какая разница?

В этом конкретном сценарии (NLB в 3 зонах доступности и один экземпляр в 1 зоне доступности) на самом деле ничего не происходит. С точки зрения конечного пользователя, нет очевидной разницы с межзональной балансировкой нагрузки или без нее. Экземпляр будет доступен в любом случае.

Чтобы убедиться в этом, я разработал простой шаблон CloudFormation, который создает NLB, с межзональной балансировкой нагрузки или без нее, и 1 экземпляр. Шаблон позволяет легко экспериментировать с различными настройками балансировки сетевой нагрузки, межзонального взаимодействия и расположения экземпляра. Я использовал шаблон в us-east-1 регионе и VPC по умолчанию.

Для шаблона вы указываете несколько параметров, в том числе:

  • NLBSubnetsIds - подсети, в которых включить NLB. Вы должны сначала проверить в консоли, какие подсети и в каких зонах доступности.

  • InstanceSubnetId - подсеть для экземпляра. Опять же, вы можете проверить, какая подсеть находится в какой зоне доступности, если вы хотите поэкспериментировать с расположением экземпляра. Вы должны убедиться, что экземпляр создан в одной из зон доступности, установленных для вашего NLB.

  • 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

С точки зрения конечного пользователя, в вашем сценарии нет четкой разницы между включением или отключением межзонального взаимодействия в NLB. Однако в долгосрочной перспективе разница может заключаться в высокой доступности. А именно, если у вас отключена перекрестная зона и если что-то случится с узлом NLB в зоне доступности, где расположен экземпляр, NLB не сможет направлять трафик на ваш экземпляр из другой зоны доступности. Это мое предположение, так как это не то, что вы можете проверить вручную. Причина в том, что после того, как вы связали зону доступности / подсеть со своим NLB, вы не можете отсоединить ее, чтобы проверить, что происходит в таком сценарии.

Напротив, если перекрестная зона включена, в приведенном выше сценарии узел NLB из другой зоны, вероятно, может направлять трафик к экземпляру через зоны.

Основное преимущество включения межзонального трафика - это когда вы разное количество экземпляров в разных зонах доступности. В этом случае балансировка между зонами позволяет всем экземплярам получать примерно одинаковый объем трафика. Без межзональной балансировки изолированный экземпляр будет получать гораздо больше трафика, чем коллекция экземпляров в другой зоне доступности.

Вы можете проверить эффект балансировки зон с помощью второго шаблона. Шаблон почти такой же, как и раньше, но теперь в 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

Если вы используете вышеуказанный шаблон и неоднократно запрашиваете URL-адрес NLB, вы увидите, что изолированный экземпляр получит около 50% трафика без межзональной балансировки. При включенной межзональной балансировке это будет около 20%. Ниже приведены мои результаты на основе 100 запросов:

введите описание изображения здесь

person Marcin    schedule 22.09.2020
comment
Вот это да. Хотел бы я назначить вам более крупную награду за такой потрясающий ответ. И вы не видели потери трафика при отправке запроса из AZ2 в LB только с экземпляром, зарегистрированным в AZ1? - person Gandalf; 23.09.2020
comment
@ Гэндальф Нет проблем. Все заработало как положено. NLB увидит, что существует только один экземпляр, и будет использовать узел только в этой зоне доступности. Тем не менее, вы можете не торопиться и поиграться с шаблоном, предоставленным для его тестирования. Шаблон позволяет легко протестировать этот или аналогичные сценарии (например, что происходит, когда экземпляр находится в зоне доступности, не включенной для NLB). - person Marcin; 23.09.2020
comment
Я не уверен, что это правильный ответ. Недавно у меня была проблема, когда внутренний трафик не достигал единственной цели при обмене данными через имя хоста NLB. Когда имя хоста NLB преобразовано в IP-адрес NLB в зоне доступности A (которая имеет цель), запрос выполнен. Когда имя хоста NLB преобразовано в IP-адрес в зоне B, время ожидания запроса истекло. - person Rhys Madigan; 05.11.2020
comment
В документации указано: ›По умолчанию каждый узел балансировки нагрузки распределяет трафик между зарегистрированными целевыми объектами только в своей зоне доступности. Если вы включаете межзональную балансировку нагрузки, каждый узел балансировки нагрузки распределяет трафик между зарегистрированными целевыми объектами во всех включенных зонах доступности. Дополнительные сведения см. В разделе Межзональная балансировка нагрузки в Руководстве пользователя эластичной балансировки нагрузки. docs.aws. amazon.com/elasticloadbalancing/latest/network/ - person Rhys Madigan; 05.11.2020
comment
@RhysMadigan Не уверен, что вы имеете в виду, говоря, что это неверно. Межзонная балансировка не распределяет трафик в зоны, не включенные для балансировщика нагрузки. Это то, что также говорится в ваших цитируемых документах. - person Marcin; 06.11.2020
comment
@Marcin, по сути, я говорю с точки зрения конечного пользователя, есть есть разница - если пользователь попадает в узел NLB в зоне доступности, где нет целей, запрос не будет успешным. . Допустим, у нас есть NLB с адресом mynlb.amazonaws.com и два узла: - AZ1: 10.0.0.1 - AZ2: 10.128.0.1 И одна цель в AZ1. В ходе тестирования я обнаружил, что запросы к mynlb.amazon.aws.com разрешаются на любой IP-адрес, причем несколько случайным образом. Если адрес разрешен в узел LB в AZ2, запрос не будет успешным. С включенной кросс-зоной так и было. - person Rhys Madigan; 06.11.2020
comment
@RhysMadigan Спасибо, что указали на это. В своих тестах я такого поведения не наблюдал. Но с удовольствием еще раз протестирую. С шаблоном CFN в моем ответе должно быть легко проверить это. - person Marcin; 06.11.2020

Ваш сценарий не требует включения межзональной балансировки нагрузки. Как указал Марцин, это ничего для вас не делает. Фактически, разрешите DNS вашего NLB, и вы увидите, что он возвращает только запись A для каждой зоны доступности, в которой есть работоспособный экземпляр, агрегированный во всех целевых группах NLB. Ответ Марчина фантастичен для глубокого погружения.

Некоторые люди здесь говорят «да», но у нас все еще есть таймауты .. Это потому, что ваш сценарий более сложен, чем OP. Короче говоря, у вас, вероятно, есть NLB с более чем одной целевой группой, в которой отдельные цели существуют в нескольких зонах доступности. Включение межзональной балансировки нагрузки решит проблему неоптимальной конфигурации за счет дополнительных затрат на передачу данных в вашем счете. Утиная лента и обертки жевательной резинки работают в AWS VPC.

Больше информации:

NLB умны с DNS в том смысле, что их виртуальный IP-адрес будет разрешаться только в записи A, которые имеют работоспособные цели (по своевременной причине). Если NLB имеет несколько целевых групп с отдельными экземплярами в трех зонах доступности, вы получите три возвращенные записи A (по одной для каждой зоны доступности, имеющей работоспособную цель). Так работает NLB + RR DNS.

Однако, если ваши целевые группы содержат экземпляры EC2 в одной зоне доступности, то вероятность того, что циклический перебор DNS разрешит правильную зону доступности, составляет 33% (с учетом трех зон доступности).

Лучшее решение - включить межзонную балансировку нагрузки. Это увеличивает стоимость передачи данных, но это менее сложно по сравнению с альтернативой разделения NLB. Обратите внимание, что включение межзональной балансировки нагрузки займет несколько минут. Не включайте ее, сразу же запускайте Telnet и расстраивайтесь, если это не сработает. Подождите 5–10 минут, а затем запустите телнет.

Источник: анекдотический и практический опыт работы с AWS и нестандартными решениями EC2.

person Andrew L    schedule 27.01.2021