Как корректно завершить работу или удалить экземпляры AWS из группы ELB

У меня есть облако экземпляров серверов, работающих на Amazon, использующих их балансировщик нагрузки для распределения трафика. Теперь я ищу хороший способ изящно масштабировать сеть, не вызывая ошибок подключения на стороне браузера.

Насколько мне известно, любые подключения экземпляра будут грубо прерваны при удалении из балансировщика нагрузки.

Я хотел бы иметь способ сообщить своему экземпляру за одну минуту до его выключения или чтобы балансировщик нагрузки перестал отправлять трафик умирающему экземпляру, но без разрыва существующих подключений к нему.

Мое приложение - node.js, работающее на Ubuntu. У меня также есть специальное программное обеспечение, работающее на нем, поэтому я предпочитаю не использовать многие PAAS, предлагающие хостинг node.js.

Спасибо за любые подсказки.


person Johann Philipp Strathausen    schedule 05.10.2011    source источник
comment
Используете ли вы ELB для поддержки пользовательских сеансов, которые действительны только для определенных экземпляров EC2? И если да, то как долго длятся эти сеансы?   -  person Ray Vahey    schedule 10.10.2011
comment
Я не использую ELB для управления пользовательскими сеансами - возможно, я сделаю это только из соображений производительности, но я не полагаюсь на эту функцию. Управление сеансом осуществляется центральной базой данных, к которой имеют доступ все узлы.   -  person Johann Philipp Strathausen    schedule 11.10.2011
comment
Вот ветка о том, как ELB грубо разрывает активные соединения при удалении экземпляра: forum.aws .amazon.com / thread.jspa? threadID = 61278 Amazon попросила оставить отзыв, поэтому не стесняйтесь добавлять +1, чтобы исправить это.   -  person Eric Hammond    schedule 05.01.2012


Ответы (6)


Эта идея использует способность ELB обнаруживать неисправный узел и удалять его из пула, НО она полагается на поведение ELB, как ожидалось в предположениях ниже. Это то, что я хотел проверить на себе, но у меня еще не было времени. Я обновлю ответ, когда сделаю это.

Обзор процесса

Следующая логика может быть заключена в оболочку и запущена во время остановки узла.

  1. Блокировать новые HTTP-подключения к nodeX, но продолжать разрешать существующие подключения
  2. Подождите, пока истощатся существующие соединения, либо отслеживая существующие соединения с вашим приложением, либо выделяя «безопасное» количество времени.
  3. Инициируйте завершение работы экземпляра nodeX EC2, используя API EC2 напрямую или абстрактные сценарии.

«безопасно» в соответствии с вашим приложением, которое может быть невозможно определить для некоторых приложений.

Предположения, которые необходимо проверить

Мы знаем, что ELB удаляет нездоровые экземпляры из своего пула, я ожидаю, что это будет изящно, так что:

  1. Новое соединение с недавно закрытым портом будет корректно перенаправлено на следующий узел в пуле.
  2. Когда узел помечен как Плохой, уже установленные соединения с этим узлом не затрагиваются.

возможные тестовые случаи:

  • Запускать HTTP-соединения в ELB (например, из скрипта curl), регистрируя результаты во время открытия по сценарию закрытия одного из HTTP-портов узла. Вам нужно будет поэкспериментировать, чтобы найти приемлемое количество времени, которое позволяет ELB всегда определять изменение состояния.
  • Поддерживайте длительный HTTP-сеанс (например, загрузка файла), блокируя новые HTTP-соединения, мы надеемся, что этот длинный сеанс будет продолжен.

1. Как заблокировать HTTP-соединения

Используйте локальный брандмауэр на nodeX, чтобы заблокировать новые сеансы, но продолжайте разрешать установленные сеансы.

Например IP-таблицы:

