Migração de RabbitMQ sem falhas para Kubernetes



O RabbitMQ é um intermediário de mensagens escrito em Erlang que permite organizar um cluster de failover com replicação completa de dados para vários nós, onde cada nó pode atender a solicitações de leitura e gravação. Com muitos clusters Kubernetes em produção, suportamos um grande número de instalações RabbitMQ e somos confrontados com a necessidade de migrar dados de um cluster para outro sem tempo de inatividade.

Essa operação foi necessária para nós em pelo menos dois casos:

  1. Transferindo dados de um cluster RabbitMQ, que não está no Kubernetes, para um novo cluster que já está "desligado" (ou seja, funcionando nos pods K8s).
  2. Migração do RabbitMQ no Kubernetes de um espaço para nome (por exemplo, se os caminhos forem delimitados por espaços para nome, transfira a infraestrutura de um caminho para outro).

A receita proposta neste artigo é focada em situações (mas não limitadas a elas), nas quais existe um cluster RabbitMQ antigo (por exemplo, de 3 nós), localizado nos K8s ou em alguns servidores antigos. Um aplicativo hospedado no Kubernetes trabalha com ele (já existe ou no futuro):



... e enfrentamos o desafio de migrá-lo para uma nova produção em Kubernetes.

Primeiro, será descrita uma abordagem geral da própria migração e, depois disso, detalhes técnicos de sua implementação.

Algoritmo de migração


A primeira etapa preliminar antes de qualquer ação é verificar se o modo de alta disponibilidade ( HA ) está ativado na instalação antiga do RabbitMQ. O motivo é óbvio - não queremos perder nenhum dado. Para executar essa verificação, você pode ir ao painel de administração do RabbitMQ e, na guia Admin → Políticas, verifique se o valor ha-mode: all :



O próximo passo é criar um novo cluster RabbitMQ nos pods do Kubernetes (no nosso caso, por exemplo, consistindo em 3 nós, mas seu número pode ser diferente).

Depois disso, mesclamos os clusters RabbitMQ antigos e novos, obtendo um único cluster (de 6 nós):



O processo de sincronização de dados entre os clusters RabbitMQ antigos e novos é iniciado. Depois que todos os dados são sincronizados entre todos os nós no cluster, podemos alternar o aplicativo para usar o novo cluster:



Após essas operações, é suficiente remover os nós antigos do cluster RabbitMQ e a movimentação pode ser considerada concluída:



Usamos repetidamente esse esquema em nossa produção. No entanto, para sua própria conveniência, o implementamos no âmbito de um sistema especializado que distribui configurações típicas de RMQ em conjuntos de clusters Kubernetes (para quem está curioso: estamos falando de addon-operator , sobre o qual falamos recentemente ) . A seguir, são apresentadas instruções individuais que qualquer pessoa pode aplicar em suas instalações para experimentar a solução proposta em ação.

Tentamos na prática


Exigências


Os detalhes são muito simples:

  1. Cluster Kubernetes (o minikube também é adequado);
  2. Cluster RabbitMQ (pode ser implantado no bare metal e criado como um cluster regular no Kubernetes a partir do gráfico oficial do Helm).

Para o exemplo descrito abaixo, implantei o RMQ no Kubernetes e o nomeei rmq-old .

Preparação do estande


1. Faça o download do gráfico Helm e edite-o um pouco:

 helm fetch --untar stable/rabbitmq-ha 

Por conveniência, definimos uma senha, ErlangCookie e definimos a política ha-all para que, por padrão, as filas sejam sincronizadas entre todos os nós do cluster RMQ:

 rabbitmqPassword: guest rabbitmqErlangCookie: mae9joopaol7aiVu3eechei2waiGa2we definitions: policies: |- { "name": "ha-all", "pattern": ".*", "vhost": "/", "definition": { "ha-mode": "all", "ha-sync-mode": "automatic", "ha-sync-batch-size": 81920 } } 

