Observação:
- Este tutorial requer acesso ao Oracle Cloud. Para se cadastrar em uma conta gratuita, consulte Conceitos básicos do Oracle Cloud Infrastructure Free Tier.
- Ele usa valores de exemplo para credenciais, tenancy e compartimentos do Oracle Cloud Infrastructure. Ao concluir seu laboratório, substitua esses valores por valores específicos do seu ambiente de nuvem.
Migrar Cluster do Kafka e do Zookeeper sem Tempo de Inatividade
Introdução
Muitos serviços (nativos da nuvem ou on-premises) usam clusters Kafka para suas necessidades de mensagens assíncronas, pois é uma tecnologia de mensagens que se dimensiona bem. Pode haver situações em que você precisa substituir um conjunto de nós ou todo o cluster devido às necessidades de negócios. Este tutorial fala sobre a migração do cluster do Kafka e do Zookeeper para um novo conjunto de nós sem tempo de inatividade.
A instrução do problema
Por que substituir um nó em um cluster por outro pode ser um desafio? A adição ou remoção de um nó de um conjunto de nós por trás de um balanceador de carga é onipresente: adicione um novo nó, drene o nó existente a ser removido, depois que todas as conexões em andamento forem encerradas, desligue-o, remova-o da configuração do balanceador de carga e assim por diante.
O verdadeiro desafio está no gerenciamento de estado com um aplicativo. Em geral, os aplicativos são sem monitoramento de estado e delegam persistência de estado a um sistema de gerenciamento de dados, por exemplo, um sistema de gerenciamento de banco de dados relacional (RDBMS). Ao contrário de tais aplicativos, tanto o Kafka quanto o Zookeeper gerenciam o estado localmente, ou seja, a persistência do estado é feita usando discos locais. Isso significa que não podemos simplesmente substituir um nó por outro sem cuidar do estado local do nó existente.
Além disso, no caso do Kafka, simplesmente adicionar um nó, não inicia automaticamente qualquer rebalanceamento da carga de trabalho, ou seja, redistribuição de partições de tópicos entre corretores. O novo nó só participa do compartilhamento de carga de trabalho para novos tópicos criados deste ponto em diante.
Um problema operacional com sistemas baseados em quorum (Zookeeper neste caso) é que eles precisam saber o tamanho do cluster antecipadamente, o que significa que cada nó precisa ter conhecimento de todos os outros nós do cluster. E, para complicar ainda mais as coisas, se você estiver adicionando mais de um nó (o número exato depende do tamanho do cluster existente) de uma só vez, você deve garantir que um dos nós recém-adicionados não se torne o líder; caso contrário, perderemos os dados.
Objetivos
- Migre o cluster Kafka e Zookeeper em tempo de inatividade zero para outro conjunto de nós.
Pré-requisitos
- Compreensão da arquitetura Kafka e Zookeeper.
Migrar Cluster do Kafka
A substituição de nós no cluster Kafka é relativamente fácil. Adicione novos brokers e chame a migração de partições de tópicos e, quando a migração estiver concluída, poderemos desativar o broker antigo. O Kafka fornece a API admin para executar a migração de partição. O alterPartitionReassignments
funciona adicionando réplicas de partição adicionais a um tópico, espera que elas se tornem membros do ISR e, em seguida, troca o líder da partição.
Você precisa desativar novas atribuições de partição de tópico para brokers antigos (se a lógica do aplicativo criar tópicos no runtime), caso contrário, isso se tornaria um loop infinito de migração. Para conseguir isso, pode-se usar uma variante da API de criação de tópico, onde podemos especificar a atribuição de partição nós mesmos. O algoritmo de amostra que pode ser seguido está listado abaixo.
-
Dado um tópico a ser criado e um conjunto de IDs de corretor que não devem ser atribuídos a nenhuma partição ou réplica: as partições de tópico e suas réplicas são atribuídas aos corretores restantes de uma forma round-robin. Assumimos que os IDs de corretores são criados de forma sequencial em ADs e, em seguida, em FDs. Por exemplo, supondo que haja 3 ADs (AD-1,AD-2,AD-3) e cada AD tenha 2 FDs (FD-1,FD-2) e haja 6 corretores com IDs (1-6), eles serão colocados na ordem a seguir.
broker ID 1 -> AD-1, FD-1 broker ID 2 -> AD-2, FD-1 broker ID 3 -> AD-3, FD-1 broker ID 4 -> AD-1, FD-2 broker ID 5 -> AD-2, FD-2 broker ID 6 -> AD-3, FD-2
-
Isso ajuda a colocar uma partição e suas réplicas em diferentes domínios de falha. O algoritmo é o seguinte: classificamos os IDs do corretor e começamos com um ID selecionado aleatoriamente para colocação de forma sequencial. Por exemplo, no caso de tópico com 3 partições e fator de replicação 3, e o ID do broker selecionado aleatoriamente é 3, a seguir será a ordem de posicionamento para partições ou réplicas.
partition-0, replica-0 -> 3 partition-0, replica-1 -> 4 partition-0, replica-2 -> 5 partition-1, replica-0 -> 4 partition-1, replica-1 -> 5 partition-1, replica-2 -> 6 partition-2, replica-0 -> 5 partition-2, replica-1 -> 6 partition-2, replica-2 -> 1
Etapas de alto nível para migração que podem ser seguidas com escrituração contábil (para reiniciar no caso de o processo de migração ser interrompido ou falhar no meio).
-
O mapeamento de ID de Assert antigo para novo corretor foi fornecido e concluído.
-
Use
AdminClient
para verificar se novos corretores estão disponíveis. Se nem todos estiverem disponíveis, crie um erro e encerre. -
Use
AdminClient
para verificar se o tópico<kafka_topic_migration>
existe no cluster.- Se o tópico
<kafka_topic_migration>
não existir, crie-o designando réplicas manualmente em novos brokers. Este tópico é usado para escrituração contábil de tópicos que já foram reatribuídos significa migrados.
- Se o tópico
-
Leia o tópico
<kafka_topic_migration>
desde o início usando um consumidor. Cada mensagem é um nome de tópico que foi reatribuído a novos corretores. -
Use
AdminClient
para listar todos os tópicos disponíveis no cluster. Nessa lista, remova o tópico<kafka_topic_migration>
. -
Nas duas etapas acima, localize os tópicos a serem reatribuídos a novos corretores.
-
Para cada tópico:
-
Crie um mapa
Map<TopicPartition,Optional<NewPartitionReassignment>> reassignment = new HashMap<>();
. -
Usando
AdminClient
, descreva o tópico para localizar suas partições. -
Para cada partição:
-
Prepare um objeto
NewPartitionReassignment
substituindo cada ID de réplica antigo (ID de broker antigo) pelo novo ID de broker correspondente. Se o mapeamento de ID do corretor não contiver a chave correspondente ao ID da réplica, registre um aviso e use o ID atual (o motivo mais provável é que esse tópico já tenha sido migrado e tenhamos perdido a escrituração contábil). -
Adicione esta entrada ao mapa.
-
-
Use
AdminClient
para iniciar a reatribuição chamando o métodoalterPartitionReassignments
. -
Execute um loop para verificar se essa reatribuição está concluída listando as reatribuições em andamento (
listPartitionReassignments
) e verificando se seu tamanho é zero. Dormir de N segundos entre cada loop. -
Valide se as novas réplicas de cada partição correspondem às réplicas desejadas.
-
Envie este nome de tópico como mensagem para o tópico
<kafka_topic_migration>
.
-
-
Repita a etapa 4 a 6, se não houver mais tópicos para reatribuição e encerramento.
Uma vez concluída a migração, podemos desativar os corretores antigos e desativar a lógica personalizada da criação do tópico.
Observação: Antes de desativar os brokers antigos, certifique-se de que todos os clientes deste cluster atualizaram a configuração
bootstrap.servers
com novos broker(s).
Migrar Cluster do Zookeeper
Sendo um sistema baseado em quórum (para comprometer qualquer operação, precisamos de pelo menos Quórum de votos) e dada reeleição de líder faz com que as operações de gravação sejam interrompidas, a migração do Zookeeper é a parte mais difícil. Existem algumas abordagens para substituir nós. Uma abordagem simples é executar várias rodadas de reinicialização incremental de todo o cluster e adicionar um novo nó em cada rodada. Essa abordagem pode não ser aceitável devido a várias rodadas de reinicialização do nó do líder e atraso na execução da migração geral.
Observação: Não podemos adicionar todos os novos nós (como participantes) de uma só vez devido ao risco de um novo nó se tornar um líder sem sincronizar todos os dados (causando perda de dados).
Nunca especifique mais de um servidor de junção na mesma configuração inicial que os participantes. Atualmente, os servidores de junção não sabem que estão se juntando a um conjunto existente, se vários participantes forem listados como participantes, eles podem formar um quorum independente, criando uma situação de cérebro dividido, como operações de processamento independentemente do seu conjunto principal. Não há problema em listar vários joiners como observadores em uma configuração inicial.
Na versão do Zookeeper acima de 3.5.0
, temos suporte para reconfiguração dinâmica do conjunto do Zookeeper. O flag reconfigEnabled
deve ser definido como true
para que a reconfiguração dinâmica funcione. Para obter mais informações, consulte Reconfiguração dinâmica do ZooKeeper Ensemble.
Você pode adicionar novos nós ao conjunto com a atribuição Observer
com a configuração inicial de joiners compostos de servidores na última configuração confirmada. Por exemplo, se os servidores 4 e 5 forem adicionados ao mesmo tempo a (1, 2, 3), a configuração inicial de 4 será (1, 2, 3, 4, 5), onde 4 e 5 são listados como observadores. Da mesma forma, a configuração de 5 será (1, 2, 3, 4, 5), onde 4 e 5 são listados como observadores.
Observação: Listar os participantes como observadores não os tornará realmente observadores; isso apenas os impedirá de formar acidentalmente um quorum com outros participantes. Em vez disso, eles entrarão em contato com os servidores na configuração atual e adotarão a última configuração confirmada (1, 2, 3), onde os participantes estão ausentes. Depois de se conectar ao líder atual, os participantes se tornam seguidores sem direito a voto até que o sistema seja reconfigurado e sejam adicionados ao conjunto (como participante ou observador, conforme desejado).
Quando todos os nós estiverem ativos e em execução, a API reconfig será chamada para adicionar novos nós dinamicamente como participantes e remover nós antigos do conjunto. Por exemplo, usando a CLI.
reconfig -remove 1,2,3 -add
server.5=hostA:2111:2112;2113,6=hostB:2111:2112:participant;2113,7=
hostC:2111:2112:participant;2113*
Após essa etapa, os nós antigos podem ser desativados.
Observação:
Antes de desativar os nós antigos, verifique se todos os clientes deste cluster do Zookeeper atualizaram a string de conexão com novos nós.
O Zookeeper deve ser migrado primeiro (supondo que a versão do Kafka sendo usada dependa do Zookeeper). Ao adicionar novos nós do Zookeeper na nova configuração de corretores Kafka, estaremos preparados para a remoção de nós antigos do Zookeeper antecipadamente.
O novo nó
myID
do Zookeeper deve aumentar monotonicamente; caso contrário, o nó não será iniciado.Não reinicie o nó do Zookeeper recém-adicionado até que
reconfig
seja chamado; caso contrário, ele não será iniciado devido à falta de configuração para ele mesmo no arquivo de configuração dinâmico. A configuração inicial do nó é substituída pela configuração dinâmica que tem a última configuração confirmada.Ao selecionar um componente de código aberto para ser integrado ao seu ecossistema, é preciso considerar a capacidade de gerenciamento e os aspectos operacionais dele.
Ao migrar partições de tópico, é necessário estar ciente da quantidade de dados que seriam transferidos pela rede.
Links Relacionados
Confirmação
- Autor - Shailesh Mishra
Mais Recursos de Aprendizagem
Explore outros laboratórios em docs.oracle.com/learn ou acesse mais conteúdo de aprendizado gratuito no canal Oracle Learning YouTube. Além disso, visite education.oracle.com/learning-explorer para se tornar um Oracle Learning Explorer.
Para obter a documentação do produto, visite o Oracle Help Center.
Migrate Kafka and Zookeeper Cluster in Zero Downtime
F96323-01
April 2024