Terça-feira do Postgres nº 5: "PostgreSQL e Kubernetes. CI/CD. Automatização de testes"

Terça-feira do Postgres nº 5: "PostgreSQL e Kubernetes. CI/CD. Automatização de testes"

No final do ano passado, ocorreu uma nova transmissão ao vivo da comunidade russa de PostgreSQL #RuPostgres, na qual seu cofundador Nikolai Samokhvalov conversou com o diretor técnico da 'Flanta', Dmitry Stolyarov, sobre este SGBD no contexto do Kubernetes.

Publicamos a transcrição da parte principal desta discussão, e no canal do YouTube da comunidade está disponível a gravação completa:

Por que no hosting comum a administração do PrestaShop é lenta, e no seu não é?

Bancos de dados e Kubernetes

NS: Hoje não vamos falar sobre VACUUM e CHECKPOINTs. Queremos conversar sobre Kubernetes. Sei que você já tem muitos anos de experiência. Assistia seus vídeos e até revia alguns trechos… Vamos direto ao ponto: por que Postgres ou MySQL no K8s?

DS: Não há uma resposta definitiva para essa pergunta, nem poderia haver. Mas, basicamente, é a simplicidade e conveniência… potenciais. Todos querem serviços gerenciados.

NS: Para como RDS, apenas que seja feito internamente?

DS: Sim: para ser como o RDS, só que em qualquer lugar.

NS: 'Em qualquer lugar' — isso é um bom ponto. Em grandes empresas, tudo está em lugares diferentes. Mas por que, então, se é uma grande empresa, não optar por uma solução pronta? Por exemplo, a Nutanix tem suas próprias soluções, e outras empresas (VMware…) têm o mesmo 'RDS, só que internamente'.

DS: Mas aqui estamos falando de uma implementação específica que funcionará apenas em certas condições. E quando se trata de Kubernetes, há uma enorme diversidade de infraestrutura (que pode estar no K8s). Essencialmente, é um padrão para APIs na nuvem…

NS: E ainda por cima é gratuito!

DS: Isso não é tão importante. A gratuidade é relevante para um segmento pequeno do mercado. O que realmente importa é outra coisa… Você provavelmente deve se lembrar da apresentação 'Bancos de dados e Kubernetes»?

NS: Sim.

DS: Entendi que foi recebida de maneira muito ambígua. Parte das pessoas pensou que eu estava dizendo: 'Pessoal, vamos colocar todos os bancos de dados no Kubernetes!', enquanto outros consideraram que eram apenas bicicletas horríveis. Mas eu queria dizer algo completamente diferente: 'Vejam o que está acontecendo, quais problemas existem e como podem ser resolvidos. Agora, é hora de levar bancos para o Kubernetes? Para produção? Bem, a menos que você goste… de lidar com certas coisas. Mas para desenvolvimento — posso dizer que recomendo. Para desenvolvimento, a dinâmica na criação/exclusão de ambientes é muito importante.'

NS: Por desenvolvimento, você se refere a todos os ambientes que não são produção? Staging, QA…

DS: Se estamos falando sobre perf-stands, provavelmente não, porque os requisitos são específicos. Se estamos falando sobre casos especiais, onde um grande banco de dados é necessário no staging, então também, provavelmente não... Se for um ambiente estático e de longa duração, qual é a vantagem de ter o banco de dados no K8s?

NS: Nenhuma. Mas onde vemos ambientes estáticos? Um ambiente estático está obsoleto já amanhã.

DS: Staging pode ser estático. Temos clientes...

NS: Sim, eu também tenho. É um grande problema se você tem um banco de dados de 10 TB e o staging é de 200 GB...

DS: Eu tenho um caso muito interessante! No staging está um banco de dados de produção, no qual são feitas alterações. E há um botão: 'rollout to production'. Essas mudanças — deltas — são adicionadas (parece que são sincronizadas simplesmente via API) à produção. É uma versão muito exótica.

