У меня проблемы с отображением моего 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.
Я исследовал эту проблему на стороне 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
ОБНОВИТЬ:
Думаю, я не совсем понимаю вопрос. И после комментария ОП. Я собираюсь рассмотреть настройку кластера Redis и аналогичные проблемы.
Вот что я нашел
Из этого Проблема с Github Когда Redis выполняет такое поведение «Перенаправлено в слот xxx», он не проксирует соединение через сервер Redis, а просто передает IP-адрес соответствующего сервера обратно клиенту, который затем инициирует соединение напрямую.
Из этого Проблема с Github В случае, когда один из контейнеров докеров умирает и появляется новый контейнер, мы повторно подключаем к нему файл nodes.conf из тома, чтобы он снова мог автоматически присоединиться к работающему в данный момент кластеру Redis. Однако, когда контейнер возвращается, он получает другой IP-адрес. И когда мы запускаем новый сервер Redis внутри этого контейнера, он не обновляет IP-адрес внутри файла nodes.conf для единственного нового сгенерированного контейнера. Но все остальные узлы знают о новом IP-адресе внутри своего файла nodes.conf. В целом, вышедший из строя узел не обновляет свой IP-адрес внутри nodes.conf
Итак, вывод: нам нужно обновить IP-адрес модуля до nodes.conf
после перезапуска, чтобы он мог присоединиться к кластеру. Пример можно найти Вот добавив скрипт для добавления podIP в nodes.conf
после перезапуска.
СТАРЫЙ ОТВЕТ:
Если вы используете LoadBalancer
service, рассмотрите возможность использования статического 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"
Заменить YOUR.IP.ADDRESS.HERE
с зарезервированным внутренним IP-адресом (помните, что это региональный IP-адрес).