
Este artigo dá continuidade ao nosso sobre a migração do RabbitMQ e é dedicado ao MongoDB. À medida que gerenciamos vários clusters de Kubernetes e MongoDB, surgiu a necessidade natural de migrar dados de uma instalação para outra e fazer isso sem downtime. Os principais cenários permanecem: mover o MongoDB de um servidor virtual/real para o Kubernetes ou mover o MongoDB dentro de um único cluster Kubernetes (de um namespace para outro).
Nossa receita é destinada a situações em que um antigo cluster MongoDB está em funcionamento (por exemplo, de 3 nós e já se encontra em K8s ou em servidores antigos), com o qual um aplicativo hospedado em Kubernetes está interagindo:

Como vamos migrar esse cluster para um novo ambiente de produção em Kubernetes?
Teoria
O algoritmo geral de migração é semelhante ao descrito na situação com o RabbitMQ.
É importante notar que, para que a migração seja possível, os servidores com MongoDB e Kubernetes devem estar na mesma rede. Os nós do cluster MongoDB se comunicarão entre si pelo IP dos antigos servidores (onde estão as antigas instalações do MongoDB) e pelos nomes DNS dos pods com MongoDB em K8s. Portanto, nos servidores físicos (com as antigas instalações), será necessário rotear até os pods e, em seguida, configurá-los para usar o servidor DNS que opera no Kubernetes (ou escrever os nomes necessários em /etc/hosts, embora, de modo geral, seja melhor evitar essa possibilidade).
O próximo passo é levantar o cluster MongoDB em pods Kubernetes. No nosso caso, o cluster de banco de dados é composto por 3 nós e cada nó está localizado em um pod K8s — no entanto, seu número pode ser diferente. No ConfigMap, deve-se especificar o endereço do master MongoDB da instalação antiga: assim, os nós MongoDB que estão nos pods em K8s começarão imediatamente a sincronização com ele.
Depois que todos os pods forem iniciados, formará um cluster MongoDB com 6 nós:

Observe que os pods levarão tempo para serem iniciados, pois cada pod é iniciado sequencialmente, e no momento da inicialização, sincroniza os dados com o master.
Depois disso, é possível alternar o aplicativo para usar os novos servidores MongoDB:

E só resta remover os antigos nós do cluster MongoDB, após o que a migração pode ser considerada concluída:

Esse esquema é frequentemente aplicado em produção e, para facilitar seu uso, foi implementado no módulo (essa ferramenta nós ), que permite distribuir configurações padrão do MongoDB por vários clusters. Pretendemos publicar nossos módulos em breve, enquanto isso apresentamos instruções separadas com as quais você pode experimentar a solução proposta em ação, sem usar o addon-operator.
Vamos tentar na prática.
Requisitos
Detalhes:
- Cluster Kubernetes (minikube também serve);
- Cluster MongoDB (pode ser implantado em bare metal ou criado como um cluster comum no Kubernetes a partir do Helm chart oficial).
No exemplo descrito abaixo, o antigo cluster com MongoDB será chamado mongo-old e será instalado no mesmo cluster Kubernetes onde posteriormente instalaremos o novo (mongo-new).
Preparando o antigo cluster
1. Para exemplificar o esquema descrito em ação, criaremos um "antigo" (ou seja, sujeito à migração) cluster MongoDB diretamente no Kubernetes (na realidade, ele pode estar em servidores distintos fora do K8s). Para isso, baixaremos o Helm chart:
helm fetch --untar stable/mongodb-replicaset… e faremos algumas edições, configurando a autenticação:
auth:
enabled: true
adminUser: mongo
adminPassword: pa33w0rd
# metricsUser: metrics
# metricsPassword: password
# key: keycontent
# existingKeySecret:
# existingAdminSecret:
# exisitingMetricsSecret: Também em values.yaml podemos configurar certificados e muito mais.
2. Instalaremos o chart:
helm install . --name mongo-old --namespace mongo-oldApós isso, uma instalação de teste "antiga" do MongoDB será iniciada:
kubectl --namespace=mongo-old get pods 
Acessaremos o pod com seu mestre e criaremos um banco de dados de teste:
kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo
use admin
db.auth('mongo','password')
use music
db.artists.insert({ artistname: "The Tea Party" })
show dbs 
Acessando diferentes pods, descobri que o mestre é mongo-old-mongodb-replicaset-0. No entanto, para resolver essa questão de maneira mais conveniente, após a instalação do Helm chart, é exibido um comando para determinar MASTER_POD. No meu caso (para mongo-old de 3 nós) ele aparece assim:
for ((i = 0; i < 3; ++i)); do kubectl exec --namespace mongo-old mongo-old-mongodb-replicaset-$i -- sh -c 'mongo --eval="printjson(rs.isMaster())"'; doneCom isso, a preparação da instalação antiga do MongoDB, cujos dados serão transferidos, está pronta.
Migração do cluster MongoDB
Agora vamos implantar uma nova instalação do MongoDB, que estará no Kubernetes e será utilizada pelo aplicativo em produção.
NB: Vale ressaltar que deve ser usada a mesma versão do MongoDB que era utilizada anteriormente. Caso contrário, há o risco de problemas de compatibilidade.
Seguindo a mesma lógica da seção anterior (onde simulamos a "antiga" instalação do MongoDB), usaremos o Helm chart mencionado (com o comando helm fetch) e configuraremos a autorização, bem como outros parâmetros, se forem utilizados. Além disso, corrigiremos o arquivo init/on-start.sh, temporariamente adicionando na linha 165 o endereço do mestre, obtido na etapa anterior (ou conhecido por você da instalação do MongoDB em servidores separados):
peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'Estamos prontos para criar uma nova instalação do MongoDB:
helm install . --name mongo-new --namespace mongo-newAguardamos até que todos os pods sejam iniciados (se houver muitos dados, seu início pode levar horas):

