Mascote do HectorziN
Blog do HectorziN

Como transformar um GL.iNet Flint 3 com OpenWrt em QNetd para um cluster Proxmox

Num cluster Proxmox formado por dois nós, existe um problema bastante conhecido: para manter o quorum, temos de evitar situações em que cada né tenha exatamente metade dos votos. Uma solução habitual consiste em adicionar um QDevice, que utiliza um terceiro equipamento independente a executar QNetd para funcionar como árbitro. No meu caso, já tinha um QDevice a funcionar, mas o QNetd estava alojado noutra máquina. Queria eliminar essa dependência e aproveitar um dispositivo que está praticamente sempre ligado e que, além disso, é fisicamente independente dos servidores Proxmox: o meu router GL.iNet Flint 3 (GL-BE9300). O problema é que o Flint 3 utiliza OpenWrt, não Debian, e os repositórios disponíveis no meu firmware não incluem corosync-qnetd. Importante: este guia documenta exatamente a solução que utilizei na minha instalação. O OpenWrt, a GL.iNet, o Debian, o Corosync e o Proxmox evoluem, pelo que convém verificar versões, caminhos e parâmetros antes de os copiar literalmente.

No YouTube compartilho mais tutoriais, testes praticos e automacao residencial real. Inscrever-se no YouTube

GL.iNet Flint 3 com OpenWrt a executar QNetd para um cluster Proxmox

Video relacionado no YouTube

Video

1. Ambiente utilizado

Na minha instalação:

Código
Router:
GL.iNet Flint 3 / GL-BE9300
IP: 192.168.1.1
OpenWrt 23.05-SNAPSHOT
Arquitetura ARM64

Cluster:
Nome: hectormox

Nó 1:
miniproxmox
192.168.1.6

Nó 2:
zimaproxmox
192.168.1.7

O Debian mínimo ficou instalado em:

/opt/debian-qnetd

O QNetd escuta na porta padrão:

TCP 5403

2. Ligar ao Flint 3 por SSH

No Windows, podemos utilizar diretamente o cliente SSH incluído no PowerShell:

ssh root@192.168.1.1

Introduzimos a palavra-passe de administração do router.

Depois de entrar, veremos algo semelhante a:

Código
BusyBox
OpenWrt
root@GL-BE9300:~#

Antes de instalar seja o que for, vale a pena descobrir o que temos realmente.

3. Verificar o sistema, a arquitetura, os pacotes e o espaço disponível

Executamos:

bash
cat /etc/os-release
cat /etc/openwrt_release

uname -a
uname -m

command -v opkg
command -v apk

opkg print-architecture

df -h

No meu Flint obtive um sistema:

OpenWrt 23.05-SNAPSHOT

aarch64

e opkg como gestor de pacotes.

Também verifiquei que ferramentas estavam disponíveis:

bash
command -v ar
command -v tar
command -v gzip
command -v xz
command -v wget
command -v curl
command -v mount
command -v chroot

E, em especial, se o OpenWrt já disponibilizava o Corosync:

bash
opkg update
opkg list | grep -Ei 'corosync|qnetd|qdevice|libnss|libqb'

No meu firmware não estava disponível corosync-qnetd.

Por isso, não podíamos simplesmente executar:

opkg install corosync-qnetd

como faríamos com um pacote nativo do OpenWrt.

4. Porquê utilizar um Debian mínimo dentro do OpenWrt

Em vez de tentar compilar o Corosync e todas as respetivas dependências diretamente para o OpenWrt, optei por uma solução bastante mais simples:

criar um Debian ARM64 mínimo numa pasta e executar o QNetd através de chroot.

O OpenWrt continua a ser o sistema operativo do router. Não instalamos outro kernel, não virtualizamos nada nem substituímos o firmware.

A estrutura é simplesmente:

Código
OpenWrt
└── /opt/debian-qnetd
    └── Debian 12 ARM64
        └── corosync-qnetd

Ou seja, o Flint continua a funcionar como router OpenWrt, mas dispõe de um pequeno ambiente Debian a partir do qual podemos executar software que não existe nos respetivos repositórios.