NS: Eu vi startups no Vale que ainda estão no RDS ou até no Heroku — histórias de 2-3 anos atrás — e elas fazem download do dump para seus laptops. Porque o banco de dados ainda tem apenas 80 GB, e há espaço no laptop. Depois elas compram discos adicionais para cada um, para ter 3 bancos de dados e fazer diferentes desenvolvimentos. Isso também acontece. Também vi que não têm medo de copiar de prod para staging — isso depende muito da empresa. Mas vi também que têm muito medo, e muitas vezes não há tempo e mãos suficientes. Mas antes de falarmos sobre esse tema, eu gostaria de ouvir sobre Kubernetes. Estou certo de que em prod ainda não é comum?

DS: Temos pequenos bancos de dados em prod. Estamos falando de volumes na casa das dezenas de gigabytes e serviços não críticos, para os quais foi muito trabalhoso criar réplicas (e também não havia tal necessidade). E sob a condição de que haja armazenamento adequado no Kubernetes. Esse banco de dados funcionava em uma máquina virtual — digamos, no VMware, sobre o SAN. Nós o colocamos em PV e agora podemos transferi-lo de máquina para máquina.

NS: Bancos de dados desse tamanho, até 100 GB, em bons discos e em uma boa rede, podem ser instalados em poucos minutos, certo? Uma velocidade de 1 GB por segundo — isso já não é exótico.

DS: Sim, para uma operação linear não é um problema.

NS: Ok, sobre prod devemos apenas pensar. E se considerarmos Kubernetes para ambientes não-prod — como fazer? Vejo que na Zalando estão desenvolvendo um operador, no Crunchy estão criando, há algumas outras opções. E temos OnGres — é o nosso bom amigo Alvaro da Espanha: eles fazem não apenas operador, mas uma distribuição inteira (StackGres), que além do próprio Postgres, também envolve a implementação de backup e o proxy Envoy...

DS: Para que serve o Envoy? Para balanceamento de tráfego do Postgres?

NS: Sim. Eles veem isso assim: se pegarmos uma distribuição Linux e o kernel, o PostgreSQL padrão é o kernel, e eles querem criar uma distribuição que seja amigável a nuvens e que opere no Kubernetes. Eles integram componentes (backups etc.) e ajustam para que funcionem bem.

DS: Muito legal! Basicamente, é um software para criar seu próprio Postgres gerenciado.

NS: Distribuições Linux têm problemas contínuos: como criar drivers para suportar todo o hardware. E a ideia deles é que funcionem no Kubernetes. Sei que recentemente na Zalando vimos uma dependência do AWS, e isso não é muito bom. Não deveria haver uma dependência de infraestrutura específica — qual é o sentido nisso?

DS: Não sei em que situação a Zalando se vinculou, mas atualmente no Kubernetes o storage é feito de forma que não é possível tirar um backup em disco de maneira genérica. Recentemente, na última versão do padrão — a especificação CSI — foi implementada a possibilidade de snapshots, mas onde isso foi realizado? Honestamente, ainda está muito cru... Tentamos a CSI sobre AWS, GCE, Azure, vSphere, mas assim que começamos a usar, já dá para ver que ainda não está pronto.

NS: Por isso, às vezes é necessário se vincular à infraestrutura. Acho que isso ainda está numa fase inicial — problemas de crescimento. Pergunta: o que você aconselharia para iniciantes que querem experimentar PgSQL no K8s? Que operador, talvez?

DS: O problema é que o Postgres representa apenas 3% para nós. Temos uma longa lista de diferentes softwares no Kubernetes, nem vou mencionar todos. Por exemplo, o Elasticsearch. Há muitos operadores: alguns estão em desenvolvimento ativo, outros não. Definimos requisitos do que deve ter em um operador para que o considerássemos sério. Um operador especificamente para Kubernetes — não um ‘operador para fazer algo nas condições da Amazon’... De fato, usamos maciçamente (= quase todos os clientes) um único operador — para Redis (em breve publicaremos um artigo sobre ele).

NS: E para MySQL, também não existe? Sei que a Percona... como agora eles lidam tanto com MySQL, quanto com MongoDB e Postgres, deveriam lançar algo universal: para todos os bancos de dados, para todos os provedores de nuvem.

DS: Não conseguimos olhar para os operadores do MySQL. Para nós, isso não é o foco principal no momento. MySQL funciona bem de forma autônoma. Por que usar um operador se você pode simplesmente iniciar o banco de dados… Você pode iniciar um contêiner Docker com PostgreSQL ou pode simplesmente iniciá-lo de maneira simples.