2. Defina o gráfico:

 helm install . --name rmq-old --namespace rmq-old 

3. Vá para o painel de administração do RabbitMQ, crie uma nova fila e adicione algumas mensagens. Eles serão necessários para que, após a migração, possamos garantir que todos os dados foram salvos e que não perdemos nada:



A bancada de testes está pronta: temos o RabbitMQ "antigo" com os dados que precisam ser transferidos.

Migração de Cluster RabbitMQ


1. Primeiro, implante o novo RabbitMQ em um espaço para nome diferente com o mesmo ErlangCookie e senha para o usuário. Para fazer isso, executamos as operações descritas acima, alterando o comando de instalação RMQ final para o seguinte:

 helm install . --name rmq-new --namespace rmq-new 

2. Agora você precisa mesclar o novo cluster com o antigo. Para fazer isso, vá para cada um dos pods do novo RabbitMQ e execute os comandos:

 export OLD_RMQ=rabbit@rmq-old-rabbitmq-ha-0.rmq-old-rabbitmq-ha-discovery.rmq-old.svc.cluster.local && \ rabbitmqctl stop_app && \ rabbitmqctl join_cluster $OLD_RMQ && \ rabbitmqctl start_app 

A variável OLD_RMQ endereço de um dos nós do cluster RMQ antigo .

Esses comandos irão parar o nó atual do novo cluster RMQ, conectá-lo ao cluster antigo e reiniciá-lo.

3. O cluster RMQ de 6 nós está pronto:



Você deve esperar até que as mensagens sejam sincronizadas entre todos os nós. É fácil adivinhar que o tempo de sincronização das mensagens depende da potência do ferro no qual o cluster está implantado e do número de mensagens. No cenário descrito, existem apenas 10 deles, portanto os dados foram sincronizados instantaneamente, mas com um número suficientemente grande de mensagens, a sincronização pode levar horas.

Portanto, o status da sincronização:



Aqui, +5 significa que as mensagens estão em outros 5 nós (exceto o que é especificado no campo Node ). Assim, a sincronização foi bem sucedida.

4. Resta apenas mudar o endereço RMQ no aplicativo para o novo cluster (as ações específicas aqui dependem da pilha de tecnologia que você está usando e de outros detalhes do aplicativo), após o qual você pode se despedir do antigo.

Para a última operação (ou seja, depois de alternar o aplicativo para um novo cluster), vamos a cada nó do cluster antigo e executamos os comandos:

 rabbitmqctl stop_app rabbitmqctl reset 

O cluster "esqueceu" os nós antigos: é possível excluir o RMQ antigo, que concluirá a movimentação.

Nota : Se você usar o RMQ com certificados, basicamente nada mudará - o processo de mudança será realizado exatamente da mesma maneira.

Conclusões


O esquema descrito é adequado para quase todos os casos em que precisamos transferir o RabbitMQ ou simplesmente mudar para um novo cluster.

No nosso caso, as dificuldades ocorreram apenas uma vez, quando o RMQ foi acessado de muitos lugares, e não tivemos a oportunidade de alterar o endereço do RMQ para um novo. Em seguida, lançamos um novo RMQ no mesmo namespace com os mesmos rótulos, para que ele se enquadrasse nos serviços e no ingresso existentes e, quando iniciamos o pod, manipulamos os rótulos com as mãos, excluindo-os no início, para que as solicitações não caíssem em um RMQ vazio, e adicionando-os novamente após a sincronização da mensagem.

Usamos a mesma estratégia ao atualizar o RabbitMQ para uma nova versão com uma configuração modificada - tudo funcionava como um relógio.

PS


Como continuação lógica deste material, estamos preparando artigos sobre o MongoDB (migração de um servidor iron para o Kubernetes) e o MySQL (uma das opções para "preparar" este DBMS no Kubernetes). Eles serão publicados nos próximos meses.

PPS


Leia também em nosso blog:

Source: https://habr.com/ru/post/pt450662/


All Articles