iptables -A INPUT -j DROP -p tcp --syn --destination-port <web service port>
person Ray Vahey    schedule 11.10.2011
comment
Спасибо за идеи! К сожалению, предположение номер 2 кажется важным, которого не хватает. Насколько мне известно, узел существует примерно через 40-60 секунд после того, как был обнаружен как больной, без каких-либо гарантий. Но, к сожалению, он уже немедленно удаляется без какого-либо предупреждения от ELB, и любые существующие соединения прерываются и не перенаправляются на другой узел. Это то, что я знаю, но я мог бы попробовать с этим поэкспериментировать ... - person Johann Philipp Strathausen; 11.10.2011
comment
Хорошо, что он определяет его как неработающий и удаляет, это то, что мы хотим. Но также удаление существующих подключений, безусловно, вызовет у нас проблемы, я бы не исключил этого без теста, потому что я видел, что другое программное обеспечение для балансировки нагрузки работает таким образом ... В противном случае вы можете использовать поддомены с балансировщиком нагрузки, чтобы что он устанавливает только начальное соединение? Например. balance.domain.com перенаправляется на nodeX.domain.com? Где nodeX - следующий в круговом пуле и т. Д. - person Ray Vahey; 12.10.2011
comment
Сам ELB не поддерживает использование поддоменов, но машина может знать свое собственное имя. Я мог бы даже иметь набор машин, сопоставленных с доменными именами через записи DNS - хотя я не знаю, как это сделать автоматически. Поскольку я плачу большую часть денег за запуск инстансов, а приостановленные инстансы довольно дешевы, это может быть вариантом. Поэтому я бы использовал ELB для начального распределения, а с этого момента, возможно, использовал бы узел, которому назначен пользователь. Это может сработать! Есть идеи, как лучше всего использовать поддомены вместо URL-адресов компьютеров AWS? (Я хочу использовать wildcard-ssl для одного домена). - person Johann Philipp Strathausen; 14.10.2011
comment
хм, это не сработает с сертификатом с подстановочными знаками, потому что сертификат должен быть привязан к одному статическому IP-адресу. Вам понадобятся индивидуальные сертификаты для каждого узла. - person Ray Vahey; 14.10.2011
comment
Хотя мне нравится общая идея. Я поставил вам зеленую галочку из-за этого :-) - person Johann Philipp Strathausen; 16.10.2011
comment
Кстати, я думаю, что сертификат должен быть привязан не к статическому IP, а к домену. Нет? - person Johann Philipp Strathausen; 18.10.2011
comment
Спасибо, я только что поискал и, похоже, ошибся в привязке к одному IP. stackoverflow.com/questions/909453/ - person Ray Vahey; 18.10.2011
comment
Если вы просто удаляете отдельные узлы, а не останавливаете службу в целом, конечно, было бы намного разумнее ОТКЛЮЧИТЬ соединение, позволяя балансировщику нагрузки немедленно переназначить запрос, а не ждать тайм-аута с помощью DROP? - person symcbean; 13.06.2015

Я знаю, что это старый вопрос, но следует отметить, что Amazon недавно добавила поддержку connection draining, что означает, что когда экземпляр удаляется из балансировщика нагрузки, он завершает запросы, которые выполнялись до того, как экземпляр был удален из балансировщик нагрузки. Никакие новые запросы не будут перенаправлены на удаленный экземпляр. Вы также можете указать тайм-аут для этих запросов, что означает, что любые запросы, которые выполняются дольше, чем окно тайм-аута, будут в конце концов завершены.

Чтобы включить это поведение, перейдите на вкладку Instances вашего балансировщика нагрузки и измените Connection Draining поведение.

person Jaap Haagmans    schedule 09.04.2014

Рекомендуемый способ распределения трафика от вашего ELB - иметь равное количество экземпляров в нескольких зонах доступности. Например:

ELB

  • Экземпляр 1 (us-east-a)
  • Экземпляр 2 (us-east-a)
  • Экземпляр 3 (us-east-b)
  • Экземпляр 4 (us-east-b)

Теперь есть два интересных API ELB, которые позволяют программно (или через панель управления) отсоединять экземпляры:

  1. Отменить регистрацию экземпляра
  2. Отключить зону доступности (что впоследствии отключает экземпляры в этой зоне)

В Руководстве разработчика ELB есть раздел, описывающий последствия отключения зоны доступности. Примечание в этом разделе представляет особый интерес:

Ваш балансировщик нагрузки всегда распределяет трафик по всем включенным зонам доступности. Если все экземпляры в зоне доступности сняты с регистрации или находятся в неработоспособном состоянии до того, как эта зона доступности будет отключена для балансировщика нагрузки, все запросы, отправленные в эту зону доступности, не будут выполнены до тех пор, пока DisableAvailabilityZonesForLoadBalancer не вызовет эту зону доступности.

Что интересно в приведенном выше примечании, так это то, что это может означать, что если вы вызовете DisableAvailabilityZonesForLoadBalancer, ELB может мгновенно начать отправку запросов только в доступные зоны, что может привести к 0 простоям, пока вы выполняете обслуживание серверов в отключенной зоне доступности.

Вышеупомянутая «теория» требует детального тестирования или подтверждения от облачного инженера Amazon.

person Faraz    schedule 03.11.2011
comment
Звучит многообещающе, я не думал об этом! Я обязательно это проверю! Спасибо. - person Johann Philipp Strathausen; 03.11.2011

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

  1. Сервер мог потерять питание.
  2. Аппаратный сбой вызывает сбой сервера.
  3. Соединение могло быть прервано из-за проблем с сетью.
  4. Клиент теряет интернет или Wi-Fi.