NS: Essa também foi uma pergunta. Sem operador nenhum?

DS: Sim, 100% do tempo temos PostgreSQL funcionando sem operador. Por enquanto, assim é. Estamos usando ativamente um operador para Prometheus e para Redis. Temos planos de encontrar um operador para Elasticsearch — isso é o que mais “pegamos” porque queremos usá-lo 100% das vezes no Kubernetes. Assim como também queremos garantir que o MongoDB sempre seja instalado no Kubernetes. Aqui surgem certas necessidades — há uma sensação de que nesses casos podemos fazer algo. Quanto ao Postgres, nem olhamos. Claro, sabemos da existência de várias opções, mas, de fato, temos uma implementação autônoma.

Banco de dados para testes no Kubernetes

NS: Vamos mudar para o tema de testes. Como fazer a implementação de mudanças no banco de dados — do ponto de vista da perspectiva DevOps. Temos microsserviços, muitos bancos, e sempre há algo mudando. Como assegurar um CI/CD adequado para que do ponto de vista do SGBD tudo esteja em ordem. Qual é a sua abordagem?

DS: Não pode haver uma única resposta. Existem vários parâmetros. O primeiro é o tamanho do banco que queremos implementar. Você mesmo mencionou que nas empresas a abordagem para ter uma cópia do banco de produção no ambiente de dev e staging varia.

NS: Sob a política de GDPR, penso que estão cada vez mais cautelosos... Posso te dizer que na Europa já começaram a aplicar multas.

DS: Mas muitas vezes é possível escrever um software que faz o dump da produção e o ofusca. Isso gera dados de produção (snapshot, dump, cópia binária...), mas eles são anonimizados. Ao invés disso, podem ser scripts de geração: podem ser fixtures ou simplesmente um script que gera um banco de dados grande. O problema é: quanto tempo leva para criar a imagem base? E quanto tempo para implantá-la no ambiente necessário?

Chegamos a um esquema: se o cliente tiver um conjunto de dados de fixture (versão mínima do banco), usamos isso por padrão. Quando se trata de ambientes de review, quando criamos um branch, temos uma instância do aplicativo criada — implantamos um banco pequeno lá. Mas ficou bem feito e uma variante, quando fazemos um dump da produção uma vez por dia (à noite) e construímos com base nisso um contêiner Docker com PostgreSQL e MySQL com esses dados carregados. Se precisar desdobrar esse ambiente 50 vezes, isso pode ser feito de forma bastante simples e rápida.

NS: Simplesmente copiando?

DS: Os dados são armazenados diretamente na imagem Docker. Ou seja, temos uma imagem pronta, mesmo que de 100 GB. Graças às camadas no Docker, podemos desdobrar essa imagem o número necessário de vezes rapidamente. É um método simples, mas funciona bem.

NS: Depois, quando você testa, isso muda diretamente dentro do Docker, certo? Copy-on-write dentro do Docker — descartamos e começamos de novo, tudo funciona bem. Ótimo! E você já está usando isso amplamente?

DS: Há bastante tempo.

NS: Estamos lidando com coisas muito semelhantes. Só que não usamos o copy-on-write do Docker, mas algum outro método.

DS: Ele não é genérico. Mas o método do Docker funciona em qualquer lugar.

NS: Em teoria, sim. Mas também temos módulos, podemos fazer diferentes módulos e trabalhar com diferentes sistemas de arquivos. Aqui está o detalhe. Do lado do Postgres, olhamos para tudo isso de forma diferente. Agora, olhei do lado do Docker e vi que tudo funciona. Mas se a base for enorme, por exemplo, 1 TB, isso já se torna demorado: tanto as operações à noite quanto a inserção de tudo no Docker... E se precisar inserir 5 TB no Docker... Ou está tudo bem?

DS: Qual a diferença: são apenas blobs, apenas bits e bytes.

NS: A diferença é a seguinte: você faz isso através de dump e restore?

DS: Não necessariamente. As maneiras de gerar essa imagem podem ser diferentes.

