У меня проблемы с открытием моего Redis Cluster в Kubernetes внешним приложениям. Используя службу балансировки нагрузки Kubernetes, я могу назначить Redis внешний IP-адрес, который обеспечивает начальное подключение. Проблема в том, что всякий раз, когда клиент получает команду MOVED
, IP-адрес является внутренним IP-адресом POD Kubernetes, который недоступен для клиентов redis за пределами кластера.
Вот пример сеанса из redis-cli
для демонстрации:
10.150.0.5:7000> set test value
-> Redirected to slot [6918] located at 10.28.1.9:6379
Could not connect to Redis at 10.28.1.9:6379: Operation timed out
Как решить эту проблему? Ни одно из учебных пособий / руководств, которые я прочитал, не проливает света на доступ к кластеру внешним службам. Большинство из них озабочено настройкой кластера Redis в K8s.
Для тех, кто все еще ищет ответ, лучшим вариантом, который я нашел, является использование (теперь официальное) прокси-сервера Redis https://github.com/RedisLabs/redis- кластер-прокси.
Примечание. Как упоминает Йогеш в своем комментарии, это альфа-код, поэтому, пожалуйста, не делайте этого в производственных рабочих нагрузках, пока код не станет стабильным / вы не знаете, что делаете.
Объяснение Прокси-сервер в основном «притворяется» одним экземпляром Redis, поэтому клиентам, подключающимся к нему, не нужно знать о кластере.
Вы должны использовать последнюю версию Redis, желательно v6 или выше.
ОБНОВЛЕНИЕ:
Думаю, я не совсем понимаю вопрос. И после комментария ОП. Я собираюсь изучить настройку кластера Redis и аналогичные проблемы.
Вот что я обнаружил
Из этой проблемы Github Когда Redis выполняет такое поведение «Перенаправлен в слот xxx», он не проксирует соединение через сервер Redis, а просто передает IP-адрес соответствующего сервера обратно клиенту, который затем инициирует подключение напрямую.
Из этого Проблема с Github В случае, когда один из контейнеров докеров умирает, и появляется новый контейнер, мы повторно подключаем node.conf из тома к нему, чтобы он мог присоединиться к текущему запущенному Redis кластер снова автоматически. Однако когда контейнер возвращается, он получает другой IP-адрес. И когда мы запускаем новый сервер Redis внутри этого контейнера, он не обновляет IP-адрес внутри файла nodes.conf для единственного нового сгенерированного контейнера. Но все остальные узлы знают о новом IP-адресе внутри своего файла nodes.conf. В целом, вышедший из строя узел не обновляет свой IP-адрес внутри nodes.conf
Итак, вывод состоит в том, что нам необходимо обновить IP-адрес модуля в файле nodes.conf
после перезапуска. , поэтому он может присоединиться к кластеру. Пример можно найти здесь , добавив скрипт для добавления podIP в node.conf
после перезапуска.
СТАРЫЙ ОТВЕТ:
Если вы используете LoadBalancer
, рассмотрите возможность использования статического IP-адреса, чтобы он не был назначен новому IP-адресу.
Вот пример
apiVersion: v1
kind: Service
metadata:
name: redis
labels:
app: redis
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
type: LoadBalancer
loadBalancerIP: "YOUR.IP.ADDRESS.HERE"
Замените ВАШ.IP.АДРЕС.ЗДЕСЬ
зарезервированным внутренним IP ( и помните, что это региональный IP-адрес).
Я исследовал эту проблему на стороне Google Cloud Platform, поскольку это моя область знаний, и обнаружил следующую документацию [1]. Другая документация по Redis [2] подтвердила ваши предположения о том, как Redis обрабатывает IP-адреса. Похоже, что узлы Redis будут использовать свой собственный IP-адрес при отправке клиенту, поэтому, когда клиент отвечает (через балансировщик нагрузки), используется неправильный IP-адрес. Такое поведение могло быть преднамеренным дизайнерами Redis. Мне не удалось найти обходной путь, и я должен признать, что это выходит за рамки моих возможностей. Пища для размышлений: хотя GKE можно использовать с базой данных, это не лучшая практика. Если вы действительно хотите использовать базу данных в k8s, вам следует использовать StatefulSet, который будет пытаться поддерживать тот же IP-адрес пода. Google предлагает альтернативные методы интеграции в облако. Доступно несколько продуктов, возможно, время, потраченное на изучение ваших потребностей и возможностей продуктов Google, будет полезным. Одним из них, в частности, будет Cloud Memorystore, поскольку он предназначен для использования с Redis. В документации к этому продукту говорится: «Cloud Memorystore для Redis полностью совместим с протоколом Redis». [3]
[1] Подключение к экземпляру Redis: https://cloud.google.com/memorystore/docs/redis/connect-redis-instance-gke [2] Роли клиента и сервера: https://redis.io/topics/cluster-spec [3] Обзор Cloud Memorystore для Redis: https://cloud.google.com/memorystore/docs/redis/redis-overview