Динамическая маршрутизация HTTP-трафика в пользовательские контейнеры Docker

Я пытаюсь создать сервис, который будет запускать специфичные для пользователя процессы Java в контейнерах Docker в AWS (скорее всего, ECS). Один Java-процесс на контейнер на пользователя. Единственное исключение из этого может быть при вращении сменного контейнера на тот, который плохо себя ведет. Java-процесс представляет собой упакованное программное обеспечение, которое не может быть изменено в соответствии с моими потребностями. По сути, я стремлюсь создать сервис SaaS вокруг этого конкретного программного обеспечения, и я знаю, что будут подробности лицензирования, чтобы работать с разработчиком программного обеспечения.

Процесс Java имеет свой собственный встроенный веб-сервер, который использует нестандартные порты, например (30000-30004) для доступа к своему веб-интерфейсу. Он может поддерживать HTTP или HTTPS в зависимости от конфигурации. Я планирую запускать как можно больше таких контейнеров для каждого экземпляра EC2, чтобы сделать его более экономичным (это означало бы, что разные экземпляры в экземплярах EC2 сопоставляются с внутренними портами (30000-30004) контейнеров.

Я хотел бы обернуть встроенный пользовательский интерфейс процесса Java несколькими другими элементами, чтобы обеспечить контроль над процессом Java (остановка, запуск и т. Д.) И обслуживать мой пользовательский интерфейс через другой веб-сервер или, возможно, через шлюз API через Lambda. Это позволит пользователю запускать или останавливать свой экземпляр по мере необходимости, и вся система будет использовать эти запросы для запуска или остановки определенного контейнера Docker пользователя.

Чтобы дать представление о масштабе, возможно, что одновременно могут быть десятки тысяч пользователей. Предполагаемый размер рынка для этого проекта составляет около 100000 пользователей. Возможный размер рынка составляет около 2 миллионов пользователей в месяц. Реально, это будет приблизительно 10000 пользователей, из которых около 7500 будут активны в течение любого месяца. Потенциальный масштаб этого, вероятно, устраняет возможность использования Application Load Balancer с индивидуальной настройкой целевой и целевой группы для каждого экземпляра контейнера пользователя, поскольку ограничения ALB допускают только 1000 целей и только 100 правил.

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

Теперь вопрос: каковы некоторые из лучших решений для маршрутизации трафика в упомянутые контейнеры Docker? Я надеюсь разместить все это в своем собственном домене и использовать маршрутизацию на основе пути для получения запросов к соответствующим контейнерам.

Например:

  • Контейнер1 предназначен для пользователя1, работающего на хосте ec2-app1 на портах 30000-30004
  • Контейнер2 предназначен для пользователя2, работающего на хосте ec2-app1 на портах 31000-31004
  • Контейнер3 предназначен для пользователя 3, работающего на хосте ec2-app2 на портах 30000-30004

  • Пользовательский интерфейс управления будет обслуживаться с https://example.com/ с помощью iframe или чего-то подобного, указывающего на следующее для отдельных контейнеров.
  • Запросы к https://example.com/user1 должны идти в container1
  • Запросы к https://example.com/user2 должны идти в container2
  • Запросы на https://example.com/user3 следует отправлять на container3

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

По сути, я создаю мультитенантную службу из однопользовательского программного обеспечения, я знаю, что мне придется создавать довольно много пользовательских инструментов, и я не против этого. Я бы предпочел решения, которые хорошо работают с Python, когда требуется пользовательский код, но в случае необходимости приветствуются другие языки. Я подозреваю, что мне потребуется включить какой-либо агент или сценарий запуска в контейнеры или в выполняющие их экземпляры EC2, которые зарегистрируют контейнер в системе маршрутизации после запуска контейнера. Затем мне нужно было бы найти похожий сценарий завершения работы для удаления регистрации контейнера, а также обычную систему для очистки в случае сбоя контейнера или экземпляра EC2 без надлежащего завершения работы. Я уже изучил HAProxy и Nginx, и я готов услышать идеи относительно них, но другие варианты также очень приветствуются.

Заранее благодарю за ваши предложения!

1 ответ

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

Для этого я бы использовал балансировщик нагрузки приложения (ALB) и целевые группы. ALB может создавать настраиваемую маршрутизацию на основе пути и отправлять трафик в определенные целевые группы (читай: серверы или, в вашем случае, контейнеры Docker) при условии соответствия правил пути, например:

  • Правило 1: Путь начинается /user1, отправляйте трафик на TG1
  • Правило 2: Путь начинается /user2, отправляйте трафик на TG2
  • так далее..
  • Правило N: правило по умолчанию, весь остальной трафик на TGN (ваш основной сайт, обработчик 404 и т. Д.)

Вам нужно будет создать набор инструментов для;

  • Предоставьте контейнеры, необходимые для обслуживания ваших пользователей. Контейнеры Docker могут использовать динамические порты, и один и тот же экземпляр EC2/ECS может находиться в нескольких TG на разных портах. Как только контейнер активен, выясните, какие динамические порты он прослушивает.
  • Предоставьте TG для размещения этих контейнеров и зарегистрируйте соответствующие цели на соответствующих портах.
  • Обновите свой ALB, чтобы добавить новое правило для вашего пути, маршрутизируя к TG, который вы только что создали.
  • Перенаправить пользователя

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

Другие вопросы по тегам