5. Instalar o debootstrap no Flint

Começamos por atualizar os índices:

opkg update

Instalamos o debootstrap:

opkg install debootstrap

Verificamos se está disponível:

bash
command -v debootstrap
debootstrap --version

E verificamos o espaço disponível:

df -h /overlay

No meu caso, tinha vários gigabytes livres, suficientes para um Debian mínimo.

6. Problema com o GPG e o Debian Bookworm

Foi aqui que surgiu um dos primeiros problemas específicos da minha versão do OpenWrt.

debootstrap tem de verificar as assinaturas dos repositórios Debian, mas o gpgv inicialmente disponível no router era demasiado antigo para algumas assinaturas utilizadas pelo Bookworm.

A solução foi instalar:

opkg install gpgv2

Podemos verificar com:

gpgv2 --version

Também precisamos das chaves oficiais do Debian.

Preparamos um diretório temporário:

bash
BASE="/tmp/qnetd-bootstrap"

mkdir -p "$BASE"
mkdir -p "$BASE/bin"

Transferimos o pacote debian-archive-keyring correspondente ao Debian Bookworm.

Convém verificar qual é a versão atual do pacote quando consultar este guia, em vez de manter permanentemente um URL específico.

Depois de transferido:

DEB="$BASE/debian-archive-keyring.deb"

Extraímos o conteúdo:

bash
ar p "$DEB" data.tar.xz |
    xz -dc |
    tar -xf - -C "$BASE"

A chave fica disponível em:

bash
KEY="$BASE/usr/share/keyrings/debian-archive-keyring.gpg"
ls -l "$KEY"

Para garantir que o debootstrap utiliza o gpgv2, criamos uma pequena substituição temporária:

ln -sf /usr/bin/gpgv2 "$BASE/bin/gpgv"

Isto só afeta o PATH que vamos utilizar ao executar o debootstrap.

7. Criar Debian 12 ARM64 minbase

Definimos onde queremos instalá-lo-lo:

TARGET="/opt/debian-qnetd"

Executamos:

bash
PATH="$BASE/bin:$PATH" \
debootstrap \
    --arch=arm64 \
    --variant=minbase \
    --keyring="$KEY" \
    bookworm \
    "$TARGET" \
    https://deb.debian.org/debian

Isto transfere e instala um Debian 12 mínimo em:

/opt/debian-qnetd

Podemos verificar o conteúdo:

ls -la /opt/debian-qnetd

E entrar manualmente:

chroot /opt/debian-qnetd /bin/bash

Para regressar ao OpenWrt:

exit

8. Atualizar o Debian e instalar o QNetd

A partir do próprio OpenWrt, podemos executar diretamente comandos dentro do chroot:

chroot "$TARGET" /usr/bin/apt-get update

Antes de instalar, verificamos se o pacote está disponível:

bash
chroot "$TARGET" \
    /usr/bin/apt-cache policy corosync-qnetd

No meu caso, o Debian disponibilizava:

corosync-qnetd 3.0.3-1

A instalação inicial encontrou algumas dependências em falta no ambiente minbase.

Primeiro reparei a base de pacotes com:

bash
chroot "$TARGET" \
    /usr/bin/apt-get --no-remove -y --fix-broken install

Depois instalei:

bash
chroot "$TARGET" \
    /usr/bin/apt-get install -y \
    --no-install-recommends \
    corosync-qnetd \
    libnss3-tools

Entre as dependências que o Debian acabou por instalar estavam bibliotecas NSS, Perl, netbase e outros pacotes necessários.

9. /proc e /dev/pts durante a instalação

Durante a instalação surgiram alguns avisos relacionados com /proc e /dev/pts.

Montei temporariamente:

bash
mount -o bind \
    /proc \
    /opt/debian-qnetd/proc

E:

bash
mount -o bind \
    /dev/pts \
    /opt/debian-qnetd/dev/pts

Isto ajudou-nos durante a preparação do Debian.

Mais tarde, verificámos que o QNetd não precisa destas montagens bind para funcionar normalmente, pelo que não fazem parte do serviéo definitivo.

