Migração perfeita de RabbitMQ para Kubernetes

Migração perfeita de RabbitMQ para Kubernetes

RabbitMQ é um corretor de mensagens escrito em Erlang que permite organizar um cluster de failover com replicação completa de dados em vários nós, onde cada nó pode atender solicitações de leitura e gravação. Tendo muitos clusters Kubernetes em operação de produção, oferecemos suporte a um grande número de instalações do RabbitMQ e nos deparamos com a necessidade de migrar dados de um cluster para outro sem tempo de inatividade.

Precisávamos desta operação em pelo menos dois casos:

  1. Transferir dados de um cluster RabbitMQ que não está localizado no Kubernetes para um novo cluster – já “kubernetizado” (ou seja, operando em pods K8s).
  2. Migração do RabbitMQ dentro do Kubernetes de um namespace para outro (por exemplo, se os circuitos são delimitados por namespaces, então para transferir infraestrutura de um circuito para outro).

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

Migração perfeita de RabbitMQ para Kubernetes

... e nos deparamos com a tarefa de migrá-lo para a nova produção no Kubernetes.

Primeiro, será descrita a abordagem geral da migração em si e, em seguida, serão descritos os detalhes técnicos de sua implementação.

Algoritmo de migração

O primeiro estágio preliminar antes de qualquer ação é verificar se o modo de alta disponibilidade está habilitado na instalação antiga do RabbitMQ (HA). A razão é óbvia: não queremos perder nenhum dado. Para realizar esta verificação, você pode ir ao painel de administração do RabbitMQ e na aba Admin → Políticas certificar-se de que o valor está definido ha-mode: all:

Migração perfeita de RabbitMQ para Kubernetes

A próxima etapa é criar um novo cluster RabbitMQ em pods Kubernetes (no nosso caso, por exemplo, consistindo em 3 nós, mas seu número pode ser diferente).

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

Migração perfeita de RabbitMQ para Kubernetes

O processo de sincronização de dados entre os clusters RabbitMQ antigo e novo é iniciado. Depois que todos os dados estiverem sincronizados entre todos os nós do cluster, podemos mudar o aplicativo para usar o novo cluster:

Migração perfeita de RabbitMQ para Kubernetes

Após essas operações, basta remover os nós antigos do cluster RabbitMQ, e a movimentação pode ser considerada completa:

Migração perfeita de RabbitMQ para Kubernetes

Usamos esse esquema muitas vezes na produção. No entanto, para nossa conveniência, nós o implementamos em um sistema especializado que distribui configurações RMQ padrão em vários clusters Kubernetes (para quem está curioso: estamos falando de operador de complementosobre o qual nós recentemente disse). A seguir apresentaremos instruções individuais que qualquer pessoa pode aplicar em suas instalações para testar a solução proposta em ação.

Vamos tentar na prática

Requisitos

Os detalhes são muito simples:

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

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

Preparação do estande

1. Baixe o gráfico do Helm e edite-o um pouco:

helm fetch --untar stable/rabbitmq-ha

Por conveniência, definimos uma senha, ErlangCookie e fazer política ha-allpara 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. Instale 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 várias mensagens. Eles serão necessários para que após a migração possamos ter certeza de que todos os dados foram preservados e que não perdemos nada:

Migração perfeita de RabbitMQ para Kubernetes

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

Migrando um cluster RabbitMQ

1. Primeiro, vamos implantar o novo RabbitMQ em другом espaço para nome com o mesmo ErlangCookie e senha do usuário. Para isso, realizaremos as operações descritas acima, alterando o comando final de instalação do RMQ 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 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

Em uma variável OLD_RMQ o endereço de um dos nós é encontrado velho Cluster RMQ.

Esses comandos irão parar o nó atual novo Cluster RMQ, anexe-o ao cluster antigo e inicie-o novamente.

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

Migração perfeita de RabbitMQ para Kubernetes

Você deve aguardar enquanto as mensagens são sincronizadas entre todos os nós. Não é difícil adivinhar que o tempo de sincronização das mensagens depende da capacidade do hardware 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 durar horas.

Então, o status de sincronização:

Migração perfeita de RabbitMQ para Kubernetes

é +5 significa que as mensagens já estão em mais em 5 nós (exceto o indicado no campo Node). Assim, a sincronização foi bem-sucedida.

4. Tudo o que resta é 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 outras especificidades do aplicativo), após o qual você pode dizer adeus ao antigo.

Para a última operação (ou seja, já depois mudando o aplicativo para um novo cluster) vá para cada nó velho cluster e execute os comandos:

rabbitmqctl stop_app
rabbitmqctl reset

O cluster “esqueceu” os nós antigos: você pode excluir o RMQ antigo, momento em que a movimentação será concluída.

Nota: Se você usar RMQ com certificados, nada mudará fundamentalmente - o processo de movimentação será realizado exatamente da mesma forma.

Descobertas

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

No nosso caso, as dificuldades surgiram apenas uma vez, quando o RMQ foi acessado de vários locais, e não tivemos a oportunidade de alterar o endereço do RMQ para um novo em todos os lugares. Em seguida, lançamos um novo RMQ no mesmo namespace com os mesmos rótulos para que se enquadrasse nos serviços e ingressos existentes, e ao lançar o pod manipulamos os rótulos manualmente, removendo-os no início para que as solicitações não caíssem no RMQ vazio e adicioná-los novamente após a sincronização das mensagens.

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

PS

Como continuação lógica deste material, estamos preparando artigos sobre MongoDB (migração de um servidor de hardware para Kubernetes) e MySQL (como preparamos este SGBD dentro do Kubernetes). Eles serão publicados nos próximos meses.

PPS

Leia também em nosso blog:

Fonte: habr.com

Adicionar um comentário