Вопрос или проблема
Я пишу оператор Kubernetes для развертывания отдельных, выделенных игровых серверов внутри одного кластера. Какой будет лучший способ для экспонирования этих серверов за пределами кластера?
Требования
- Серверы должны быть адресуемы индивидуально за пределами кластера. Выделенные игровые серверы изолированы друг от друга и не могут быть сбалансированы по нагрузке.
- Поддержка протоколов TCP и UDP. Это основные протоколы, с которыми будут взаимодействовать игры.
- Управляемые программно. Мой пользовательский ресурс – это отдельный сервер. Ассоциация сервера с чем-то вроде ingress опасна, так как один ресурс ingress содержит правила для других серверов тоже.
- Масштабируемость до пределов Kubernetes.
- Коренные решения для Kubernetes. Это может размещаться где угодно, без зависимости от пользовательских ресурсов или инструментов вне моего проекта.
Идеи
Сначала я подумал об ingress
. Однако слушатели ingress и правила не являются отдельными ресурсами от самого ingress. Изменение этих правил программно для каждого отдельного сервера может быть очень опасно. То же самое касается слушателей нового Gateway API.
Я рассмотрел nodeports
, но поскольку область действия nodeports охватывает весь кластер, теоретический предел на кластер составляет единственный диапазон портов – значительно ниже 65535
.
Ближе всего, что я смог добиться, это clusterIps
с externalIps
. Из того, что я читаю, это кажется работающим аналогично nodePort, но область действия устанавливается на externalIps. Это означает, что я мог бы распределять серверы по множеству externalIps, масштабируя значительно больше, чем nodeports.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 49152
externalIPs:
- 198.51.100.32
Я не уверен, неправильно ли я понимаю, как работают clusterIps
и externalIps
.
Иногда лучшее решение – это простое:
Используйте поле hostPort
в спецификации контейнера Pod.
Это открывает порт на узле хоста и перенаправляет трафик к контейнеру через iptables или ipvs, в зависимости от провайдера хоста и/или сетевого оверлея.
Мы делаем это, так как вы действительно не можете использовать LoadBalancer для маршрутизации UDP-пакетов к конкретному экземпляру игрового сервера, и вам не нужен этот переход (в большинстве случаев) – гораздо лучше идти прямо к узлу.
Как и externalIP
, это означает, что вам нужен публично адресуемый узел.
Я получил этот ответ в форумах сообщества Kubernetes от главного участника проекта Agones, который очень похож на мой проект.
Тип сервиса: LoadBalancer – лучший способ для экспонирования сервисов извне. Установите externalTrafficPolicy: Local, чтобы направить трафик на эти выделенные узлы. Ознакомьтесь с этим: https://docs.loxilb.io/k3s_quick_start_incluster/
Ответ или решение
Экспонирование подов Kubernetes с использованием TCP и UDP трафика
Ваша задача по созданию оператора Kubernetes для развертывания индивидуальных игровых серверов требует тщательного подхода к экспонированию сервисов за пределами кластера. Рассмотрим оптимальные способы достижения ваших целей в контексте указанных вами требований.
Основные требования
- Индивидуальная адресуемость серверов вне кластера: Необходимо обеспечить доступ к каждому игровому серверу отдельно.
- Поддержка TCP и UDP протоколов: Большинство игровых приложений используют эти протоколы для связи.
- Программируемое управление: Вы хотели бы иметь возможность управлять каждым сервером независимо и безопасно.
- Масштабируемость: Решение должно быть способно поддерживать высокие нагрузки и масштабироваться в пределах Kubernetes.
- Нативность для Kubernetes: Решение не должно зависеть от сторонних инструментов или ресурсов, за исключением вашего собственного проекта.
Возможные решения
1. Использование hostPort
Использование поля hostPort
в спецификации контейнера пода — это одно из простейших и эффективных решений для экспонирования игровых серверов. Это решение открывает порт на узле хоста и напрямую перенаправляет трафик в контейнер через iptables или ipvs. Это позволяет избежать использования балансировщиков нагрузки для маршрутизации UDP-пакетов к конкретному игровому серверу.
Пример конфига с использованием hostPort
:
apiVersion: v1
kind: Pod
metadata:
name: my-game-server
spec:
containers:
- name: game-server
image: my-game-server-image
ports:
- containerPort: 8080 # Порт, на который сервер слушает UDP/TCP
hostPort: 8080 # Порт на узле хоста
Таким образом, вы можете напрямую обращаться по IP-адресу узла и порту, задействованному в hostPort
.
2. Использование Service с externalIPs
Еще одним решением может стать использование сервиса с externalIPs
. Это позволит вам запускать несколько сервисов и привязывать их к различным внешним IP-адресам. Однако, важно было бы соблюдать порядок и выделять порты для каждого сервиса.
Пример:
apiVersion: v1
kind: Service
metadata:
name: my-game-service
spec:
selector:
app: my-game-server
ports:
- name: udp-port
protocol: UDP
port: 7070
targetPort: 8080
externalIPs:
- 198.51.100.32
- 198.51.100.33
С помощью этого сервиса вы можете обеспечить доступ к вашим игровым контейнерам по нескольким IP-адресам.
3. Использование LoadBalancer с externalTrafficPolicy: Local
Вы также можете рассмотреть возможность использования сервиса типа LoadBalancer
, который будет направлять трафик только на локальные узлы. Это также обеспечит доступность отдельных серверов, однако необходимо иметь в наличии облачного провайдера, который поддерживает данный тип сервиса.
Пример конфигурации:
apiVersion: v1
kind: Service
metadata:
name: my-game-loadbalancer
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- protocol: TCP
port: 8080
targetPort: 8080
- protocol: UDP
port: 8081
targetPort: 8081
selector:
app: my-game-server
Здесь externalTrafficPolicy: Local
обеспечивает, что только узлы с подами будут обрабатывать входящий трафик, что уменьшает задержку.
Заключение
Каждое из описанных решений имеет свои преимущества и недостатки. Выбор наиболее подходящего способа будет зависеть от ваших конкретных требований, архитектуры и инфраструктуры. Использование hostPort
представляет собой простой и эффективный способ организации доступа, в то время как LoadBalancer
и Service
с externalIPs
могут предложить более масштабируемые решения.
Рекомендуется протестировать каждое из решений в вашем кластере Kubernetes для определения наилучшего подхода к экспонированию игровых серверов.