Можно ли создать кластер Redis в Kubernetes с помощью поисковой сетки Istio? - PullRequest
0 голосов
/ 23 октября 2019

Я пытаюсь настроить кластер Redis на Kubernetes с установленной сеткой Istio. Redis Cluster может быть создан без Istio, и каждый Pod автоматически вводится с помощью Istio Proxy (Envoy). Однако с установленным Istio и подключенным к каждому из Redis Pod прокси-сервером Istio кластер Redis не может правильно «встретиться» с помощью команды CLUSTER MEET от CLI.

Например, у меня есть Redis Pod A (слот 0 - 10919) и Redis Pod B (слот 10920 - 16383). Это результат после попытки выполнить команду CLUSTER MEET между ними (кластер соответствует ClusterIPForRedisPodB 6379).

Для Redis Pod A информация о кластере обновляется и включает Redis Pod B:

Redis Pod A

Напротив, для Redis PodB, информация о кластере не обновляется и не включает в себя Redis Pod A:

Redis Pod B

Я могу отправлять ответы curl и netcat между двумя модулямидля портов 16379 и 6379. Кроме того, Envoy, по-видимому, также открыл эти порты.

1 Ответ

0 голосов
/ 31 октября 2019

Я повторил вашу проблему и нашел решение вашей проблемы.

Позвольте мне начать с объяснения причины вашей проблемы.

Протокол сплетен Redis работает следующим образом: когда вывведите cluster meet <ip> <port> on redis1 , redis1 открывает TCP-соединение с redis2 . В обычном случае, когда redis2 получает соединение, оно принимает его, ищет IP-адрес источника подключающегося и также открывает tcp-соединение с этим адресом, поэтому в этом случае redis1 ,(Подробнее о том, как работает протокол сплетен inredis, можно найти в документации redis или в этой статье )

Здесь приводится часть istio . Istio по умолчанию настраивает посланника в качестве типичного прокси и, как вы можете прочитать в документации istio :

interception mode

Istio по умолчанию используетREDIRECT Прокси и как указано в документации:

Этот режим теряет IP-адреса источника при перенаправлении

Это наш источник проблемы.

redis2 когда получает соединение, оно видит, что оно исходит от localhost. Посланник потерял исходный IP-адрес redis1 и redis2 теперь не может открыть подключение обратно к redis1 .

Теперь у нас есть некоторыепараметры:

  1. вы можете попробовать изменить режим проксирования на TPROXY (я пробовал, но не смог заставить его работать)
  2. использовать встроенную переменную конфигурации redis

Давайте посмотрим на второй вариант немного ближе, потому что это тот, который работал для меня. В файле redis.conf вы можете найти этот раздел:

Поддержка CLUSTER DOCKER / NAT

В некоторых развертываниях обнаружение адресов узлов Redis Cluster не выполняется, поскольку адресаNAT-ted или потому что порты переадресованы (типичный случай - Docker и другие контейнеры).

Для того, чтобы заставить Redis Cluster работать в таких средах, необходима статическая конфигурация, где каждый узел знает свой публичный адрес. Для этой области используются следующие два параметра:

  • cluster-announce-ip
  • cluster-announce-port
  • cluster-announce-bus-порт

Каждый сообщает узлу свой адрес, порт клиента и порт шины сообщений кластера. Затем информация публикуется в заголовке пакетов шины, чтобы другие узлы могли правильно отобразить адрес узла, публикующего информацию.

Если указанные выше параметры не используются, обычный автоматический Redis Cluster auto-detection будет использоваться вместо этого.

Обратите внимание, что при переназначении шинный порт может не иметь фиксированного смещения клиентского порта + 10000, поэтому вы можете указать любой порт и шинный порт в зависимости от того, как они переназначаются,Если шинный порт не задан, то обычно используется фиксированное смещение 10000.

Пример:

cluster-announce-ip 10.1.1.5
cluster-announce-port6379
порт кластера-анонса-шины 6380

Нам нужно установить переменную cluster-announce-ip на собственный IP-адрес модуля pis.

Вы можете сделать это, например, изменив redis-cluster ConfigMap следующим образом (это модифицированный redis configmap из этой статьи ):

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster
data:
  update-node.sh: |
      #!/bin/sh
      REDIS_NODES="/data/nodes.conf"
      sed -i -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${REDIS_NODES}
      cp /conf/redis.conf /redis.conf # <------HERE-----
      sed -i "s/MY_IP/${POD_IP}/" /redis.conf # <------HERE-----
      exec "$@"
  redis.conf: |+
      cluster-enabled yes
      cluster-require-full-coverage no
      cluster-node-timeout 15000
      cluster-config-file /data/nodes.conf
      cluster-migration-barrier 1
      appendonly yes
      protected-mode no
      cluster-announce-ip MY_IP # <------HERE-----

Также не забудьте изменить command вашего контейнера следующим образомчтобы указать redis.conf файл справа:

command: ["/conf/update-node.sh", "redis-server", "/redis.conf"]

Каждый узел redis теперь будет объявлять этот адрес как свой собственный, поэтому другие узлы redis теперь будут знать, как с ним связаться.

Дайте мне знать, если это помогло.

...