Agora fazemos exec no novo pod e verificamos a lista de bancos:
kubectl --namespace=mongo-new exec -ti mongo-new-mongodb-replicaset-0 mongo 
Dois clusters MongoDB foram unidos em um, composto por 6 nós.
Neste momento, já é possível mudar o aplicativo para o novo cluster, mas ainda restam algumas etapas para finalizar a migração.
Do arquivo init/on-start.sh na nova instalação removemos a linha que adicionamos:
peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'Agora vamos ao antigo mestre do cluster e "derrubá-lo" — assim, um novo mestre será designado no cluster. Acessamos o pod com o mestre do MongoDB:
kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo
use admin
db.auth('mongo','password')Depois disso, mudamos as prioridades dos nós e trocamos o mestre:
cfg = rs.conf()
cfg.members[5].priority = 2
rs.reconfig(cfg)
rs.stepDown(120)O nó atual deixou de ser o mestre — ocorrerão eleições para um novo. Como mudamos as prioridades, o nó que queremos se tornará o mestre.
NB: Por padrão, todos os nós MongoDB têm prioridade igual a 1. Acima, aumentamos para 2 a prioridade do nó que precisamos. Assim, o mestre comum se tornará um membro do novo cluster. Para mais detalhes sobre como esses mecanismos funcionam no MongoDB, consulte .
Desconectaremos a antiga instalação do MongoDB e em seguida acessaremos o mestre novo e removeremos os nós antigos:
rs.remove("mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017")
rs.remove("mongo-old-mongodb-replicaset-1.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017")
rs.remove("mongo-old-mongodb-replicaset-2.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017")Depois disso, a migração pode ser considerada concluída: migramos com sucesso do antigo cluster MongoDB para o novo!
Resultados
O esquema descrito é adequado para praticamente todos os casos em que é necessário transferir o MongoDB ou simplesmente mudar para um novo cluster.
Certamente, o principal detalhe ao transferir é a necessidade de encaminhar os endereços IP dos novos pods para os servidores da antiga instalação do MongoDB, caso esteja fora do K8s, e a correta nomeação deles no DNS (ou /etc/hosts). No exemplo, esses passos não foram necessários, uma vez que a migração ocorreu entre diferentes namespaces de um mesmo cluster Kubernetes.
P.S.
Confira também em nosso blog:
- «»;
- «»;
- «».
Fonte: habr.com