10. Inicializar os certificados do QNetd

O QNetd utiliza uma base de dados NSS para gerir os certificados.

No nosso Debian temos o utilitário:

corosync-qnetd-certutil

Inicializamo-la a partir do OpenWrt:

bash
chroot /opt/debian-qnetd \
    /usr/bin/corosync-qnetd-certutil \
    -i

Vista a partir do OpenWrt, a base de dados NSS fica em:

/opt/debian-qnetd/etc/corosync/qnetd/nssdb

Podemos verificé-la com:

bash
ls -lah \
    /opt/debian-qnetd/etc/corosync/qnetd/nssdb

Dentro do chroot, o mesmo caminho é:

/etc/corosync/qnetd/nssdb

A CA pública fica em:

/opt/debian-qnetd/etc/corosync/qnetd/nssdb/qnetd-cacert.crt

11. Verificar o utilizador coroqnetd

O pacote Debian cria um utilizador específico para executar o QNetd.

Verificamos os respetivos identificadores:

chroot /opt/debian-qnetd id coroqnetd

Na minha instalação obtive:

UID 100

GID 101

Isto é importante porque mais é frente vou executar o QNetd com:

--userspec=100:101

Estes números não devem ser copiados sem serem verificados primeiro.

Cada instalação deve executar:

chroot /opt/debian-qnetd id coroqnetd

e utilizar os valores obtidos.

Também verificamos as permissóes da base de dados NSS:

bash
DB="/opt/debian-qnetd/etc/corosync/qnetd/nssdb"
ls -ln "$DB"

No meu caso, tive de ajustar:

bash
chgrp 101 \
    "$DB/pwdfile.txt" \
    "$DB/pkcs11.txt"

chmod 640 \
    "$DB/pwdfile.txt" \
    "$DB/pkcs11.txt"

Também no meu caso, 101 era o GID específico da instalação.

12. Testar o QNetd manualmente

Antes de o transformar num serviéo, é importante confirmar que o daemon arranca realmente.

Testei:

bash
timeout -s TERM 10 \
    chroot --userspec=100:101 \
    /opt/debian-qnetd \
    /usr/bin/corosync-qnetd \
    -f \
    -4 \
    -l 192.168.1.1 \
    -p 5403 \
    -s req

Os parâmetros utilizados são:

  • -f: executá-lo em primeiro plano.
  • -4: utilizar IPv4.
  • -l 192.168.1.1: endereéo em que o QNetd fica à escuta.
  • -p 5403: porta.
  • -s req: exigir TLS na versão que utilizamos.

Antes de copiar as opções, convém consultar a ajuda da versão instalada:

bash
chroot /opt/debian-qnetd \
    /usr/bin/corosync-qnetd \
    -h

13. O problema de LD_PRELOAD do OpenWrt

Ao executar programas Debian a partir do OpenWrt, surgiram avisos relacionados com uma variável do firmware chamada LD_PRELOAD.

Para evitar que o processo do chroot herdasse variáveis próprias do OpenWrt, acabei por o executar num ambiente limpo:

bash
/usr/bin/env -i \
    PATH=/usr/sbin:/usr/bin:/sbin:/bin \
    ...

Este detalhe passou a fazer parte do serviéo definitivo.

14. Criar o serviéo QNetd no OpenWrt

Esta é uma das diferenças mais importantes em relaééo a um Debian normal.

No Debian utilizaríamos o systemd.

No OpenWrt utilizamos o procd e scripts em:

/etc/init.d/

Criamos o ficheiro:

bash
cat > /etc/init.d/qnetd-debian <<'EOF'
#!/bin/sh /etc/rc.common

USE_PROCD=1
START=98
STOP=10

start_service() {
    procd_open_instance

    procd_set_param command \
        /usr/bin/env -i \
        PATH=/usr/sbin:/usr/bin:/sbin:/bin \
        /usr/sbin/chroot --userspec=100:101 \
        /opt/debian-qnetd \
        /usr/bin/corosync-qnetd \
        -f -4 -l 192.168.1.1 -p 5403 -s req

    procd_set_param respawn 3600 5 5
    procd_set_param stdout 1
    procd_set_param stderr 1

    procd_close_instance
}
EOF

