Clusters Redis conteinerizados são fáceis de implantar e dimensionar, além de armazenarem recursos em espaços isolados. Isso aumenta a eficiência na implantação, no gerenciamento, no dimensionamento e na manutenção de clusters Redis, reduzindo os custos de operações e manutenção (O&M). Este tópico descreve como criar um cluster Redis em uma instância de contêiner elástica em um cluster Serverless do Container Service for Kubernetes (ACK).
Informações básicas
Instâncias Redis podem operar em modo cluster. Nesse modo, o Redis divide o espaço de armazenamento em 16.384 hash slots. Cada nó mestre no cluster Redis é responsável por um shard de banco de dados, composto por um número específico de hash slots. Ao gravar uma entrada de dados, o Redis calcula os hash slots correspondentes e escreve os dados no nó responsável por esses slots. É possível adicionar um ou mais nós escravos a cada nó mestre. Se um nó mestre ficar indisponível, um dos nós escravos assume automaticamente a função de mestre para manter o serviço ativo.
O modo cluster oferece alto throughput e alta disponibilidade. No entanto, mesmo nesse modo, o Redis não evita totalmente a perda de dados. Para mais detalhes, consulte a Documentação oficial do Redis.
Pré-requisitos
Crie um cluster ACK Serverless que atenda às seguintes condições:
O acesso à internet deve estar habilitado para o cluster, permitindo o pull de imagens públicas.
-
Um plug-in de armazenamento deve estar implantado no cluster.
Recomendamos a implantação do plug-in Container Storage Interface (CSI). Verifique se o componente Alibaba Cloud CSI-Provisioner está presente no plug-in CSI.
O CoreDNS deve estar implantado no cluster.
Crie um cluster Redis
Neste tópico, utilizamos a imagem oficial do Redis v6.0.8 como exemplo para criar um cluster composto por seis nós: três mestres e três escravos. Cada nó possui um status e um identificador próprios. Utilize um StatefulSet para criar os pods. Além disso, anexe um disco a cada nó para garantir o armazenamento persistente dos dados.
Recomendamos o uso do Redis v5.0 ou superior. Caso utilize uma versão anterior à 5.0, o comando de inicialização do cluster pode ser diferente do apresentado neste tópico.
-
Crie um ConfigMap para armazenar e gerencie as configurações do cluster Redis.
kubectl create -f redis-config.yamlExemplo de conteúdo do arquivo redis-config.yaml:
apiVersion: v1 kind: ConfigMap metadata: name: redis-cluster data: redis.conf: | bind 0.0.0.0 port 6379 cluster-announce-bus-port 16379 cluster-enabled yes appendonly yes cluster-node-timeout 5000 dir /data cluster-config-file /data/nodes.conf requirepass pass123 masterauth pass123O campo
dirdefine o diretório de armazenamento persistente para os dados dos nós no cluster Redis. O diretório/datados pods deve corresponder a esse local de armazenamento persistente.O campo
cluster-config-fileespecifique onde ficam as informações dos nós do cluster Redis. O próprio nó Redis gera e modifica essas informações automaticamente. O valor desse campo também aponta para um diretório de armazenamento persistente. Assim, caso um nó falhe, os demais nós do cluster conseguem assumir suas funções para manter o serviço disponível.
-
Crie um Service headless.
kubectl create -f redis-service.yamlExemplo de conteúdo do arquivo redis-service.yaml:
apiVersion: v1 kind: Service metadata: name: redis-cluster-svc spec: clusterIP: None selector: app: redis-cluster -
Crie um StatefulSet para implantar o Redis.
Ao criar o StatefulSet, referencie o Service criado anteriormente, monte o ConfigMap no diretório
/configde cada pod, crie uma persistent volume claim (PVC) para cada pod e monte essa PVC no diretório/data.kubectl create -f redis.yamlExemplo de conteúdo do arquivo redis.yaml:
apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-cluster spec: selector: matchLabels: app: redis-cluster serviceName: redis-cluster-svc replicas: 6 template: metadata: labels: app: redis-cluster alibabacloud.com/eci: "true" spec: terminationGracePeriodSeconds: 10 affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - redis-cluster topologyKey: kubernetes.io/hostname weight: 100 containers: - name: redis image: redis:6.0.8 command: ["redis-server", "/config/redis.conf"] ports: - name: redis containerPort: 6379 protocol: TCP - name: election containerPort: 16379 protocol: TCP volumeMounts: - name: redis-conf mountPath: /config - name: pvc-essd-redis-data mountPath: /data volumes: - name: redis-conf configMap: name: redis-cluster items: - key: redis.conf path: redis.conf volumeClaimTemplates: - metadata: name: pvc-essd-redis-data spec: accessModes: [ "ReadWriteOnce" ] storageClassName: alicloud-disk-essd resources: requests: storage: 20GiApós criar o StatefulSet, aguarde até que todos os pods atinjam o estado Ready.
kubectl get statefulset redis-cluster -o wideA saída do comando será semelhante a esta:
NAME READY AGE CONTAINERS IMAGES redis-cluster 6/6 8m52s redis redis:6.0.8 -
Inicialize o cluster.
-
Obtenha o endereço IP de cada nó.
O Redis não permite inicializar um cluster usando hostname. Portanto, é obrigatório obter o endereço IP de cada nó durante a inicialização.
kubectl get pods -l app=redis-cluster -o wideA saída do comando será semelhante a esta:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES redis-cluster-0 1/1 Running 0 9m37s 172.16.55.6 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-1 1/1 Running 0 9m5s 172.16.55.7 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-2 1/1 Running 0 8m30s 172.16.55.8 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-3 1/1 Running 0 7m46s 172.16.55.9 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-4 1/1 Running 0 7m7s 172.16.55.10 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-5 1/1 Running 0 6m30s 172.16.55.11 virtual-kubelet-cn-beijing-k <none> <none> -
Faça login em um dos nós Redis.
kubectl exec -ti redis-cluster-0 bashExecute o comando de inicialização para os seis nós. Defina a opção
--cluster-replicascomo 1 para atribuir um nó escravo a cada nó mestre. Dessa forma, o cluster ficará com três nós mestres e três nós escravos.redis-cli -a pass123 --cluster create 172.16.55.6:6379 172.16.55.7:6379 172.16.55.8:6379 172.16.55.9:6379 172.16.55.10:6379 172.16.55.11:6379 --cluster-replicas 1Se a saída abaixo for retornada, o cluster foi inicializado com sucesso.
[OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
-
-
Utilize o cluster Redis.
Após a criação de um Service headless, o cluster Kubernetes atribui um registro A do Domain Name System (DNS) ao Service no formato
{service name}.{service namespace}.svc.{domain}. Esse registro DNS mapeia para o endereço IP de um pod de backend. Sempre que você acessar o nome do Service, ele será resolvido para um nó Redis aleatório.Isso permite acessar o cluster Redis conectando-se a qualquer pod do cluster.
redis-cli -a pass123 -c -h redis-cluster-svc.default.svc.cluster.local -p 6379Exemplo de teste:
172.16.55.8> set k1 v1 OK 172.16.55.8> get k1 "v1"
Dimensionar um cluster Redis
O dimensionamento dinâmico de um cluster Redis não é viável pelos seguintes motivos: primeiro, sempre que um novo nó é adicionado, o Redis precisa realocar hash slots para todos os nós do cluster. Embora seja possível adicionar um script à imagem do Redis para automatizar essa realocação na inicialização do pod, o resharding contínuo torna o dimensionamento lento quando há grande volume de dados. Além disso, o sharding pode saturar a largura de banda do cluster, causando timeout em todos os clientes dependentes do Redis. Segundo, não existe uma política adequada para definir se um pod reiniciado deve atuar como mestre ou escravo.
Para contornar esses problemas, o exemplo a seguir demonstra como dimensionar um cluster Redis realizando o sharding manualmente.
-
Altere o número de réplicas no StatefulSet de 6 para 8.
kubectl scale statefulsets redis-cluster --replicas=8 -
Obtenha os endereços IP dos novos nós.
Quando todos os pods estiverem no estado Ready, execute o comando abaixo para obter os IPs dos novos nós:
kubectl get pods -l app=redis-cluster -o wideA saída do comando será semelhante a esta. Os nós redis-cluster-6 e redis-cluster-7 são os novos nós adicionados.
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES redis-cluster-0 1/1 Running 0 88m 172.16.55.6 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-1 1/1 Running 0 88m 172.16.55.7 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-2 1/1 Running 0 87m 172.16.55.8 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-3 1/1 Running 0 87m 172.16.55.9 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-4 1/1 Running 0 86m 172.16.55.10 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-5 1/1 Running 0 85m 172.16.55.11 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-6 1/1 Running 0 52s 172.16.55.16 virtual-kubelet-cn-beijing-k <none> <none> redis-cluster-7 1/1 Running 0 32s 172.16.55.17 virtual-kubelet-cn-beijing-k <none> <none> -
Adicione um nó mestre.
Faça login em um dos nós existentes. Neste exemplo, usaremos o redis-cluster-0. Execute o comando abaixo para adicionar o redis-cluster-6 como um novo nó mestre do cluster:
kubectl exec -ti redis-cluster-0 bashredis-cli -a pass123 --cluster add-node 172.16.55.16:6379 172.16.55.6:6379NotaNo comando acima,
172.16.55.6:6379representa o endereço de um nó existente. Após conectar-se a ele, o redis-cli obtém automaticamente os endereços dos demais nós.Consulte o ID do redis-cluster-6.
redis-cli -a pass123 -c cluster nodes | grep 172.16.55.16:6379 | awk '{print $1}'A saída do comando será semelhante a esta:
47879390ecc7635f5c57d3e324e2134b24****** -
Realoque os hash slots.
Com a adição do redis-cluster-6 como mestre, o cluster passa a ter quatro nós mestres compartilhando 16.384 hash slots. Em média, cada nó mestre deve receber
16.384/4 = 4.096hash slots. Portanto, é necessário mover 4.096 hash slots dos três mestres originais para o novo nó mestre.Execute o comando a seguir para realocar os hash slots. O endereço
172.16.55.6:6379refere-se a um nó existente; após a conexão, o redis-cli descobre automaticamente os outros nós.redis-cli -a pass123 --cluster reshard 172.16.55.6:6379Insira as informações solicitadas seguindo os prompts do comando interativo.
How many slots do you want to move (from 1 to 16384)? 4096 What is the receiving node ID? 47879390ecc7635f5c57d3e324e2134b24****** Source node #1: all Do you want to proceed with the proposed reshard plan (yes/no)? yesQuantidade de hash slots a serem alocados para o novo nó (redis-cluster-6): 4.096
ID do nó receptor (novo nó): 47879390ecc7635f5c57d3e324e2134b24
ID dos nós de source (todos os nós existentes): all
Confirmação da realocação: yes
Aguarde a conclusão da realocação dos hash slots. Durante esse processo, o cluster Redis continua atendendo requisições normalmente.
-
Adicione o nó escravo.
Execute o comando abaixo para configurar o redis-cluster-7 como escravo do redis-cluster-6:
redis-cli -a pass123 --cluster add-node 172.16.55.17:6379 172.16.55.6:6379 --cluster-slave --cluster-master-id 47879390ecc7635f5c57d3e324e2134b24******NotaNo comando acima,
172.16.55.6:6379é o endereço de um nó existente. Após a conexão, o redis-cli obtém automaticamente os endereços dos demais nós.O valor
47879390ecc7635f5c57d3e324e2134b24******corresponde ao ID do nó mestre (redis-cluster-6).
Após adicionar o nó escravo, o cluster Redis terá quatro nós mestres, cada um com seu respectivo escravo.
redis-cli -a pass123 -c cluster nodesExemplo de saída:
47879390ecc7635f5c57d3e324e2134b24****** 172.16.55.16:6379@16379 master - 0 1667383406000 7 connected 0-1364 5461-6826 10923-12287 75a7398a45f9696066eaa6ac7968b13a47****** 172.16.55.11:6379@16379 slave b8f6b826241b47f29a4bdde14104b28fe8****** 0 1667383406514 2 connected b7849f8577e43d5a6da51bc78ae809bbb1****** 172.16.55.17:6379@16379 slave 47879390ecc7635f5c57d3e324e2134b24****** 0 1667383406314 7 connected b8f6b826241b47f29a4bdde14104b28fe8****** 172.16.55.7:6379@16379 master - 0 1667383406815 2 connected 6827-10922 ffce547186e0be179830cb0dca47c203f6****** 172.16.55.6:6379@16379 myself,master - 0 1667383406000 1 connected 1365-5460 833a939cde93991c8a16c41fb2568b8642****** 172.16.55.8:6379@16379 master - 0 1667383406514 3 connected 12288-16383 a4df1a26394bfcb833914278744219db01****** 172.16.55.9:6379@16379 slave 833a939cde93991c8a16c41fb2568b8642****** 0 1667383407515 3 connected c4234d71343ca4dbe07822e17f7572ac30****** 172.16.55.10:6379@16379 slave ffce547186e0be179830cb0dca47c203f6****** 0 1667383405813 1 connected
Reduzir um cluster Redis
Ao reduzir um cluster Redis, os StatefulSets só conseguem excluir pods individualmente, seguindo a ordem inversa de criação. Para remover um nó mestre e um nó escravo do cluster, é necessário usar o StatefulSet para excluir o redis-cluster-7 e o redis-cluster-6. Antes dessa exclusão, o Redis deve transferir todos os hash slots desses dois nós para os demais. Caso contrário, haverá perda de dados e o cluster rejeitará novas requisições.
-
Realoque os hash slots.
Para evitar desbalanceamento de carga nos três nós mestres restantes, o StatefulSet deve distribuir uniformemente os hash slots do redis-cluster-6 entre eles. Isso exige três operações de resharding. O processo é similar ao de dimensionamento, mas em cada operação você deve defina um dos mestres restantes como nó receptor e o redis-cluster-6 como nó de source. Exemplo de comando:
redis-cli -a pass123 --cluster reshard 172.16.55.6:6379Insira as informações solicitadas seguindo os prompts do comando interativo.
How many slots do you want to move (from 1 to 16384)? 4096 What is the receiving node ID? ffce547186e0be179830cb0dca47c203f6****** Source node #1: 47879390ecc7635f5c57d3e324e2134b24****** Source node #2: done Do you want to proceed with the proposed reshard plan (yes/no)? yesQuantidade de hash slots a serem alocados para os mestres restantes: 4.096
ID do nó receptor (um dos nós restantes): ffce547186e0be179830cb0dca47c203f6
ID do nó de source (redis-cluster-6): 47879390ecc7635f5c57d3e324e2134b24
Confirmação da realocação: yes
-
Altere o número de réplicas no StatefulSet de 8 para 6.
kubectl scale statefulsets redis-cluster --replicas=6Visualize as informações dos pods do cluster Redis. O número de nós deve ter sido reduzido para seis.
kubectl get pods -l app=redis-cluster -o wide
Exclua um cluster Redis
Para excluir um cluster Redis, remova o StatefulSet, o Service e o ConfigMap.
kubectl delete statefulset redis-cluster
kubectl delete svc redis-cluster-svc
kubectl delete cm redis-cluster
A exclusão do StatefulSet não remove automaticamente as PVCs associadas. É necessário excluí-las manualmente. Ao remover a PVC, os discos e dados correspondentes também serão apagados.
kubectl delete pvc -l app=redis-cluster