NS: Para alguns clientes, fizemos de forma que, em vez de gerar regularmente a imagem básica, a mantemos constantemente atualizada. No fundo, é uma réplica, mas os dados não vêm diretamente do mestre, e sim através de um arquivo de log. Um arquivo binário, onde os WALs são aplicados diariamente, e backups também são feitos... Esses WALs depois são enviados — com um pequeno atraso (apenas 1-2 segundos) — até a imagem básica. A partir dela, clonamos de qualquer maneira — atualmente, usamos ZFS por padrão.

DS: Mas com ZFS você está limitado a um nó.

NS: Sim. Mas o ZFS tem uma mágica extra send: com ela é possível enviar um snapshot e até (eu ainda não testei muito isso, mas...) é possível enviar a delta entre dois PGDATA. Na verdade, temos mais uma ferramenta que não consideramos muito para essas tarefas. No PostgreSQL existe pg_rewind, funcionando como um «rsync inteligente», ignorando muitas coisas que não precisam ser observadas, pois realmente não houve mudanças. Podemos fazer uma rápida sincronização entre dois servidores e voltar no tempo da mesma forma.

Então, estamos tentando, desse lado mais DBA, criar uma ferramenta que permita fazer o mesmo que você mencionou: temos um banco de dados, mas queremos testar algo 50 vezes, quase ao mesmo tempo.

DS: 50 vezes significa que você precisa solicitar 50 instâncias Spot.

NS: Não, fazemos tudo em uma máquina.

DS: Mas como você vai implementar 50 vezes se esse único banco, digamos, tem um terabyte? Provavelmente, ele precisa de, digamos, 256 GB de RAM?

NS: Sim, às vezes precisa de muita memória — isso é normal. Mas aqui vai um exemplo da vida real. Em uma máquina de produção, temos 96 núcleos e 600 GB. Para o banco de dados, usamos 32 núcleos (até mesmo 16 núcleos às vezes) e de 100 a 120 GB de memória.

DS: E cabe ali 50 cópias?

NS: Mas a cópia é uma só, depois funciona com copy-on-write (ZFS)… Vou explicar melhor.

Por exemplo, temos um banco de dados de 10 TB. O disco foi feito, e o ZFS ainda comprimiu seu tamanho em 30-40%. Como não fazemos testes de carga, o tempo de resposta exato não é importante para nós: pode ser até 2 vezes mais lento — tudo bem.

Oferecemos a possibilidade para programadores, QA, DBA, etc., realizarem testes em 1-2 fluxos. Por exemplo, eles podem iniciar alguma migração. Não precisa imediatamente de 10 núcleos — precisa de 1 backend do Postgres, 1 núcleo. A migração será iniciada — pode ser que autovacuum outra migração inicie, então o segundo núcleo será usado. Temos entre 16 e 32 núcleos dedicados, então 10 pessoas podem trabalhar ao mesmo tempo, sem problemas.

Como fisicamente PGDATA é igual, resulta que estamos, na verdade, enganando o Postgres. A questão é a seguinte: são iniciados, por exemplo, 10 Postgres ao mesmo tempo. Qual é o problema normalmente? Configuram shared_buffers, digamos, em 25%. Portanto, seriam 200 GB. Você não consegue iniciar mais de três deles, pois a memória acaba.

Mas chegamos a um ponto em que percebemos que isso não era necessário: configuramos shared_buffers em 2 GB. O PostgreSQL possui effective_cache_size, e na realidade só ele afeta os planos. O que configuramos para 0,5 TB. E nem importa que na verdade não existam: ele cria planos como se existissem.

Assim, ao testarmos uma migração, podemos reunir todos os planos — veremos como isso acontecerá em produção. Os segundos lá serão diferentes (mais lentos), mas os dados que realmente lemos e os próprios planos (quais são os JOINs, etc.) permanecem exatamente os mesmos que na produção. E, ao mesmo tempo, podemos realizar várias dessas verificações em uma única máquina.

DS: Você não acha que há alguns problemas aqui? O primeiro é que essa solução funciona apenas no PostgreSQL. Essa abordagem é muito específica, não é genérica. O segundo é que o Kubernetes (e tudo o que está se movendo em direção às tecnologias de nuvem) pressupõe uma infinidade de nós, e esses nós são efêmeros. No seu caso, é um nó stateful, persistente. Essas coisas me causam contradições.

