Настройка внешнего доступа к YTsaurus в Kubernetes
По умолчанию кластер YTsaurus, развёрнутый в Kubernetes, изолирован от внешней сети. Для публикации сервисов, как правило, используются механизмы LoadBalancer или Ingress. Они хорошо подходят для отдельных веб-сервисов, предоставляя единую точку входа для клиентов, но не обеспечивают масштабирование большого сетевого потока.
Из данной статьи вы узнаете, как:
-
Решить проблему сетевой изоляции — настроить кластер так, чтобы внешние клиенты могли напрямую обращаться к узлам кластера для эффективной записи и чтения больших объёмов данных.
-
Разделить нагрузку между клиентами — изолировать ресурсы разных проектов, а также разделить трафик на «лёгкий» (метаданные, UI) и «тяжёлый» (чтение и запись таблиц).
-
Настроить доступ для SPYT — настроить TCP-проксирование для прямого соединения внешнего драйвера Spark с воркерами внутри кластера.
Обзор прокси
Пользователи взаимодействуют с сервером YTsaurus не напрямую, а через специальные прокси. Это компоненты YTsaurus, которые выступают единой точкой входа и скрывают взаимодействие между компонентами и внутреннюю топологию кластера — например, адреса мастеров и data-нод.
С точки зрения Kubernetes, прокси обычно разворачиваются как StatefulSet, состоящий из нескольких подов. Их количество и выделяемые ресурсы (CPU, RAM) задаются в спецификации оператора YTsaurus, а при запуске кластера каждый под прокси автоматически регистрируется в Кипарисе (в системных директориях //sys/http_proxies и //sys/rpc_proxies).
Прокси в YTsaurus бывают двух типов:
- HTTP-прокси — реализуют HTTP API YTsaurus. Активно используются в SDK, для работы веб-интерфейса и CLI.
- RPC-прокси — реализуют более быстрый бинарный протокол (YT RPC). В первую очередь необходимы там, где требуется низкая латентность запросов (например, при интенсивной потоковой работе с динамическими таблицами). Для всех остальных сценариев рекомендуется использовать HTTP-прокси.
Понятие роли
Прокси можно разбивать на функциональные группы с помощью ролей. Как правило, выделяют две основные группы:
- Контрольные (control-прокси) — обрабатывают «лёгкие» запросы (навигация в UI, работа с метаданными Кипариса). Для них обычно назначается роль
control. - Тяжёлые (data-прокси) — обрабатывают «тяжёлые» запросы (потоковое чтение и запись больших таблиц). В Kubernetes-инсталляциях они чаще всего работают под ролью
default.
Такое разделение позволяет гибко управлять ресурсами кластера: активное чтение огромной таблицы через data-прокси не затормозит работу веб-интерфейса и не помешает другим пользователям просматривать дерево Кипариса.
Технически роль — это строковая метка (атрибут @role в Кипарисе), которая присваивается инстансу прокси при запуске. По умолчанию все прокси в кластере запускаются с ролью default. Назначить роль можно в спецификации Ytsaurus.
Механизм Discovery
При инициализации клиента (SDK) разработчик указывает общий адрес кластера (например, yt.example.com). Обычно за этим адресом стоит балансировщик (Ingress или LoadBalancer), распределяющий запросы между доступными прокси-серверами.
Однако прогонять гигабайты трафика чтения/записи через один центральный балансировщик неэффективно. Чтобы масштабировать сетевой поток, SDK автоматически отправляют тяжёлые запросы на data-прокси напрямую, минуя центральную точку входа. Разработчику не нужно указывать в коде десятки адресов — SDK узнает про них самостоятельно через встроенный механизм Discovery. Он работает следующим образом:
- Перед выполнением тяжёлого запроса SDK отправляет служебный HTTP-запрос
GET /api/v4/discover_proxiesна общий балансировщик. - В ответ сервер возвращает список адресов (FQDN) активных data-прокси.
- SDK выбирает один адрес из списка и отправляет тяжёлый запрос напрямую к этому поду.
Ниже приведена схема работы механизма Discovery при вызове write_table в HTTP-прокси:
Пояснения к схеме
- Клиентская библиотека (SDK) выполняет служебный HTTP-запрос
discover_proxiesна основной публичный адрес кластера (балансировщикyt.example.com). - Балансировщик принимает запрос и перенаправляет его внутрь кластера на один из доступных контрольных прокси-серверов (Control Proxy).
- Контрольный прокси формирует список FQDN активных data-прокси (например,
hp-0.svc.local,hp-1.svc.local) и возвращает его балансировщику. - Балансировщик возвращает этот список клиенту.
- SDK выбирает из списка один конкретный адрес (в нашем примере —
hp-0) и отправляет запрос на запись данных (write_table) напрямую к этому поду, минуя центральный балансировщик. - Между клиентом и data-прокси устанавливается прямое соединение, по которому передается поток данных.
Роли прокси в Discovery
При запросе discover_proxies клиент может дополнительно передать требуемую роль. При этом действует логика:
- Если роль указана явно (например,
role=heavy), балансировщик вернёт адреса только выделенных под неё прокси. - Если роль не указать, будут запрашиваться прокси с ролью
default.
Discovery в разных протоколах
- В HTTP используется «ленивый» подход. Запрос к
discover_proxiesвыполняется перед началом чтения или записи файла. - В RPC используется «жадный» подход. Клиент вызывает
discover_proxiesсразу при старте, получает список адресов RPC-прокси и устанавливает с ними постоянные TCP-соединения.
Примечание
В более старых версиях API (< v4) точки входа в сервис Discovery различались.
Отличия в Discovery в API v3 и API v4
В версиях API ниже v4:
- Для получения списка всех HTTP-прокси клиенты обращались к эндпоинту
/v3/entry. - Для получения RPC-прокси — к
/v3/discover_proxies.
Начиная с версии v4, оба типа клиентов используют единый универсальный эндпоинт /api/v4/discover_proxies (с параметром type=rpc для RPC-клиентов).
Почему возникает проблема доступов
В стандартной конфигурации Kubernetes адреса подов являются внутренними (например, hp-0.http-proxies.default.svc.cluster.local).
Когда внешний SDK вызывает discover_proxies, кластер возвращает ему список внутренних FQDN. SDK, находясь за периметром кластера, не может разрешить эти DNS-имена в IP-адреса. В результате лёгкие команды через балансировщик работают успешно, а попытка записать данные завершается различными сетевыми ошибками — от ошибок разрешения DNS-имён до невозможности подключиться (Temporary failure in name resolution, Connection refused, Connection timed out).
Пример: как распознать проблему
Рассмотрим сценарий: кластер YTsaurus развёрнут в Kubernetes, и требуется проверить доступ с локальной машины.
Для быстрого доступа к API контрольных прокси порт открыт через kubectl port-forward:
$ kubectl port-forward service/http-proxies-control-lb 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Выполним лёгкую операцию — создать таблицу.
$ export YT_PROXY=127.0.0.1:8080
$ yt create table //home/my-table
30-56c4-10191-712a11b3
Команда сработала: таблица создана. Механизм Discovery не задействовался, запрос ушёл напрямую на адрес, указанный в переменной YT_PROXY.
Теперь попробуем записать данные в эту таблицу (write-table):
$ echo '{ "id": 0, "text": "Hello" }' | yt write-table //home/my-table --format json
WARNING HTTP PUT request http://hp-0.http-proxies.default.svc.cluster.local/api/v4/write_table failed with error NewConnectionError...
Failed to establish a new connection: [Errno -3] Temporary failure in name resolution
Что произошло:
При выполнении write-table SDK запросил список data-прокси. Кластер вернул внутренний адрес пода: hp-0.http-proxies.default.svc.cluster.local. SDK попытался соединиться с этим FQDN напрямую, но с локальной машины это имя не резолвится.
В качестве временного решения для отладки можно отключить Discovery на клиенте. Сделать это можно через переменные окружения, тогда весь трафик пойдёт через port-forward:
# Через патч конфига:
export YT_CONFIG_PATCHES='{proxy={enable_proxy_discovery=%false}}'
# Или через более короткий и популярный алиас для CLI:
export YT_USE_HOSTS=0
echo '{ "id": 0, "text": "Hello" }' | yt write-table //home/my-table --format json
Если после этого запись прошла успешно — значит, проблема именно в маршрутизации Discovery.
Как решить проблему сетевой изоляции
Если вы настроили Ingress, но при попытке записать данные получаете ошибки, несмотря на работающие команды list или create, — вы столкнулись с проблемой изоляции.
Решить проблему можно несколькими способами:
- Использовать прямую маршрутизацию
- Использовать Host Network
- Настроить Kubernetes Services и подмену адресов
Использовать прямую маршрутизацию
Если ваша сетевая инфраструктура позволяет обращаться к подам напрямую (например, используется CNI Calico с маршрутизацией BGP или AWS VPC CNI), дополнительная настройка YTsaurus не требуется. Механизм Discovery вернёт внутренние FQDN подов (например, hp-0.http-proxies.default.svc.cluster.local).
Однако внешний клиент должен иметь возможность:
- Разрешить DNS-имена подов. Внутренние FQDN вида
*.svc.cluster.localпо умолчанию известны только DNS-серверу внутри кластера Kubernetes — внешний клиент не сможет их разрешить через обычные публичные DNS-серверы. - Установить сетевое соединение. Даже если имя разрешилось в IP-адрес, клиент должен иметь сетевую связность с этим IP (маршрутизацию).
Настройка для AWS
В AWS самый простой способ получить доступ к подам, которые уже имеют сетевую связность в dual stack режиме, — это настроить CoreDNS для разрешения имён подов. Для этого необходимо:
- Открыть доступ к CoreDNS в кластере для внешних клиентов.
- Настроить CoreDNS отвечать на запросы вида
*.cluster.domain.name, гдеcluster.domain.name— это доменное имя вашего кластера.
Пример настройки CoreDNS ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
# ВНИМАНИЕ: Замените 'cluster.domain.name' на реальный домен вашего кластера.
# Этот шаблон позволяет внешним клиентам находить IP-адреса подов по их именам.
template IN A cluster.domain.name {
match "^([^.]+)\.http-proxies\.default\.svc\.cluster\.domain\.name\.$"
answer "{{ .Name }} 60 IN A {{ .Group 1 | replace \"-\" \".\" }}"
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
После этого внешние клиенты смогут разрешать FQDN подов в их реальные IP-адреса и устанавливать прямые соединения.
Использовать Host Network
В этом режиме поды прокси не получают выделенного IP-адреса на под из внутренней сети кластера K8s, а используют сетевой интерфейс физического сервера (ноды), на котором они запущены.
Чтобы включить режим, добавьте поле hostNetwork: true в корневой уровень спецификации оператора:
apiVersion: cluster.ytsaurus.tech/v1
kind: Ytsaurus
metadata:
name: my-cluster
spec:
# Включаем использование сети хоста для всех компонентов.
hostNetwork: true
httpProxies:
- serviceType: ClusterIP # При hostNetwork внешний сервис K8s не обязателен.
instanceCount: 1
# ... остальные настройки ...
В этом случае прокси будут регистрироваться в Кипарисе под именами нод кластера Kubernetes. Они будут отдавать именно эти имена K8s-нод клиентам при Discovery. Дальше внешним клиентам необходимо самостоятельно разрешать DNS-имена этих нод.
Важно
В режиме hostNetwork прокси будут занимать порты (по умолчанию 80 и 443) непосредственно на нодах кластера. Убедитесь, что на этих узлах не запущены другие конфликтующие веб-сервисы, либо измените порты в конфигурации.
Настроить K8S Services и подмену адресов
Этот способ наиболее универсален для облачных сред. Прокси публикуются через сервисы (NodePort или LoadBalancer), а YTsaurus конфигурируется так, чтобы механизм Discovery возвращал клиентам именно эти внешние адреса, а не внутренние имена (FQDN) подов.
Этот подход требует двух шагов:
- Открыть порты через K8s-сервисы (NodePort или LoadBalancer).
- Настроить подмену адресов (Advertised Addresses).
Шаг 1: Открыть порты
В спецификации оператора укажите тип сервиса для нужных групп прокси. Например:
spec:
# HTTP прокси
httpProxies:
- role: control
serviceType: LoadBalancer # Входная точка для лёгких запросов
instanceCount: 1
- role: default
serviceType: NodePort # Точки входа для тяжёлых запросов (Data)
instanceCount: 3
# RPC прокси
rpcProxies:
- role: project-a
serviceType: LoadBalancer
instanceCount: 2
Шаг 2: Настроить подмены адресов (Discovery)
Даже если сервисы созданы, команда discover_proxies всё ещё будет возвращать внутренние FQDN подов. Необходимо настроить YTsaurus так, чтобы он возвращал внешние адреса, которые ведут на созданные сервисы.
Для этого задайте конфигурацию атрибутам //sys/http_proxies/@balancers и //sys/rpc_proxies/@balancers:
{
"<proxy_role>" = {
"<address_type>" = {
"<network_name>" = ["<external_addr_1>"; "<external_addr_2>"]
}
}
}
proxy_role— роль прокси (например,defaultилиproject-a).address_type— тип протокола. Используйтеhttpдля HTTP-прокси иinternal_rpcдля RPC-прокси.network_name— имя сети. В серверных компонентах YTsaurus есть поддержка нескольких интерфейсов (исторически для разделения real-time и bulk трафика). В Kubernetes у пода обычно один сетевой интерфейс, поэтому стандартное значение —default.
Важно
Значение internal_rpc у параметра address_type — историческое. Оно относится к внутренней реализации кода и не означает, что адреса должны быть внутренними. В этот блок нужно вписывать внешние адреса (или FQDN), доступные клиентам.
Обратите внимание, что формат конфигурации — YSON, поэтому элементы списков разделяются не запятой, а точкой с запятой (;).
Примечание
Настройку адресов необходимо задавать для каждой роли отдельно.
Пример настройки
Предположим, в кластере сконфигурированы две роли прокси:
- Контрольные прокси: доступны через общий LoadBalancer (или Ingress) по адресу
yt.example.com. - Data-прокси: вы запустили три инстанса и открыли к ним прямой доступ через NodePort. При использовании NodePort порт одинаков для всех узлов K8s, поэтому адреса будут вида:
node1.example.com:30001,node2.example.com:30001иnode3.example.com:30001.
Чтобы Discovery корректно возвращал эти адреса для каждой роли, выполните команды:
# 1. Настройка адресов для Data-прокси (роль default)
# Эти адреса будут использоваться для тяжёлых операций (чтение/запись).
$ yt set //sys/http_proxies/@balancers/default \
'{"http"={"default"=[
"node1.example.com:30001";
"node2.example.com:30001";
"node3.example.com:30001"
]}}'
# 2. Настройка адреса для контрольных прокси (роль control)
# Этот адрес будет возвращаться, если клиент явно запросит дискавери для контрольной группы.
$ yt set //sys/http_proxies/@balancers/control \
'{"http"={"default"=[
"yt.example.com"
]}}'
Совет
В примере команда set применяется к конкретным путям (@balancers/default и @balancers/control), а не к корневому атрибуту @balancers. Такой подход безопаснее: каждая роль конфигурируется независимо, без риска случайно перезаписать конфигурацию других ролей.
Как настроить доступ к SPYT
Для работы SPYT в режиме Standalone внешний драйвер Spark должен соединяться напрямую со Spark-воркерами. Эти воркеры запускаются не как отдельные поды Kubernetes, а как процессы внутри Vanilla-джобов YTsaurus. Стандартные сетевые абстракции Kubernetes (Services) не умеют адресовать трафик внутрь таких процессов.
Для проксирования таких соединений используется tcp_proxy. Это компонент YTsaurus, который знает, на какой ноде и на каком порту запустился конкретный процесс воркера, и умеет пробросить туда трафик снаружи — на основе таблиц в Кипарисе //sys/tcp_proxies/routes.
Чтобы настроить tcp_proxy:
- Убедитесь, что порты, на которых работает
tcp_proxy(по умолчанию 32000–32019), открыты через Kubernetes-сервисы (NodePort или LoadBalancer). - Пропишите внешние адреса этих портов в атрибут
//sys/tcp_proxies/routes/<proxy_role>/@external_addressesв Кипарисе.
Это позволит драйверу Spark использовать tcp_proxy как посредника для связи с внутренними воркерами.
Пример:
yt set //sys/tcp_proxies/routes/default/@external_addresses '["node1.example.com:32000"; "node2.example.com:32000"]'
Как разделить трафик
По умолчанию все прокси в кластере имеют роль default. Это создаёт проблему «шумных соседей»: один пользователь, запустивший тяжёлую операцию чтения, может перегрузить прокси и замедлить работу всех остальных, включая запросы веб-интерфейса.
Решение — разбить прокси на группы с помощью ролей. Это позволит разделить нагрузку между лёгкими и тяжёлыми запросами, а также изолировать ресурсы разных проектов и команд.
Разделение лёгкого и тяжёлого трафика (для HTTP)
На практике HTTP-прокси обычно делят на две функциональных группы:
- Control-прокси (обычно с ролью
control) — обслуживают «лёгкие» запросы: просмотр веб-интерфейса, листинг директорий, создание/удаление таблиц, работа с метаинформацией. - Data-прокси (обычно с ролью
default) — обслуживают «тяжёлые» запросы: чтение и запись таблиц или файлов.
Для отказоустойчивости рекомендуется, чтобы каждой роли соответствовало несколько реплик прокси.
Задать роли можно в спецификации Ytsaurus:
spec:
httpProxies:
# Тяжёлая группа (по умолчанию принимает Data-трафик)
- role: default
instanceCount: 5
serviceType: NodePort
# Контрольная группа (UI и метаданные)
- role: control
instanceCount: 2
serviceType: LoadBalancer # Удобно для Ingress
Примечание
Имя роли становится частью имени K8s-пода (например, hp-control-0). Поэтому используйте только DNS-совместимые имена (строчные буквы, цифры и дефисы). Символ подчеркивания (_) использовать нельзя.
Как это работает:
- Оператор создаёт две независимые группы подов (StatefulSets) с лейблами
controlиdefault. - Оператор автоматически создаёт Kubernetes-сервис (Service) для каждой группы. В селекторе сервиса
http-proxies-controlпрописан фильтр: «обслуживать только поды с меткой control». - Вы настраиваете Ingress/DNS на сервис группы
control. Клиенты будут автоматически получать адреса Data-прокси через механизм Discovery и отправлять тяжёлые запросы напрямую на них.
Примечание
При создании Service или Ingress вручную (без участия оператора) убедитесь, что в Label Selector сервиса прописан правильный фильтр по метке роли. Проверить лейблы на запущенных подах можно командой kubectl get pods --show-labels. Без этого фильтра балансировщик будет отправлять лёгкие запросы на все прокси подряд, включая Data-прокси.
Особенности HTTP доступа и Ingress
Для HTTP-прокси часто используют Ingress-контроллеры для терминации SSL и маршрутизации. Если Ingress используется только для Control-прокси, а Data-прокси выставлены через NodePort (как описано выше), схема работает эффективно.
Если же весь трафик требуется направить через Ingress (включая Data), придётся решить несколько проблем:
- Двойная балансировка и потеря эффективности.
- Сложные правила Ingress для каждого пода data-прокси отдельно (для прямой адресуемости).
- Настройка липких сессий для корректной работы с транзакциями.
Проблема липких сессий
При использовании Ingress для data-прокси важно учитывать особенности работы с транзакциями. Транзакции в YTsaurus создаются на конкретном прокси, и все последующие запросы в рамках одной транзакции должны попадать на тот же самый прокси. Вызов через Ingress-контроллер случайным образом может привести к ошибкам вида "Transaction not found" или "Invalid transaction state". Чтобы избежать этого, настройте липкие сессии в вашем Ingress-контроллере.
Настройка липких сессий зависит от используемого Ingress-контроллера:
- NGINX Ingress: используйте аннотацию
nginx.ingress.kubernetes.io/affinity: "cookie" - Traefik: настройте
stickinessв конфигурации сервиса - HAProxy Ingress: используйте
haproxy.org/cookie-persistence
Пример для NGINX Ingress с липкими сессиями
Этот Ingress настраивает NGINX, чтобы он помечал клиента специальной cookie и всегда отправлял его на один и тот же под прокси.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: yt-data-proxies
annotations:
# Включаем липкие сессии: NGINX запомнит, на какой под отправить клиента
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "yt-proxy-id"
nginx.ingress.kubernetes.io/session-cookie-max-age: "14400"
spec:
rules:
- host: yt-data.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: http-proxies-default
port:
number: 80
Про TLS
Важно
При выставлении Data-прокси напрямую (через NodePort) трафик не проходит через Ingress, а значит, передается без TLS-шифрования.
Для высоконагруженных инсталляций, если нет жёстких требований к шифрованию, оптимальной остаётся раздельная схема:
- используйте Ingress только для Control-трафика (для удобного доступа к UI, лёгким API-запросам и HTTPS);
- Data-прокси публикуйте напрямую через NodePort или LoadBalancer с настроенным механизмом Discovery (трафик пойдёт открыто, но максимально производительно).
Если требования безопасности диктуют обязательное использование шифрования для внешних клиентов, есть два пути:
- направлять весь трафик через Ingress (с настроенными липкими сессиями), принимая во внимание возможное снижение производительности,
- либо настраивать балансировщики (Network Load Balancer) или внутренний TLS в самом кластере.
Изоляция проектов (для RPC)
Для RPC-прокси чаще применяется деление по проектам. Например, можно создать выделенную группу прокси с ролью project-a и выдать доступ к ней только конкретному пользователю.
spec:
rpcProxies:
# Поды для общих нужд
- role: default
instanceCount: 2
serviceType: NodePort
# Выделенные поды под проект Project A
- role: project-a
instanceCount: 2
serviceType: NodePort
Чтобы клиент начал работать с выделенной группой прокси, в коде приложения (или в настройках CLI) нужно явно указать proxy_role. Если этого не сделать, клиент по умолчанию пойдёт в роль default.
Пример для Python
# Пример клиента Python, жестко привязанного к группе
client = yt.YtClient(proxy="yt.cluster", config={"proxy_role": "project-a"})
Пример для CLI
# Можно передать через переменную окружения перед запуском скриптов
export YT_CONFIG_PATCHES='{proxy_role="project-a"}'
yt list //home
FAQ
Можно ли использовать для Data-прокси роль с названием, отличным от default (например, heavy)?
Да, но это требует дополнительной настройки.
По умолчанию клиентские библиотеки (SDK) отправляют все тяжёлые запросы (чтение/запись) в группу прокси с ролью default. Если в операторе создать группу с ролью heavy, но не перенастроить кластер, SDK не узнает о её существовании и продолжит искать несуществующую роль default.
Чтобы перенаправить стандартный трафик клиентов в новую группу, измените атрибут @default_role_filter в Кипарисе:
# Теперь клиенты, не указавшие роль явно, будут направляться на прокси с ролью 'heavy'
yt set //sys/http_proxies/@default_role_filter heavy
Можно ли направить весь трафик (включая Data) через Ingress?
Технически — можно, но для высоконагруженных инсталляций это не рекомендуется. Если настроить клиенты на работу без Discovery (только через Ingress), возникнут три проблемы:
- Двойная балансировка. Весь трафик проходит через промежуточный Ingress-контроллер, что увеличивает задержки.
- Сложность настройки. Для работы Discovery через Ingress придётся создавать отдельный Ingress-ресурс и DNS-имя для каждого пода Data-прокси.
- Проблемы с транзакциями. Необходима настройка липких сессий.
Для высоконагруженных инсталляций рекомендуется комбинированный подход:
- L7 (Ingress): Используйте только для Control-трафика (роль
control). Это даст понятное доменное имя, SSL и удобство для пользователей. - L4 (NodePort/LoadBalancer): Используйте для Data-трафика (роль
default). Это позволит клиентам соединяться с подами напрямую (через Discovery и Advertised Addresses), обеспечивая максимальную пропускную способность без узкого места (bottleneck) в виде Ingress-контроллера.
Почему команды list и create работают, а write-table падает с ошибкой сети?
Это признак неверно настроенного (или ненастроенного) Discovery.
Лёгкие команды идут через контрольные прокси. Тяжёлые команды (read-table, write-table) пытаются соединиться с Data-прокси напрямую. Ошибка «Name resolution failure» или «Connection refused» на записи означает, что Discovery возвращает клиенту внутренние адреса подов.
Настройте подмену адресов через атрибут //sys/http_proxies/@balancers (см. раздел Настройка подмены адресов).
Можно ли временно отключить Discovery для отладки?
Да, механизм Discovery можно отключить на стороне клиента (опция конфига enable_proxy_discovery=%false). Это удобно для быстрой отладки и тестирования: трафик перестаёт разделяться и направляется в единую точку входа.
Примеры, как отключить Discovery:
client = yt.YtClient(proxy="localhost:8080", config={"proxy": {"enable_proxy_discovery": False}})
export YT_USE_HOSTS=0
# Или:
# export YT_CONFIG_PATCHES='{proxy={enable_proxy_discovery=%false}}'
Важно
Не используйте этот режим в продакшене для передачи больших данных — это создаст узкое место на входном балансировщике.
Можно ли указать роль прокси через атрибут в Кипарисе?
Да, роль конкретного инстанса можно сменить «на лету», изменив атрибут @role в Кипарисе. Это полезно для оперативного вывода прокси из-под нагрузки.
Пример смены роли через CLI:
# Назначаем конкретному прокси роль control
yt set //sys/http_proxies/hp-0.http-proxies.default.svc.cluster.local:80/@role control
Внимание
При перезапуске пода роль вернётся к значению, указанному в спецификации оператора.
LoadBalancer и Ingress пропускают весь трафик через одну точку входа, но при больших объёмах данных это становится узким местом.
Чтобы масштабировать нагрузку, клиенты должны подключаться к узлам кластера напрямую. В Kubernetes IP-адреса подов по умолчанию внутренние — внешние клиенты не смогут к ним обратиться напрямую без дополнительной настройки.
Липкие сессии (sticky sessions) — механизм балансировки, при котором Ingress-контроллер привязывает клиента к конкретному серверу (поду) на время всей сессии. При первом обращении балансировщик выдаёт клиенту специальную cookie-метку, благодаря которой все последующие запросы гарантированно попадают на тот же самый под.