то вот мое исследование проблемы:
"Всем привет.
А AWS NLB случаем не умеет в аналог опции nginx http://nginx.org/ru/docs/stream/ngx_stream_proxy_module.html#proxy_next_upstream proxy_next_upstream?
Это либо aws nlb какаха, либо я просто не вижу опций чтобы это включить. Может быть подскажете?
Ситуация следующая: увидел тут некоторое количество пакетов c connection timeout/refused решил расследовать.
И действительно если сравнить nginx L4 stream у которого такой простой конфиг: https://pastebin.com/mwWBmzwu (где ип адреса в апстримах являются просто подами в кубе, которые возвращают 200 ответ на любой GET запрос)
И aws nlb созданный контроллером куба по таким вот манифестам: https://pastebin.com/chfVVi2x
Если интересно то вот такие аннотации у сервиса:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
То есть таргеты смотрят напрямую в pod'ы.
То получаем в сравнении интересные резлуьтаты, не в пользу AWS NLB.
Запускаю смешную нагрузку в 20 RPS на протяжении 10 минут. И каждые 120 секунд убиваю по одному pod'у из апстримов.
В случае балансера nginx в режиме L4 стриминга, всё окей, убил 3 пода из 4 по очереди, он конечно у себя там пишет что-то вроде:
2023/08/04 10:01:26 [error] 8#8: *20305 upstream timed out (110: Operation timed out) while connecting to upstream, client: 172.31.120.49, server: 0.0.0.0:3000, upstream: "172.31.91.10:3000", bytes from/to client:0/0, bytes from/to upstream:0/0
2023/08/04 10:01:26 [warn] 8#8: *20305 upstream server temporarily disabled while connecting to upstream, client: 172.31.120.49, server: 0.0.0.0:3000, upstream: "172.31.91.10:3000", bytes from/to client:0/0, bytes from/to upstream:0/0
Ну то есть да, у него connection timeout c апстримом, но благодоря опции proxy_next_upstream он направляет коннекты на живой апстрим. Последние 4 минуты теста работал один под, всё без проблем. То есть клиент вообще этого даже не заметил. Из 12000 запросов на протяжении 10 минут, все запросы вернули 200 ответ.
А вот с AWS NLB история интересней. Я уже не говорю про то, что там он долго регистрирует таргеты, и чтобы пережить штатный rollingUpdate надо еще добавить readinessGates (достаточно повесить лейбл на ns чтобы они автоматом добавлялись). Но это дает лишь возможность держать pod'ы включенными пока регистрируются новые таргеты в балансере. Но при удалении pod'а всё равно получаем connection timeout'ы/ refused'ы. Из 12000 запросов на протяжении 10 минут, я получаю 176 connection timeout'ов, и еще несколько connection refused. При этом постоянно проверял живые таргеты балансера, там из 4 всегда было живо 3 таргета.
Окей и это можно решить, можно добавить костыль со sleep в preStop хуке (например вот так https://pastebin.com/pTAJegk2). И да, это поможет пережить без timeout'ов/refused'ов штатный rolling update деплоймента или штатное удаление одного из подов через kubectl delete po. А как насчет не штатного завершения приложения? Например по OOM или нода вылетела из сети или перезагрузилась?
Заходим в pod одного из апстримов, киляем приложение через kill -SIGTERM 1, и опять получаем connectiin refused или connection timeout.
При этом nginx в режиме L4 эту ситуацию без проблем обрабатывает, просто направляет упавший коннект на следующий апстрим (клиент этого не заметит), а вот в случае AWS NLB я получаю connection timeout/refused, почему AWS NLB так не делает (клиент получает connection timeout/refused)? Возможно я упускаю какую-то опцию балансера и она всё таки есть? А если нет, то это объективно же какаха получается, haproxy/nginx/envoy лучше справляются с балансингом L4 чем aws nlb =("
И похоже это не решаемо. То есть это кейс не как твой, со спотами, тут у меня всё честно. Живые выделенные ноды под контроллер, не споты. Но даже с таким сетапом возникают проблемы
грустно из-за этого. Поскольку это всё связано с приложением встроенным в японскую соц. сеть. Все запросы от пользователей соц сети к приложению летят через прокси соц. сети, и если на протяжении 5-10 секунд будет примерно 4-6 connection timeout/connectiin refused или же 504, тогда соц. сеть ставит наше приложение автоматом на тех работы, отключить это можно только отправив письмо на почту японцу, который через часов 10 отключит тех работы (если прочитает вообще) Переехали из linode в amazon, и вот страдаем. Денег естественно платим amazon больше, чем в Linide =)
а чего не терминировать это всё через alb ?
я вот уверен что в alb будет тоже самое, Его еще не тестил. Но вообще если брать alb то это надо тогда сертификаты тащить в amazon
хе интересно, спасибо за такой детальный тест на самом деле если бы Classic Load Balancer умел бы в target-ip и его бы не собирались удалять, я б уже на него свалил, а то тугость таргет групп NLB меня напрягает connection timeout пока не ловил, prestop хуки похоже помогли, заранее их добавил по умолчанию + надо не забывать что у NLB таймаут соединений 350 секунд, и нужно ставить на контроллере и нжинксах(сайдкары к приложению) меньше значение, это тоже может влиять на таймауты
это какой таймаут ?
в алб по крайний мере регистрация таргетов быстрее в разы, в режиме ip
да это хорошо. Но только в моем кейсе я получаю connection timeout/connection refused при 3 живых таргетах. То есть у меня беда не в регистрации. Ну плюс с регистрацией у меня там решено - redinessGate'ы настроены
с alb тоже самое А именно для нормального штатного завершения нужен preStop хук со слипом большим В случае нештатного завершения, получаю 502ые. То есть alb в аналог proxy_next_upstream как в nginx тоже не умеет
Обсуждают сегодня