Um grupo do central em servidores separados¶
Redundância explica de que é feita uma instalação com reserva e o que a segunda instância muda. Esta página trata de montá-la: quais ajustes cada máquina recebe, o que se diz aos streamers e o que verificar quando tudo estiver de pé.
O que se descreve aqui é um parque de servidores independentes — uma máquina por instância. Para experimentar o mesmo num único notebook, sem alugar servidores, siga o laboratório no Docker: o mesmo grupo sobe a partir de contêineres em alguns minutos.
O que exatamente é implantado¶
Uma instalação com reserva tem quatro partes, e apenas uma delas é o Catena:
- Um cluster PostgreSQL, acessível por todas as instâncias num mesmo endereço. É o único depósito de estado e a única parte cuja tolerância a falhas o Catena não assume.
- Duas ou mais instâncias do central — máquinas separadas com a mesma configuração, diferindo nos papéis e no endereço anunciado.
- Streamers — máquinas separadas às quais se dá não o endereço de uma instância, e sim a lista de endereços do grupo.
- Um ponto de entrada do operador — um único endereço com uma instância viva atrás: um nome DNS com comutação ou um balanceador.
A regra com que começa uma instalação assim: o central e a transmissão vivem em máquinas diferentes. Um streamer local dentro do processo do central não serve aqui — ele compartilha a sorte do processo, e seus streams morrem junto com o plano de controle.
Quantos de cada um¶
| Parte | Quantos | Observação |
|---|---|---|
| PostgreSQL | Um cluster lógico | Dois servidores de banco independentes são duas instalações distintas, não uma reserva |
| Instâncias do central | Duas ou mais | Uma terceira entra com a mesma configuração; as existentes não precisam ser reescritas |
| Streamers | Quantos o ar exigir | A redundância deles vem da alocação, não daqui |
| Ponto de entrada do operador | Um endereço | Os streamers não passam por ele |
A configuração de uma instância do central¶
As instâncias de um grupo diferem em exatamente duas linhas: o endereço anunciado e o conjunto de papéis. Todo o resto é idêntico, inclusive a string de conexão com o banco.
A primeira instância:
listeners:
http:
- port: 80
central:
database_url: postgres://central:senha@db.example.com:5432/central
admin_keys:
- chave-de-gestao
roles: [run, migrate, layouter, stats]
advertise_url: http://central-a.example.com
api_auth:
login: admin
password: senha-do-operador
A segunda é a mesma, sem o papel migrate e com seu próprio endereço:
central:
database_url: postgres://central:senha@db.example.com:5432/central
admin_keys:
- chave-de-gestao
roles: [run, layouter, stats]
advertise_url: http://central-b.example.com
Papéis são declarações, não atribuições¶
Um papel na configuração significa «esta máquina está pronta para fazer este trabalho», não «esta máquina o faz». Qual instância realmente faz o trabalho é decidido pelo PostgreSQL e não pela configuração — por isso layouter e stats são declarados pelas duas, e isso não é erro nem partida dupla.
run— servir requisições: o console, a API de gestão, a recepção da sincronização dos streamers, a exportação de métricas. Cada instância precisa dele.migrate— aplicar as migrações do esquema na partida.layouter— executar as passagens da alocação.stats— manter a imagem do «agora mesmo» de todo o cluster.
O único papel que não se pode deixar em todas é migrate. Ele não é protegido por um mandato: dois processos que partam ao mesmo tempo lançarão as migrações em disputa. Por isso o esquema é aplicado por uma instância e as demais partem depois dela.
É também a razão para não deixar roles vazio na segunda instância: uma lista vazia não significa «nenhum papel», e sim os quatro, migrate incluído.
O endereço anunciado¶
advertise_url é o endereço pelo qual os vizinhos do grupo alcançam esta máquina. Ele é necessário porque a imagem do «agora mesmo» é mantida por uma instância enquanto as demais chegam a ela pela rede: o titular anota seu endereço e os vizinhos o leem de lá.
O endereço de um balanceador não serve aqui — levaria o vizinho de volta a si mesmo. O endereço tem de ser o de uma máquina específica.
O ajuste pode ser omitido: uma instância sem endereço anunciado funciona por completo e até pode manter a imagem, mas os vizinhos não chegarão a ela e dirão isso no log. No console uma linha assim fica marcada; ver a verificação após a implantação.
Licença¶
A licença é necessária a cada processo do central, não uma por grupo: sem ela o processo nem parte. A chave e o produto declarado são os mesmos em todas as instâncias.
Quem faz o quê: os mandatos¶
O trabalho cujo duplicado seria nocivo é feito por uma única instância do grupo: a que tomou o mandato correspondente. O mandato vive no PostgreSQL e é emitido numa conexão própria, de modo que a morte do processo o libera sozinha, sem timeouts nem análise de executores travados: se a sessão morreu, o mandato está livre.
Os mandatos são vários e são independentes. O central não tem um líder único: layouter e stats podem acabar em máquinas diferentes, e isso é um estado normal, não um desequilíbrio.
Cada emissão leva um número — a época. Ela cresce a cada troca de titular e viaja com cada escrita: uma instância que acorda de uma pausa já sem ser a titular recebe uma recusa na escrita, em vez de estragar a alocação depois do fato. É isso que torna a mudança de um mandato segura e sem confirmação manual.
A troca de titular leva segundos — o que o PostgreSQL precisa para notar a sessão morta e o vizinho para vir buscar o mandato liberado.
Uma instância que não tem mandato algum não é reserva nem está dormindo: ela serve por completo o console, a API e a sincronização dos streamers. O mandato diz respeito apenas ao trabalho de fundo.
A configuração de um streamer¶
O streamer se dirige ao grupo, não a um processo, então sua configuração leva uma lista de endereços:
managed_by:
name: streamer-01
url:
- http://central-a.example.com
- http://central-b.example.com
join_token: token-de-adesao
A ordem da lista é uma preferência de partida, não uma vinculação permanente. O streamer fica no endereço atual enquanto ele responder e passa ao seguinte após uma requisição malsucedida. Ele não volta por conta própria: enquanto o novo endereço responder não há nada a ganhar trocando-o, e alternar por igualdade só espalharia a máquina pelo grupo.
O segundo endereço é obrigatório, não desejável. Uma interrupção do laço de sincronização é o único sinal de vida de um streamer que o central tem. Um streamer que fique com um único endereço morto consta como offline um minuto e meio depois, e então o layouter move honestamente seus streams para outra máquina — de uma viva e transmitindo. A morte de uma instância de gestão vira a mudança de metade do ar.
Convém dividir a lista pelas metades do parque: dar a uma metade a primeira instância como primeiro endereço e à outra a segunda. Em estado tranquilo a carga de sincronização fica distribuída e, ao morrer qualquer uma das instâncias, só a metade dela se muda.
O ponto de entrada do operador¶
O operador precisa de um único endereço que encontre sozinho uma instância viva: um nome DNS com comutação ou um balanceador diante do grupo. Um manipulador de requisições não guarda estado próprio, então qualquer instância pode responder à requisição de um operador.
Os streamers não devem passar por esse ponto de entrada: eles têm a própria lista de endereços, e um intermediário a mais no caminho da sincronização só acrescenta um ponto de falha.
Ordem de implantação¶
- Subir o PostgreSQL e criar o banco.
- Iniciar a primeira instância — a que tem o papel
migrate. Esperar até que ela responda às requisições: o esquema é aplicado antes de ela ficar pronta. - Iniciar as demais instâncias.
- Abrir a janela de adesão e subir os streamers, dando a cada um a lista de endereços do grupo.
- Apontar o ponto de entrada do operador para o grupo.
O pacote nas máquinas das instâncias é o catena-base, o mesmo que os streamers recebem: a pergunta de instalação sobre um PostgreSQL existente é respondida com o endereço do banco compartilhado, enquanto os papéis e o endereço anunciado vêm da configuração acima. O pacote catena não serve aqui — ele monta o banco na própria máquina, e um grupo precisa dele separado das instâncias.
A ordem só importa no primeiro passo: as demais instâncias não subirão antes do esquema, e os streamers não aderirão antes de haver um central vivo.
O que verificar após a implantação¶
Tudo o que vale olhar está no console, na seção Cluster → Central.
- A tabela tem tantas linhas quantas instâncias. Uma linha aparece segundos após uma partida. Se não aparecer, a instância não chegou ao banco.
- Cada linha tem o «Endereço anunciado» preenchido. A marca «não anunciado» significa que os vizinhos não chegarão a essa instância: falta-lhe
advertise_url. - A coluna «Papéis reivindicados» mostra os papéis declarados. Garanta que
migrateesteja declarado em exatamente uma. - A coluna «Mandatos detidos» não está vazia em pelo menos uma instância. Vazia em todas significa que nenhuma declarou os papéis
layouterestats, e o grupo não tem nem alocação nem imagem do «agora mesmo». - A coluna «Compilação» é a mesma em todas as linhas. Versões diferentes num grupo são um estado normal apenas enquanto durar uma atualização.
- A seção «Streamers» mostra todo o parque a partir de qualquer instância. Metade do parque visível num endereço e a outra metade em outro significa que as instâncias não veem a imagem uma da outra: revise
advertise_url.
Não é preciso testar a comutação à mão, e não convém fazê-lo numa instalação em serviço — para isso existe o laboratório, sobre um banco descartável.
O que este arranjo não faz¶
- Não torna o banco redundante. A tolerância a falhas do PostgreSQL é tarefa do próprio banco: uma réplica com comutação ou uma instância gerenciada de um provedor.
- Não substitui backups. A reserva protege da perda de uma máquina, não de uma exclusão por engano — ver Backup e restauração.
- Não toca o ar. Os streams transmitem e gravam o arquivo sem o central; só a gestão é tornada redundante, ver Autonomia do streamer.