NS: Primeiro — concordo, isso é puramente uma história do Postgres. Acho que se tivermos algum IO direto e um pool de buffer quase para toda a memória, essa abordagem não será adequada — os planos serão diferentes. Mas, por enquanto, estamos apenas trabalhando com Postgres e não pensamos em outros.

Sobre o Kubernetes. Você mesmo sempre diz que nossa base é persistente. Se a instância cair, o principal é manter o disco. Nossa plataforma também está toda em Kubernetes, e o componente com PostgreSQL — separado (embora um dia ele esteja lá também). Portanto, é assim: a instância caiu, mas nós salvamos seu PV e simplesmente conectamos a outra (nova) instância, como se nada tivesse acontecido.

DS: Do meu ponto de vista, estamos criando pods no Kubernetes. O K8s é elástico: os nós são requisitados conforme necessário. A tarefa é simplesmente criar um pod e dizer que ele precisa de X recursos, e então o K8s se encarregará do resto. Mas o suporte a armazenamento no Kubernetes ainda é instável: em 1.16, neste teste de 2015 1.17 (esse lançamento saiu semanas atrás) essas funcionalidades estão se tornando apenas beta.

Daqui a seis meses a um ano — isso se tornará mais ou menos estável, ou pelo menos será declarado como tal. Então a possibilidade de snapshots e resize já resolve sua tarefa completamente. Porque você tem uma base. Sim, ela pode não ser muito rápida, mas a velocidade depende do que está "por trás", pois algumas implementações conseguem copiar e fazer copy-on-write no nível do subsistema de disco.

NS: Além disso, é necessário que todos os motores (Amazon, Google…) comecem a suportar essa versão — isso também leva algum tempo.

DS: Por enquanto, não os estamos usando. Estamos usando o nosso.

Desenvolvimento local em Kubernetes

NS: Você já se deparou com a necessidade de configurar todos os pods em uma única máquina e fazer um pequeno teste? Para obter rapidamente uma prova de conceito e verificar se o aplicativo funciona no Kubernetes, sem alocar várias máquinas para isso. Existe o Minikube, certo?

DS: Eu acho que esse caso — a implantação em um único nó — é exclusivamente sobre desenvolvimento local. Ou algumas manifestações desse padrão. Existe Minikube, existe k3s, KIND. Estamos indo na direção de usar Kubernetes IN Docker. Começamos a trabalhar com isso para testes.

NS: Eu costumava pensar que era uma tentativa de embalar todos os pods em uma única imagem Docker. Mas, na verdade, é sobre algo totalmente diferente. Ainda há contêineres separados, pods separados — apenas dentro do Docker.

DS: Sim. E lá há uma simulação bem interessante, mas a ideia é essa… Temos uma ferramenta para implantação — werf. Queremos adicionar um modo — digamos werf up: “Levante meu Kubernetes local”. E então inicie um werf follow. Assim, o desenvolvedor pode editar no IDE, enquanto um processo em execução no sistema vê as alterações e recompila as imagens, reaplica-as no K8s local. Assim, queremos tentar resolver o problema do desenvolvimento local.

Snapshots e clonagem de DB na realidade do K8s

NS: Se voltarmos ao copy-on-write. Eu notei que as nuvens também têm snapshots. Eles funcionam de maneiras diferentes. Por exemplo, no GCP: você tem uma instância de vários terabytes na costa leste dos EUA. Você faz snapshots periodicamente. Levanta uma cópia do disco a partir do snapshot na costa oeste — em poucos minutos já está tudo pronto, funciona muito rápido, só precisa preencher o cache na memória. Mas esses clones (snapshots) são para provisionar um novo volume. É ótimo quando você precisa criar muitas instâncias.

Mas para testes, parece-me que os snapshots sobre os quais você fala no Docker ou eu falo no ZFS, btrfs e até LVM… — eles permitem que não se crie realmente novos dados em uma única máquina. Na nuvem, você ainda terá que pagar por eles toda vez e esperar, em vez de segundos, minutos (e no caso de lazy load, possivelmente, horas).

Em vez disso, você pode obter esses dados em um ou dois segundos, rodar o teste e descartá-los. Esses snapshots resolvem diferentes tarefas. No primeiro caso — para escalar e obter novas réplicas, e no segundo — para testes.

