Do ponto de vista geral, parece que quando se trata de migrar as cargas de trabalho do PostgreSQL para a nuvem, a escolha do provedor de nuvem não deve fazer diferença. Pronto para uso, o PostgreSQL facilita a replicação de dados, sem tempo de inatividade, via Replicação Lógica, embora com algumas restrições. A fim de tornar seus serviços de oferta de serviços mais atraentes, os provedores de nuvem podem resolver algumas dessas restrições. À medida que começamos a pensar nas diferenças nas versões disponíveis do PostgreSQL, compatibilidade, limites, limitações e desempenho, fica claro que os serviços de migração são fatores-chave na oferta geral de serviços. Não é mais o caso de “nós oferecemos, nós migramos”. Tornou-se mais como “nós oferecemos, nós migramos, com o mínimo de limitações”.
A migração é importante tanto para pequenas quanto para grandes organizações. Não se trata tanto do tamanho do cluster PostgreSQL, mas sim do tempo de inatividade aceitável e do esforço pós-migração.
Selecionando uma estratégia
A estratégia de migração deve levar em consideração o tamanho do banco de dados, o link de rede entre a origem e o destino, bem como as ferramentas de migração oferecidas pelo provedor de nuvem.
Hardware ou Software?
Assim como o envio de chaves USB e DVDs nos primórdios da Internet, nos casos em que a largura de banda da rede não é suficiente para transferir dados na velocidade desejada, os provedores de nuvem estão oferecendo soluções de hardware, capazes de para transportar até centenas de petabytes de dados. Abaixo estão as soluções atuais de cada um dos três grandes:
Uma tabela útil fornecida pelo Google mostrando as opções disponíveis:
O appliance do GCP é o Transfer Appliance
Uma recomendação semelhante do Azure com base no tamanho dos dados versus largura de banda da rede:
O appliance do Azure é a caixa de dados
No final de sua página de migração de dados, a AWS fornece um vislumbre do que podemos esperar, juntamente com sua recomendação da solução:
Nos casos em que os tamanhos do banco de dados excedem 100 GB e largura de banda de rede limitada, a AWS sugere um solução de hardware.
O dispositivo AWS é o Snowball Edge
Exportação/importação de dados
As organizações que toleram o tempo de inatividade podem se beneficiar da simplicidade das ferramentas comuns fornecidas pelo PostgreSQL prontas para uso. No entanto, ao migrar dados de um provedor de nuvem (ou hospedagem) para outro provedor de nuvem, tenha cuidado com o custo de saída.
AWS
Para testar as migrações, usei uma instalação local do meu banco de dados Nextcloud em execução em um dos meus servidores de rede doméstica:
postgres=# select pg_size_pretty(pg_database_size('nextcloud_prod'));
pg_size_pretty
----------------
58 MB
(1 row)
nextcloud_prod=# \dt
List of relations
Schema | Name | Type | Owner
--------+-------------------------------+-------+-----------
public | awsdms_ddl_audit | table | s9sdemo
public | oc_accounts | table | nextcloud
public | oc_activity | table | nextcloud
public | oc_activity_mq | table | nextcloud
public | oc_addressbookchanges | table | nextcloud
public | oc_addressbooks | table | nextcloud
public | oc_appconfig | table | nextcloud
public | oc_authtoken | table | nextcloud
public | oc_bruteforce_attempts | table | nextcloud
public | oc_calendar_invitations | table | nextcloud
public | oc_calendar_reminders | table | nextcloud
public | oc_calendar_resources | table | nextcloud
public | oc_calendar_resources_md | table | nextcloud
public | oc_calendar_rooms | table | nextcloud
public | oc_calendar_rooms_md | table | nextcloud
...
public | oc_termsofservice_terms | table | nextcloud
public | oc_text_documents | table | nextcloud
public | oc_text_sessions | table | nextcloud
public | oc_text_steps | table | nextcloud
public | oc_trusted_servers | table | nextcloud
public | oc_twofactor_backupcodes | table | nextcloud
public | oc_twofactor_providers | table | nextcloud
public | oc_users | table | nextcloud
public | oc_vcategory | table | nextcloud
public | oc_vcategory_to_object | table | nextcloud
public | oc_whats_new | table | nextcloud
(84 rows)
The database is running PostgreSQL version 11.5:
postgres=# select version();
version
------------------------------------------------------------------------------------------------------------
PostgreSQL 11.5 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 9.1.1 20190503 (Red Hat 9.1.1-1), 64-bit
(1 row)
Também criei um usuário do PostgreSQL para ser usado pelo AWS DMS, que é o serviço da Amazon para importar PostgreSQL para o Amazon RDS:
postgres=# \du s9sdemo
List of roles
Role name | Attributes | Member of
-----------+------------+-------------
s9sdemo | | {nextcloud}
O AWS DMS oferece muitas vantagens, exatamente como esperamos de uma solução gerenciada na nuvem:
- escalonamento automático (somente armazenamento, pois a instância de computação deve ter o tamanho certo)
- provisionamento automático
- modelo de pagamento conforme o uso
- failover automático
No entanto, manter a consistência dos dados para um banco de dados ativo é o melhor esforço. Uma consistência de 100% é alcançada somente quando o banco de dados está no modo somente leitura — isso é uma consequência de como as alterações na tabela são capturadas.
Em outras palavras, as tabelas têm um cutover point-in-time diferente:
Assim como tudo na nuvem, há um custo associado ao serviço de migração.
Para criar o ambiente de migração, siga o guia de conceitos básicos para configurar uma instância de replicação, uma origem, um endpoint de destino e uma ou mais tarefas.
Instância de replicação
A criação da instância de replicação é simples para qualquer pessoa familiarizada com instâncias do EC2 na AWS:
A única alteração dos padrões foi selecionar AWS DMS 3.3.0 ou mais tarde devido ao meu mecanismo local do PostgreSQL ser 11.5:
E aqui está a lista de versões do AWS DMS atualmente disponíveis:
As grandes instalações também devem observar os limites do AWS DMS:
Há também um conjunto de limitações que são consequência da replicação lógica do PostgreSQL restrições. Por exemplo, o AWS DMS não migrará objetos secundários:
Vale ressaltar que no PostgreSQL todos os índices são índices secundários, e que não é uma coisa ruim, como observado nesta discussão mais detalhada.
Ponto de extremidade de origem
Siga o assistente para criar o Source Endpoint:
No cenário de configuração Configuração de uma rede para uma VPC usando a Internet my rede doméstica exigiu alguns ajustes para permitir que o endereço IP do endpoint de origem acessasse meu servidor interno. Primeiro, criei um encaminhamento de porta no roteador de borda (173.180.222.170) para enviar tráfego na porta 30485 para meu gateway interno (10.11.11.241) na porta 5432, onde posso ajustar o acesso com base no endereço IP de origem por meio das regras do iptables. A partir daí, o tráfego de rede flui através de um túnel SSH para o servidor web que executa o banco de dados PostgreSQL. Com a configuração descrita o client_addr na saída de pg_stat_activity aparecerá como 127.0.0.1.
Antes de permitir o tráfego de entrada, os logs do iptables mostram 12 tentativas da instância de replicação em ip=3.227.167.58):
Jan 19 17:35:28 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=23973 DF PROTO=TCP SPT=54662 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:35:29 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=23974 DF PROTO=TCP SPT=54662 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:35:31 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=23975 DF PROTO=TCP SPT=54662 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:35:35 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=23976 DF PROTO=TCP SPT=54662 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:35:48 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=4328 DF PROTO=TCP SPT=54667 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:35:49 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=4329 DF PROTO=TCP SPT=54667 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:35:51 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=4330 DF PROTO=TCP SPT=54667 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:35:55 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=4331 DF PROTO=TCP SPT=54667 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:36:08 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=8298 DF PROTO=TCP SPT=54670 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:36:09 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=8299 DF PROTO=TCP SPT=54670 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:36:11 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=8300 DF PROTO=TCP SPT=54670 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Jan 19 17:36:16 mha.can.local kernel: filter/INPUT: IN=enp0s29f7u2 OUT= MAC=00:24:9b:17:3a:fa:9c:1e:95:e5:ad:b0:08:00 SRC=3.227.167.58 DST=10.11.11.241 LEN=60 TOS=0x00 PREC=0x00 TTL=39 ID=8301 DF PROTO=TCP SPT=54670 DPT=5432 WINDOW=26880 RES=0x00 SYN URGP=0
Depois de permitir o endereço IP do endpoint de origem (3.227.167.58), o teste de conexão é bem-sucedido e a configuração do endpoint de origem é concluída. Também temos uma conexão SSL para criptografar o tráfego através de redes públicas. Isso pode ser confirmado no servidor PostgreSQL usando a consulta abaixo, bem como no console da AWS:
postgres=# SELECT datname, usename, client_addr, ssl, cipher, query, query_start FROM pg_stat_activity a, pg_stat_ssl s where a.pid=s.pid and usename = 's9sdemo';
datname | usename | client_addr | ssl | cipher | query | query_start
---------+---------+-------------+-----+--------+-------+-------------
(0 rows)
… e, em seguida, assista enquanto executa a conexão no console da AWS. Os resultados devem ser semelhantes ao seguinte:
postgres=# \watch
Sun 19 Jan 2020 06:50:51 PM PST (every 2s)
datname | usename | client_addr | ssl | cipher | query | query_start
----------------+---------+-------------+-----+-----------------------------+------------------------------------------------------------------------------------+-------------------------------
nextcloud_prod | s9sdemo | 127.0.0.1 | t | ECDHE-RSA-AES256-GCM-SHA384 | select cast(setting as integer) from pg_settings where name = 'server_version_num' | 2020-01-19 18:50:51.463496-08
(1 row)
…enquanto o console da AWS deve relatar um sucesso:
Conforme indicado na seção de pré-requisitos, se escolhermos a opção de migração Full load , replicação em andamento, precisaremos alterar as permissões para o usuário do PostgreSQL. Esta opção de migração requer privilégios de superusuário, portanto ajustei as configurações para o usuário PostgreSQL criado anteriormente:
nextcloud_prod=# \du s9sdemo
List of roles
Role name | Attributes | Member of
-----------+------------+-----------
s9sdemo | Superuser | {}
O mesmo documento contém instruções para modificar postgresql.conf. Aqui está uma diferença do original:
--- a/var/lib/pgsql/data/postgresql.conf
+++ b/var/lib/pgsql/data/postgresql.conf
@@ -95,7 +95,7 @@ max_connections = 100 # (change requires restart)
# - SSL -
-#ssl = off
+ssl = on
#ssl_ca_file = ''
#ssl_cert_file = 'server.crt'
#ssl_crl_file = ''
@@ -181,6 +181,7 @@ dynamic_shared_memory_type = posix # the default is the first option
# - Settings -
+wal_level = logical
#wal_level = replica # minimal, replica, or logical
# (change requires restart)
#fsync = on # flush data to disk for crash safety
@@ -239,6 +240,7 @@ min_wal_size = 80MB
#max_wal_senders = 10 # max number of walsender processes
# (change requires restart)
#wal_keep_segments = 0 # in logfile segments; 0 disables
+wal_sender_timeout = 0
#wal_sender_timeout = 60s # in milliseconds; 0 disables
#max_replication_slots = 10 # max number of replication slots
@@ -451,6 +453,7 @@ log_rotation_size = 0 # Automatic rotation of logfiles will
#log_duration = off
#log_error_verbosity = default # terse, default, or verbose messages
Por último, não se esqueça de ajustar as configurações do pg_hba.conf para permitir a conexão SSL do endereço IP da instância de replicação.
Agora estamos prontos para a próxima etapa.
Ponto de extremidade de destino
Siga o assistente para criar o Target Endpoint:
Esta etapa pressupõe que a instância do RDS com o endpoint especificado já existe junto com o banco de dados vazio nextcloud_awsdms. O banco de dados pode ser criado durante a configuração da instância do RDS.
Neste ponto, se a rede da AWS estiver configurada corretamente, devemos estar prontos para executar o teste de conexão:
Com o ambiente instalado, agora é hora de criar a tarefa de migração :
Tarefa de migração
Depois que o assistente for concluído, a configuração ficará assim:
... e a segunda parte da mesma visualização:
Uma vez iniciada a tarefa, podemos monitorar o progresso — abra a tarefa detalhes e role para baixo até Estatísticas da Tabela:
O AWS DMS está usando o esquema em cache para migrar as tabelas do banco de dados. Enquanto a migração avança, podemos continuar “observando” as consultas no banco de dados de origem e o log de erros do PostgreSQL, além do console da AWS:
Em caso de erros, o estado de falha é exibido no console:
Um lugar para procurar pistas é o CloudWatch, embora durante meus testes os logs não acabou sendo publicado, o que provavelmente poderia ser apenas mais uma falha na versão beta do AWS DMS 3.3.0, como aconteceu no final deste exercício:
O progresso da migração é bem exibido no console do AWS DMS:
Quando a migração for concluída, revisando mais uma vez, o log de erros do PostgreSQL , revela uma mensagem surpreendente:
O que parece acontecer, é que no PostgreSQL 9.6, 10 a tabela pg_class contém a coluna nomeada relhaspkey, mas esse não é o caso em 11. E essa é a falha na versão beta do AWS DMS 3.3.0 que eu estava me referindo anteriormente.
GCP
A abordagem do Google é baseada na ferramenta de código aberto PgBouncer. A empolgação durou pouco, pois a documentação oficial fala sobre a migração do PostgreSQL para um ambiente de mecanismo de computação.
Outras tentativas de encontrar uma solução de migração para o Cloud SQL semelhante ao AWS DMS falharam. As estratégias de migração do banco de dados não contêm nenhuma referência ao PostgreSQL:
As instalações do PostgreSQL no local podem ser migradas para o Cloud SQL usando os serviços de um dos parceiros do Google Cloud.
Uma possível solução pode ser o PgBouncer para Cloud SQL, mas isso não está no escopo deste blog.
Microsoft Cloud Services (Azure)
Para facilitar a migração de cargas de trabalho PostgreSQL do local para o banco de dados gerenciado do Azure para PostgreSQL, a Microsoft fornece o Azure DMS que, de acordo com a documentação, pode ser usado para migrar com tempo de inatividade mínimo. O tutorial Migrar PostgreSQL para o Banco de Dados do Azure para PostgreSQL online usando DMS descreve essas etapas em detalhes.
A documentação do Azure DMS discute detalhadamente os problemas e limitações associados à migração das cargas de trabalho do PostgreSQL para o Azure.
Uma diferença notável do AWS DMS é o requisito de criar manualmente o esquema:
Uma demonstração disso será tema de um blog futuro. Fique atento.