Definimos as permissóes:

chmod 755 /etc/init.d/qnetd-debian

Ativamos o arranque automético:

/etc/init.d/qnetd-debian enable

Podemos verificar as ligações criadas:

ls -l /etc/rc.d/*qnetd*

No meu Flint ficaram:

/etc/rc.d/S98qnetd-debian

/etc/rc.d/K10qnetd-debian

Iniciamos o serviéo:

/etc/init.d/qnetd-debian start

15. Verificar se o QNetd está a funcionar

Começamos por procurar o processo:

pidof corosync-qnetd

Depois verificamos a porta:

netstat -lntp 2>/dev/null | grep 5403

Deveremos ver:

192.168.1.1:5403 LISTEN

Também podemos verificar o processo completo:

ps w | grep '[c]orosync-qnetd'

E consultamos diretamente o procd:

bash
ubus call service list \
    '{"name":"qnetd-debian"}'

Um estado correto contém:

"running": true

No meu caso, também podíamos ver:

Código
/usr/bin/corosync-qnetd
-f
-4
-l 192.168.1.1
-p 5403
-s req

16. Verificar o reinécio automético do processo

O serviéo inclui:

procd_set_param respawn 3600 5 5

Isto permite ao procd voltar a iniciar o QNetd se o processo terminar inesperadamente.

Durante os testes, terminámos o processo manualmente e confirmámos que reaparecia com outro PID e voltava a escutar em:

192.168.1.1:5403

17. Preparar o Proxmox

Passamos agora ao primeiro né do cluster:

ssh root@192.168.1.6

Verificamos o estado atual:

pvecm status

E:

corosync-qdevice-tool -s

O meu cluster chama-se:

hectormox

Anteriormente, tinha outro QNetd em:

192.168.1.5:5403

O novo ficará em:

192.168.1.1:5403

18. Fazer uma cépia de seguranéa antes de alterar o QDevice

Antes de mexer nos certificados, fiz uma cépia de seguranéa de:

/etc/corosync/qdevice

/etc/pve/corosync.conf

Por exemplo:

bash
BACKUP="/root/qdevice-backup-$(hostname)-$(date +%Y%m%d-%H%M%S).tar.gz"

tar -czf "$BACKUP" \
    -C / \
    etc/corosync/qdevice \
    etc/pve/corosync.conf

sha256sum "$BACKUP"

ls -lh "$BACKUP"

Não recomendo continuar sem esta cépia de seguranéa.

19. Criar uma nova base de dados NSS no Proxmox

No miniproxmox:

bash
DIR="/root/qnetd-migration"
DB="$DIR/nssdb-new"
PASS="$DIR/pwdfile-new.txt"

mkdir -p "$DIR"
mkdir -m 700 "$DB"

: > "$PASS"
chmod 600 "$PASS"

Inicializamos NSS:

certutil -N \
    -d "sql:$DB" \
    -f "$PASS"

20. Copiar a CA do Flint para o Proxmox

A partir do miniproxmox:

bash
scp \
    root@192.168.1.1:/opt/debian-qnetd/etc/corosync/qnetd/nssdb/qnetd-cacert.crt \
    /root/qnetd-migration/qnetd-cacert.crt

Importamos a CA:

bash
certutil -A \
    -d "sql:$DB" \
    -n "QNet CA" \
    -t "CT,c,c" \
    -i "$DIR/qnetd-cacert.crt" \
    -f "$PASS"

Verificamos:

bash
certutil -L \
    -d "sql:$DB" \
    -f "$PASS"

Deveremos ver:

QNet CA CT,c,c

21. Criar o CSR do cluster

Geramos alguma entropia:

bash
dd if=/dev/urandom \
    of="$DIR/noise-new.txt" \
    bs=1024 \
    count=1 \
    status=none

Criamos o CSR:

bash
CSR="$DIR/qdevice-net-node.crq"
certutil -R \
    -d "sql:$DB" \
    -f "$PASS" \
    -z "$DIR/noise-new.txt" \
    -s "CN=hectormox" \
    -g 3072 \
    -o "$CSR"

é necessório substituir:

hectormox

pelo nome real do cluster.

Podemos verificé-lo com:

pvecm status

22. Enviar o CSR para o Flint

A partir do Proxmox:

bash
scp \
    "$CSR" \
    root@192.168.1.1:/opt/debian-qnetd/tmp/hectormox.crq

Voltamos a ligar-nos ao Flint:

ssh root@192.168.1.1

E assinamos:

bash
chroot /opt/debian-qnetd \
    /usr/bin/corosync-qnetd-certutil \
    -s \
    -c /tmp/hectormox.crq \
    -n hectormox

O certificado assinado fica em:

/opt/debian-qnetd/etc/corosync/qnetd/nssdb/cluster-hectormox.crt

23. Recuperar o certificado assinado

A partir do miniproxmox:

bash
scp \
    root@192.168.1.1:/opt/debian-qnetd/etc/corosync/qnetd/nssdb/cluster-hectormox.crt \
    /root/qnetd-migration/cluster-hectormox.crt

Podemos convertê-lo para PEM:

bash
cd /root/qnetd-migration

openssl x509 \
    -inform DER \
    -in cluster-hectormox.crt \
    -out cluster-hectormox.pem

E verificé-lo:

bash
openssl verify \
    -CAfile qnetd-cacert.crt \
    cluster-hectormox.pem

O resultado correto é:

OK

24. Importar o certificado do cluster

Adicionamos o certificado assinado é NSS:

bash
certutil -A \
    -d "sql:$DB" \
    -n "Cluster Cert" \
    -t "u,u,u" \
    -i "$DIR/cluster-hectormox.crt" \
    -f "$PASS"

Verificamos:

bash
certutil -L \
    -d "sql:$DB" \
    -f "$PASS"

Agora deverão aparecer:

QNet CA CT,c,c

Cluster Cert u,u,u

25. Exportar o certificado e a chave privada para PKCS#12

Geramos:

bash
pk12util \
    -o "$DIR/qdevice-net-node.p12" \
    -d "sql:$DB" \
    -k "$PASS" \
    -W "" \
    -n "Cluster Cert"

Resultado esperado:

PKCS12 EXPORT SUCCESSFUL

Este ficheiro contém uma chave privada. Não deve ser publicado nem partilhado.

26. Preparar o segundo né Proxmox

Copiamos para o segundo né:

bash
scp \
    /root/qnetd-migration/qnetd-cacert.crt \
    root@192.168.1.7:/root/qnetd-migration/

E:

bash
scp \
    /root/qnetd-migration/qdevice-net-node.p12 \
    root@192.168.1.7:/root/qnetd-migration/

No zimaproxmox:

bash
DIR="/root/qnetd-migration"
DB="$DIR/nssdb-new"
PASS="$DIR/pwdfile-new.txt"
CA="$DIR/qnetd-cacert.crt"
P12="$DIR/qdevice-net-node.p12"

mkdir -m 700 "$DB"

: > "$PASS"
chmod 600 "$PASS"

certutil -N \
    -d "sql:$DB" \
    -f "$PASS"

Importamos a CA:

bash
certutil -A \
    -d "sql:$DB" \
    -n "QNet CA" \
    -t "CT,c,c" \
    -i "$CA" \
    -f "$PASS"

Importamos o PKCS#12:

bash
pk12util \
    -i "$P12" \
    -d "sql:$DB" \
    -k "$PASS" \
    -W ""

O resultado correto é:

PKCS12 IMPORT SUCCESSFUL

E verificamos:

bash
certutil -L \
    -d "sql:$DB" \
    -f "$PASS"

27. Preparar uma base de dados NSS definitiva

Antes de alterar a base de dados realmente utilizada pelo QDevice, preparei outra pasta:

/root/qnetd-migration/nssdb-ready

Em cada né:

bash
DIR="/root/qnetd-migration"
READY="$DIR/nssdb-ready"

mkdir -m 700 "$READY"

cp -a \
    "$DIR/nssdb-new/." \
    "$READY/"

install -m 600 \
    "$DIR/pwdfile-new.txt" \
    "$READY/pwdfile.txt"

Verificamos:

bash
certutil -L \
    -d "sql:$READY" \
    -f "$READY/pwdfile.txt"

E podemos confirmar a identidade:

bash
certutil -L \
    -d "sql:$READY" \
    -n "Cluster Cert" \
    -a |
openssl x509 \
    -noout \
    -subject \
    -issuer

No meu caso:

subject=CN=hectormox

issuer=CN=QNet CA

28. Substituir as credenciais ativas

Realizámos este passo né a né.

Paramos apenas o QDevice:

systemctl stop corosync-qdevice

Não paramos o Corosync.

Guardamos uma cépia da base de dados antiga:

bash
ACTIVE="/etc/corosync/qdevice/net/nssdb"
BACKUP="${ACTIVE}.pre-glinet-$(date +%Y%m%d-%H%M%S)"
mv "$ACTIVE" "$BACKUP"

Copiamos a nova:

bash
cp -a \
    /root/qnetd-migration/nssdb-ready \
    "$ACTIVE"

Ajustamos as permissóes:

bash
chown -R root:root "$ACTIVE"
chmod 700 "$ACTIVE"
chmod 600 "$ACTIVE"/*

Verificamos:

bash
certutil -L \
    -d "sql:$ACTIVE" \
    -f "$ACTIVE/pwdfile.txt"

E iniciamos o QDevice:

systemctl start corosync-qdevice

Repetimos o mesmo procedimento no outro né.

29. Alterar o IP do QNetd antigo

No meu caso, o QDevice já estava configurado para utilizar outro servidor:

192.168.1.5

e deveria passar para o Flint:

192.168.1.1

Antes disso, fiz outra cépia de seguranéa:

bash
cp \
    /etc/pve/corosync.conf \
    "/root/corosync-pre-glinet-$(date +%Y%m%d-%H%M%S).conf"

A alteraééo foi:

- host: 192.168.1.5

+ host: 192.168.1.1

Também aumentámos:

- config_version: 3

+ config_version: 4

O bloco correspondente ficou semelhante a:

bash
quorum {
  device {
    model: net
    net {
      algorithm: ffsplit
      host: 192.168.1.1
      tls: on
    }
    votes: 1
  }
}

Tenha em conta que o config_version deve ser incrementado em relaééo ao valor de cada instalação.

Não se deve copiar literalmente 3 → 4.

30. Reiniciar apenas o QDevice

Depois da alteraééo, o Corosync adotou a nova configuração, mas o processo QDevice continuou a utilizar o endereéo antigo até o reiniciarmos.

Executamos:

systemctl restart corosync-qdevice

Verificamos:

corosync-qdevice-tool -s

O resultado correto foi:

Cluster name: hectormox

QNetd host: 192.168.1.1:5403

Algorithm: Fifty-Fifty split

State: Connected

Repetimos o reinécio do QDevice no segundo né.

31. Verificar o quorum

Executamos:

pvecm status

No nosso caso, o resultado final foi:

Expected votes: 3 Highest expected: 3 Total votes: 3 Quorum: 2 Quorate: Yes

E nas informações dos membros:

0x00000001 1 A,V,NMW 192.168.1.6

0x00000002 1 A,V,NMW 192.168.1.7

0x00000000 1 Qdevice

Isto significa:

  • miniproxmox: 1 voto.
  • zimaproxmox: 1 voto.
  • QDevice/QNetd: 1 voto.

Total:

3 votos

O quorum necessório continua a ser:

2

32. Fazer uma cépia de seguranéa completa do QNetd do Flint

Depois de terminar tudo, fiz uma cépia de seguranéa completa do ambiente.

Definimos:

bash
SERVICE="/etc/init.d/qnetd-debian"
BACKUP="/overlay/qnetd-backup-completo-$(date +%Y%m%d-%H%M%S).tar.gz"

Paramos o QNetd por alguns instantes:

"$SERVICE" stop

Criamos a cépia de seguranéa:

bash
tar -czf "$BACKUP" \
    -C / \
    --exclude=opt/debian-qnetd/proc \
    --exclude=opt/debian-qnetd/dev/pts \
    --exclude=opt/debian-qnetd/run \
    --exclude=opt/debian-qnetd/tmp \
    opt/debian-qnetd \
    etc/init.d/qnetd-debian \
    etc/rc.d/S98qnetd-debian \
    etc/rc.d/K10qnetd-debian

Voltamos a iniciar o serviéo:

"$SERVICE" start

Verificamos a integridade:

bash
tar -tzf "$BACKUP" >/dev/null
sha256sum "$BACKUP"
ls -lh "$BACKUP"

A minha cépia final ocupava aproximadamente:

157 MB

33. Transferir a cépia de seguranéa para o Windows

A partir do PowerShell:

bash
scp -O `
    root@192.168.1.1:/overlay/qnetd-backup-completo-XXXXXXXX.tar.gz `
    "$env:USERPROFILE\Downloads\"

Depois calculamos o hash:

bash
Get-FileHash `
    "$env:USERPROFILE\Downloads\qnetd-backup-completo-XXXXXXXX.tar.gz" `
    -Algorithm SHA256

O valor tem de coincidir exatamente com o obtido anteriormente no Flint.

A cépia de seguranéa contém certificados e chaves privadas, pelo que deve ser guardada num local seguro.

34. Testar o sistema depois de reiniciar o Flint

Não queria considerar o projeto concluído apenas por funcionar depois de o iniciar manualmente.

Reiniciei o Flint 3 através da interface web.

Quando voltou a estar disponível, liguei-me novamente:

ssh root@192.168.1.1

Primeiro confirmei que o script continuava presente:

wc -l /etc/init.d/qnetd-debian

Depois:

pidof corosync-qnetd

Verifiquei a porta:

netstat -lntp 2>/dev/null | grep 5403

Y finalmente procd:

bash
ubus call service list \
    '{"name":"qnetd-debian"}'

No teste final obtive:

23 /etc/init.d/qnetd-debian

um PID válido:

28139

a porta:

192.168.1.1:5403 LISTEN

e:

"running": true

Isto demonstrou que o QNetd arrancou automaticamente depois do reinécio do router.

35. Verificar se o Proxmox volta a ligar-se automaticamente

No miniproxmox:

corosync-qdevice-tool -s

O estado voltou automaticamente a:

QNetd host: 192.168.1.1:5403 State: Connected

E:

pvecm status

voltou a apresentar:

Expected votes: 3

Total votes: 3

Quorum: 2

Quorate: Yes

Se reiniciarmos o Flint, os nós Proxmox perdem temporariamente o voto do QDevice; quando o QNetd volta a arrancar, os QDevice ligam-se novamente de forma automática.

36. Um problema curioso que encontrámos

Durante um dos testes aconteceu algo estranho.

O serviéo aparecia como ativado:

/etc/init.d/qnetd-debian enabled

mas o QNetd não estava a ser executado.

Verificámos:

pidof corosync-qnetd

Não era devolvido qualquer PID.

Também não havia nada é escuta:

bash
netstat -lntp 2>/dev/null |
    grep 5403

Revimos entéo o script:

wc -l /etc/init.d/qnetd-debian

E descobrimos:

0 /etc/init.d/qnetd-debian

O ficheiro tinha ficado vazio.

No entanto, continuavam a existir:

/etc/rc.d/S98qnetd-debian

/etc/rc.d/K10qnetd-debian

Por isso, o OpenWrt podia indicar que o serviéo estava ativado, apesar de não haver realmente nada para executar.

Reconstruímos o script e repetimos todo o teste após o reinécio.

Desde entéo, arrancou corretamente.

A conclusão é importante:

Não basta verificar se um serviéo está ativado.

Convém também verificar:

bash
pidof corosync-qnetd
netstat -lntp 2>/dev/null | grep 5403
ubus call service list \ '{"name":"qnetd-debian"}'

37. Diagnóstico répido se o QNetd não arrancar

Primeiro confirmamos que o script existe e tem conteúdo:

bash
wc -l /etc/init.d/qnetd-debian
cat /etc/init.d/qnetd-debian

Depois:

/etc/init.d/qnetd-debian enabled

Procuramos o processo:

pidof corosync-qnetd

Porta:

bash
netstat -lntp 2>/dev/null |
    grep 5403

Estado no procd:

bash
ubus call service list \
    '{"name":"qnetd-debian"}'

E, se quisermos testar o QNetd fora do procd:

bash
timeout 5 /usr/bin/env -i \
    PATH=/usr/sbin:/usr/bin:/sbin:/bin \
    /usr/sbin/chroot --userspec=100:101 \
    /opt/debian-qnetd \
    /usr/bin/corosync-qnetd \
    -f -4 \
    -l 192.168.1.1 \
    -p 5403 \
    -s req

echo "EXIT=$?"

Se devolver:

124

significa que o daemon ainda estava ativo quando o timeout o terminou.

Nesse caso, provavelmente temos um problema com o serviéo procd, não com o QNetd.

38. Diagnóstico répido a partir do Proxmox

Começamos por verificar os serviços:

bash
systemctl is-active corosync
systemctl is-active corosync-qdevice

Depois:

corosync-qdevice-tool -s

O resultado correto é:

State: Connected

E:

pvecm status

deve apresentar:

Total votes: 3

Quorate: Yes

Se aparecer:

Cannot initialize CMAP service

isso não significa necessariamente que o QNetd esteja com problemas.

Convém verificar primeiro:

systemctl is-active corosync

Durante os meus testes tivemos precisamente uma ocorrência deste tipo, que acabou por ser um problema independente do QNetd e relacionado com montagens NFS no anfitrião Proxmox.

39. Valores a adaptar à sua instalação

Não copie literalmente todos os valores deste guia.

Endereço do Flint

No meu caso:

192.168.1.1

Nós Proxmox

192.168.1.6

192.168.1.7

Nome do cluster

hectormox

Confirme com:

pvecm status

Arquitetura

O meu Flint é:

ARM64

mas devemos verificar com:

uname -m

UID e GID do coroqnetd

Na minha instalação:

100:101

Mas consulte:

bash
chroot /opt/debian-qnetd \
    id coroqnetd

Diretório do Debian

Escolhi:

/opt/debian-qnetd

Não é obrigatório.

Versão do Debian

Neste guia:

Debian 12 Bookworm

TLS

A minha versão utilizava:

-s req

é necessório verificar com:

bash
chroot /opt/debian-qnetd \
    /usr/bin/corosync-qnetd \
    -h

config_version

Não copie:

3 → 4

é necessório incrementar em um o valor atual no nosso corosync.conf.

40. Resultado final

Depois de concluir todo o processo, o Flint 3 fica a funcionar assim:

Código
OpenWrt
└── Debian 12 ARM64 em chroot
    └── corosync-qnetd

QNetd:

192.168.1.1:5403

TLS

procd

reinécio automético

arranque automético

E o cluster:

Código
miniproxmox  → QDevice ─┐
                         ├──→ Flint 3 / QNetd
zimaproxmox  → QDevice ─┘

Podemos verificar o resultado final com:

corosync-qdevice-tool -s

é:

QNetd host: 192.168.1.1:5403

State: Connected

E com:

pvecm status

obtemos:

Expected votes: 3

Total votes: 3

Quorum: 2

Quorate: Yes

O interessante desta solução é que não transformámos o Flint 3 num servidor Debian nem substituímos o OpenWrt.

O Flint continua a ser o nosso router OpenWrt.

Aproveitámos simplesmente um dispositivo ARM64 sempre ligado, com espaço de armazenamento suficiente e suporte para chroot, para criar um Debian mínimo dedicado é execução do QNetd.

Desta forma, podemos ter um terceiro voto fisicamente independente para um cluster Proxmox de dois nós, sem manter outro servidor ligado apenas para executar o árbitro.

Equipamento recomendado

Dispositivo usado neste projeto: GL.iNet GL-BE9300 Flint 3. Se voce precisar dele, aqui esta onde encontra-lo:

Video relacionado

CUPONS ALIEXPRESS