Я мог бы продолжить список, но я хочу сказать, что вместо того, чтобы проектировать систему, она всегда работает правильно. Разработайте его так, чтобы справляться с отказами. Если вы разрабатываете систему, которая может справиться с потерей мощности сервера в любое время, вы создали очень надежную систему. Это не проблема с ELB, это проблема с вашей текущей системной архитектурой.

person bwight    schedule 04.10.2012
comment
Вы правы, существует множество сценариев, которые могут вызвать мгновенную потерю связи, но я думаю, что это вопрос степени. Автоматическое масштабирование задумано как обычное дело; счета оплачиваются по часам, поэтому вы можете увеличивать или уменьшать масштаб каждый час ... это много потерянных соединений. - person Stephen; 04.04.2013

Не могу комментировать причину своей низкой репутации. Вот несколько созданных мной фрагментов, которые могут быть очень полезны для кого-то там. Он использует инструмент aws cli, чтобы проверить, когда из экземпляра были удалены соединения.

Вам нужен ec2-экземпляр с предоставленным сервером python за ELB.

from flask import Flask
import time

app = Flask(__name__)

@app.route("/")
def index():
    return "ok\n"

@app.route("/wait/<int:secs>")
def wait(secs):
    time.sleep(secs)
    return str(secs) + "\n"

if __name__ == "__main__":
    app.run(
        host='0.0.0.0',
        debug=True)

Затем запустите следующий сценарий с локальной рабочей станции по направлению к ELB.

#!/bin/bash

which jq >> /dev/null || {
   echo "Get jq from http://stedolan.github.com/jq"
}

# Fill in following vars
lbname="ELBNAME"
lburl="http://ELBURL.REGION.elb.amazonaws.com/wait/30"
instanceid="i-XXXXXXX"

getState () {
    aws elb describe-instance-health \
        --load-balancer-name $lbname \
        --instance $instanceid | jq '.InstanceStates[0].State' -r
}

register () {
    aws elb register-instances-with-load-balancer \
        --load-balancer-name $lbname \
        --instance $instanceid | jq .
}

deregister () {
    aws elb deregister-instances-from-load-balancer \
        --load-balancer-name $lbname \
        --instance $instanceid | jq .
}

waitUntil () {
    echo -n "Wait until state is $1"
    while [ "$(getState)" != "$1" ]; do
        echo -n "."
        sleep 1
    done
    echo
}

# Actual Dance
# Make sure instance is registered. Check latency until node is deregistered

if [ "$(getState)" == "OutOfService" ]; then
    register >> /dev/null
fi

waitUntil "InService"

curl $lburl &
sleep 1

deregister >> /dev/null

waitUntil "OutOfService"
person Loa    schedule 23.12.2014
comment
См. документы .aws.amazon.com / autoscaling / latest / userguide / - я думаю, что это лучший подход и должен быть быстрее. Насколько я понимаю, описанный выше подход, вероятно, приведет к тому, что группа автомасштабирования создаст новый узел, когда вы отмените регистрацию одного для обновления ... - person David Goodwin; 31.05.2016

Предостережение, которое не обсуждалось в существующих ответах, заключается в том, что ELB также используют записи DNS с 60-секундным TTL для балансировки нагрузки между несколькими узлами ELB (к каждому из которых прикреплен один или несколько ваших экземпляров).

Это означает, что если у вас есть экземпляры в двух разных зонах доступности, у вас, вероятно, есть два IP-адреса для вашего ELB с TTL 60 с в их записях A. Когда вы удаляете последние экземпляры из такой зоны доступности, ваши клиенты «могут» по-прежнему использовать старый IP-адрес хотя бы минуту - неисправные преобразователи DNS могут вести себя намного хуже.

Другой раз, когда ELB носят несколько IP-адресов и имеют ту же проблему, когда в одной зоне доступности у вас очень большое количество экземпляров, которое слишком много для обработки одним сервером ELB. ELB в этом случае также создаст другой сервер и добавит его IP в список A-записей с 60-секундным TTL.

person Evgeny    schedule 04.10.2012
comment
Заявленный контракт, насколько я понимаю, заключается в том, что трафик, маршрутизируемый (из-за устаревшего DNS) в зону доступности без работоспособных экземпляров, будет перенаправляться ELB в зону доступности, у которой есть работоспособные экземпляры. Вы можете проверить это, настроив 2 экземпляра в разных зонах доступности, отключив одну, затем принудительно отправив трафик на IP-адрес ELB для зоны доступности, которая отключена, и посмотреть, будет ли он по-прежнему обеспечивать нормальный ответ. - person Johnny C; 07.07.2013