Динамическая маршрутизация 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 минут... самая длинная часть будет ждать, пока контейнеры не станут активными, и даже это не так уж долго.