DS: Não concordo. Fazer a clonagem de volumes de forma adequada é uma tarefa da nuvem. Não olhei para a implementação deles, mas sei como fazemos isso no hardware. Temos Ceph, e nele podemos dizer a qualquer volume físico (RBD) e obter em questão de dezenas de milissegundos um segundo volume com as mesmas características, clone IOPS e assim por diante. É preciso entender que lá dentro tem um complicado copy-on-write. Por que a nuvem não faz da mesma forma? Estou certo de que eles estão, de alguma forma, tentando fazer isso.: Mas mesmo assim, eles levarão segundos, dezenas de segundos, para levantar uma instância, trazer o Docker, etc.

NS: Por que é necessário levantar uma instância inteira? Temos uma instância com 32 núcleos, outra com 16... e cabe um certo número de usuários — por exemplo, quatro. Quando pedimos o quinto, já se levanta uma nova instância que depois será removida.

DS: Sim, interessante, no Kubernetes é uma história diferente. Nossa base de dados não está no K8s, e é uma instância única. No entanto, para clonar uma base de dados multi-terabyte, não leva mais do que dois segundos.

NS: Isso é incrível. Mas meu argumento inicial é que isso não é uma solução genérica. Sim, é ótimo, mas só funciona com Postgres e apenas em um único nó.

DS: Ele não é adequado apenas para Postgres: esses planos, como descrevi, funcionarão apenas nele. Mas se não nos preocupamos com os planos, e precisamos apenas de todos os dados para testes funcionais, então isso serve para qualquer SGBD.

NS: Muitos anos atrás fizemos algo semelhante com snapshots LVM. É o clássico. Essa abordagem foi usada de forma bastante ativa. O problema são os nós stateful — é uma dor de cabeça. Porque não podemos derrubá-los, devemos sempre lembrar deles...

DS: Você não vê aqui uma possibilidade de hibridização? Suponha que o stateful seja um pod, ele está funcionando para várias pessoas (muitos testadores). Temos um volume, mas graças ao sistema de arquivos, os clones são locais. Se o pod falhar, o disco permanece — o pod levantará, coletará informações sobre todos os clones, levantará tudo de volta e dirá: 'Aqui estão seus clones nessas portas, continuem trabalhando com eles'.

NS: Tecnologicamente, isso significa que dentro do Kubernetes é um único pod, dentro do qual rodamos muitos Postgres.

DS: Sim. Ele tem um limite: digamos que ao mesmo tempo não mais de 10 pessoas trabalham com ele. Se precisarmos de 20 — vamos levantar um segundo pod assim. É perfeitamente viável cloná-lo, obtendo um segundo volume completo, que terá os mesmos 10 clones 'finos'. Não vê essa possibilidade?

NS: Não. Isso é possível, mas requer um bom planejamento.

DS: É necessário adicionar questões de segurança aqui. Esse tipo de organização implica que este pod tenha altas permissões (capabilities), pois ele pode realizar operações não padrão no sistema de arquivos... Mas reitero: acredito que, a médio prazo, o Kubernetes corrigirá o armazenamento, nas nuvens resolverão toda a história com os volumes — tudo vai "funcionar normalmente". Haverá redimensionamento, clonagem... Se há um volume — nós dizemos: "Crie um novo com base naquele", — e em um segundo e meio teremos o que precisamos.

NS: Não acredito em um segundo e meio para muitos terabytes. No Ceph você faz isso manualmente, e está falando sobre nuvens. Vá para a nuvem, faça um clone do volume EBS de vários terabytes na EC2 e veja qual será o desempenho. Isso não vai levar alguns segundos. Estou muito curioso para saber quando eles alcançarão essa métrica. Entendo o que você está dizendo, mas permito-me discordar.

DS: Ok, mas disse que a médio prazo, não a curto prazo. Dentro de alguns anos.

Sobre o operador para PostgreSQL da Zalando

No meio desta reunião, Aleksey Klyukin, um ex-desenvolvedor da Zalando, também se juntou a ela e contou a história do operador PostgreSQL:

