место для рекламы
Хотите вместе создать новую бессерверную систему исследований и разработок? Добро пожаловать в команду беспроводных серверов Alibaba CBU, мы ищем старших инженеров / технических экспертов по исследованиям и разработкам, отправьте свое резюме на yuanyan.lmh@alibaba-inc.com
Сегодня попробуем развернуть кластер Redis в k8s и узнать больше о деталях и возможностях k8s.
Среда: minikube v0.30 (kubernetes 1.10)
Примечание. Базовые знания и подробности, связанные с redis-cluster, здесь повторяться не будут, вы можете обратиться кпредыдущая статьяНебольшой обзор
анализ проблемы
По сути, нет большой разницы между развёртыванием redis-кластера на k8s и развёртыванием обычного приложения, но нужно обратить внимание на следующие моменты:
-
REDIS — это приложение с отслеживанием состояния
Это самая важная проблема, на которую мы должны обратить внимание при развертывании кластера Redis.Когда мы развертываем Redis в виде подов в k8s, данные, кэшированные в каждом поде, разные, и IP-адрес пода может измениться в любое время. , В то время, если вы используете обычное развертывание и службу для развертывания redis-кластера, будет много проблем, поэтому вам нужно использовать StatefulSet + Headless Service для ее решения.
-
сохранение данных
Хотя Redis — это кеш в памяти, ему по-прежнему необходимо полагаться на диск для сохранения данных, чтобы кешированные данные можно было восстановить, когда у службы возникнет проблема и она перезапустится. В кластере нам нужно использовать метод общей файловой системы + PV (постоянный том), чтобы позволить всем модулям во всем кластере совместно использовать одно и то же постоянное хранилище.
Введение концепции
Прежде чем мы начнем, давайте подробно познакомимся с некоторыми понятиями и принципами.
Headless Service
Проще говоря, безголовая служба — это служба, которая не указывает IP-адрес кластера, соответственно, в dns-маппинге k8s результатом разрешения безголовой службы является не IP-адрес кластера, а список IP-адресов всех подов, связанных с ним.
StatefulSet
StatefulSet
Это ресурс в k8s, посвященный решению задач развертывания приложений с отслеживанием состояния.Deployment/RC
Вариант , который имеет следующие особенности:
-
Каждый под, управляемый StatefulSet, имеет уникальный идентификатор документа/сети, который генерируется в соответствии с числовым законом, вместо того, чтобы иметь случайные имена и IP-адреса, как в развертывании (например, если имя StatefulSet — redis, то имя пода — redis). 0, редис -1...)
-
Последовательность запуска и остановки ReplicaSet в StatefulSet строго контролируется, и работа N-го модуля должна ожидать выполнения первых N-1 модулей.
-
Поды в StatefulSet используют стабильное постоянное хранилище, и соответствующий PV не будет уничтожен при удалении пода.
Кроме того, следует отметить, что StatefulSet необходимо использовать с Headless Service.Это добавит еще один уровень к сопоставлению DNS, предоставляемому Headless Service, и, наконец, сформирует сопоставление доменных имен, точное для каждого модуля.Формат выглядит следующим образом:
$(podname).$(headless service name)
С помощью этого сопоставления вы можете использовать доменное имя вместо IP-адреса при настройке кластера для управления кластерами приложений с отслеживанием состояния.
план
С помощью StatefulSet и Headless Service схема развертывания кластера построена следующим образом (картинка из справочной статьи):
Шаги настройки примерно перечислены ниже:
- Настройка общей файловой системы NFS
- Создание PV и PVC
- Создать карту конфигурации
- Создать безголовый сервис
- Создать StatefulSet
- Инициализировать кластер Redis
Фактическая операция
Поскольку используется одноузловая среда minikube, для упрощения сложности в этот раз PV и PVC не настраиваются, а данные монтируются напрямую через обычный Volume.
Создать карту конфигурации
создать первыйredis.conf
конфигурационный файл
appendonly yes
cluster-enabled yes
cluster-config-file /var/lib/redis/nodes.conf
cluster-node-timeout 5000
dir /var/lib/redis
port 6379
потомkubectl create configmap redis-conf --from-file=redis.conf
для создания ConfigMap
Создать безголовый сервис
apiVersion: v1
kind: Service
metadata:
name: redis-service
labels:
app: redis
spec:
ports:
- name: redis-port
port: 6379
clusterIP: None
selector:
app: redis
appCluster: redis-cluster
Создать StatefulSet
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: redis-app
spec:
serviceName: "redis-service"
replicas: 6
template:
metadata:
labels:
app: redis
appCluster: redis-cluster
spec:
terminationGracePeriodSeconds: 20
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
topologyKey: kubernetes.io/hostname
containers:
- name: redis
image: "registry.cn-qingdao.aliyuncs.com/gold-faas/gold-redis:1.0"
command:
- "redis-server"
args:
- "/etc/redis/redis.conf"
- "--protected-mode"
- "no"
resources:
requests:
cpu: "100m"
memory: "100Mi"
ports:
- name: redis
containerPort: 6379
protocol: "TCP"
- name: cluster
containerPort: 16379
protocol: "TCP"
volumeMounts:
- name: "redis-conf"
mountPath: "/etc/redis"
- name: "redis-data"
mountPath: "/var/lib/redis"
volumes:
- name: "redis-conf"
configMap:
name: "redis-conf"
items:
- key: "redis.conf"
path: "redis.conf"
- name: "redis-data"
emptyDir: {}
Инициализировать кластер Redis
После создания StatefulSet видно, что запущено 6 подов, но в это время весь кластер redis не инициализирован, нужно использовать официально предоставленныйredis-trib
инструмент.
Мы, конечно, можем запустить соответствующий инструмент на любом узле redis для инициализации всего кластера, но это явно не подходит, мы хотим, чтобы обязанности каждого узла были как можно более едиными, поэтому лучше иметь отдельный pod для запуска все инструменты управления кластером.
Здесь нам нужно представитьredis-trib
, это официальный инструмент управления кластером Redis, который может создавать и обновлять кластеры Redis.redis-trib.rb
То, как работает этот ruby-скрипт (можно и python-версию на pip тянуть, но мне не удалось его запустить), сейчас (использую5.0.3
) был официально интегрирован вredis-cli
середина.
Начните инициализировать кластер, сначала создайте ubuntu pod на k8s в качестве узла управления:
kubectl run -i --tty redis-cluster-manager --image=ubuntu --restart=Never /bin/bash
Войдите в модуль и сначала установите некоторые инструменты, в том числеwget
,dnsutils
, затем загрузите и установите Redis:
wget http://download.redis.io/releases/redis-5.0.3.tar.gz
tar -xvzf redis-5.0.3.tar.gz
cd redis-5.0.3.tar.gz && make
После компиляцииredis-cli
будет помещен вsrc
каталог, поместите его в/usr/local/bin
удобно для последующих операций
Затем, чтобы получить IP-адрес хоста из 6 созданных узлов, вы можете пройтиnslookup
В сочетании с правилами доменного имени StatefulSet для поиска, например, для поискаredis-app-0
Для IP-адреса этого модуля выполните следующую команду:
root@redis-cluster-manager:/# nslookup redis-app-0.redis-service
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: redis-app-0.redis-service.gold.svc.cluster.local
Address: 172.17.0.10
172.17.0.10
это соответствующий ip. В этом развертывании мы используем 0, 1 и 2 в качестве главных узлов и 3, 4 и 5 в качестве подчиненных узлов.Сначала выполните следующую команду, чтобы инициализировать главный узел кластера:
redis-cli --cluster create 172.17.0.10:6379 172.17.0.11:6379 172.17.0.12:6379
Затем прикрепите к ним соответствующие узлы Slave соответственно, здесьcluster-master-id
При создании на предыдущем шаге он даст:
redis-cli --cluster add-node 172.17.0.13:6379 172.17.0.10:6379 --cluster-slave --cluster-master-id adf443a4d33c4db2c0d4669d61915ae6faa96b46
redis-cli --cluster add-node 172.17.0.14:6379 172.17.0.11:6379 --cluster-slave --cluster-master-id 6e5adcb56a871a3d78343a38fcdec67be7ae98f8
redis-cli --cluster add-node 172.17.0.16:6379 172.17.0.12:6379 --cluster-slave --cluster-master-id c061e37c5052c22f056fff2a014a9f63c3f47ca0
После инициализации кластера введите узел по желанию, чтобы проверить информацию о кластере:
На этом инициализация кластера завершена, вводим ноду на пробу, обратите внимание на режим кластераredis-cli
необходимо добавить-c
параметры для доступа к данным на других узлах:
Создать сервис
Теперь введите любой кластер Node Redis Cluster можно напрямую, но, чтобы иметь возможность предоставить доступ к кластерам других услуг, также необходимо установить услугу для достижения службы открытия и балансировки нагрузки (обратите внимание, что обслуживание здесь и без головы, которое мы создали более раннее обслуживание, не вещь)
Файл yaml выглядит следующим образом:
apiVersion: v1
kind: Service
metadata:
name: gold-redis
labels:
app: redis
spec:
ports:
- name: redis-port
protocol: "TCP"
port: 6379
targetPort: 6379
selector:
app: redis
appCluster: redis-cluster
Проведите тест после развертывания:
Очень красиво, вся работа сделана здесь~