É ótimo que esse tema tenha sido abordado: tanto Postgres quanto Kubernetes. Quando começamos a trabalhar nisso na Zalando em 2017, era um tópico que todos queriam desenvolver, mas ninguém estava fazendo. Todos já estavam adotando Kubernetes, mas quando perguntávamos como lidar com bancos de dados, até pessoas como Kelsey Hightower, que pregavam K8s, diziam aproximadamente o seguinte:

"Vá para serviços gerenciados e os utilize, não execute bancos de dados no Kubernetes. Caso contrário, seu K8s decidirá, por exemplo, fazer uma atualização, desligará todos os nós, e seus dados desaparecerão para muito longe".

Decidimos criar um operador que, ao contrário desse conselho, executaria bancos de dados Postgres no Kubernetes. E tínhamos uma boa justificativa — Patroni. Isso é um failover automático para PostgreSQL, feito corretamente, ou seja, utilizando etcd, consul ou ZooKeeper como repositório de informações do cluster. Um repositório que fornecerá a todos que perguntarem, por exemplo, quem é o líder atual, a mesma informação — apesar de estarmos completamente distribuídos — para evitar o split brain. Além disso, tínhamos imagem Docker para ele.

Na realidade, a necessidade de auto failover da empresa surgiu após a migração de um data center interno para a nuvem. A nuvem foi baseada em uma solução própria de PaaS (Platform-as-a-Service). É Open Source, mas para implementá-la foi necessário um grande esforço. Chamava-se STUPS.

Inicialmente, não havia Kubernetes. Na verdade, quando a solução própria foi implantada, o K8s já existia, mas era tão imaturo que não servia para produção. Foi, na minha opinião, em 2015 ou 2016. Em 2017, Kubernetes ficou mais ou menos maduro — surgiu a necessidade de migração para lá.

E já tínhamos um contêiner Docker. Havia PaaS que usava Docker. Por que não tentar o K8s? Por que não escrever nosso próprio operador? Murat Kabilov, que veio até nós do Avito, começou isso como um projeto por iniciativa própria — "brincar" — e o projeto "decolou".

Mas, na verdade, eu queria falar sobre AWS. Por que historicamente houve código relacionado à AWS...

Quando você inicia qualquer coisa no Kubernetes, é preciso entender que o K8s é um trabalho em progresso. Ele está sempre se desenvolvendo, melhorando e, periodicamente, até quebrando. É necessário acompanhar cuidadosamente todas as mudanças no Kubernetes e estar preparado, se necessário, para se aprofundar e descobrir como funciona em detalhes — talvez mais do que você gostaria. Isso é, na verdade, comum a qualquer plataforma na qual você está executando seus bancos de dados...

Assim, quando fizemos o operador, tínhamos um Postgres que trabalhava com um volume externo (neste caso — EBS, já que estávamos trabalhando na AWS). O banco de dados cresceu e, em algum momento, foi necessário fazer um resize: por exemplo, o tamanho original do EBS era de 100 TB, o banco cresceu para isso, agora queremos aumentar o EBS para 200 TB. Como? Suponha que você possa fazer um dump/restauração em uma nova instância, mas isso é demorado e gera inatividade.

Portanto, desejávamos um resize que aumentasse a partição do EBS e depois dissesse ao sistema de arquivos para usar o novo espaço. E fizemos isso, mas na época o Kubernetes não tinha nenhuma API para a operação de resize. Como estávamos trabalhando na AWS, escrevemos código para sua API.

Nada impede de fazer o mesmo para outras plataformas. No operador, não há a limitação de que ele só pode ser executado na AWS; em outras plataformas, ele vai funcionar. Em geral, este é um projeto Open Source: se alguém quiser acelerar a disponibilização de uma nova API — fique à vontade. Há GitHub, pull requests — a equipe da Zalando tenta respondê-las rapidamente e promover o operador. Pelo que sei, o projeto participou do Google Summer of Code e de outras iniciativas semelhantes. A Zalando está trabalhando ativamente nele.

P.S. Bônus!

Se você está interessado no tema PostgreSQL e Kubernetes, também chamamos a atenção para o fato de que na semana passada ocorreu o seguinte Postgres-terça-feira, onde Nikolai conversou com Alexander Kukushkin da Zalando. O vídeo está disponível aqui.

P.P.S.

Confira também em nosso blog:

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster