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

Video relacionado no YouTube
Video1. Ambiente utilizado
Na minha instalação:
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.7O 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:
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:
cat /etc/os-release
cat /etc/openwrt_release
uname -a
uname -m
command -v opkg
command -v apk
opkg print-architecture
df -hNo meu Flint obtive um sistema:
OpenWrt 23.05-SNAPSHOT
aarch64
e opkg como gestor de pacotes.
Também verifiquei que ferramentas estavam disponíveis:
command -v ar
command -v tar
command -v gzip
command -v xz
command -v wget
command -v curl
command -v mount
command -v chrootE, em especial, se o OpenWrt já disponibilizava o Corosync:
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:
OpenWrt
└── /opt/debian-qnetd
└── Debian 12 ARM64
└── corosync-qnetdOu 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:
command -v debootstrap
debootstrap --versionE 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:
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:
ar p "$DEB" data.tar.xz |
xz -dc |
tar -xf - -C "$BASE"A chave fica disponível em:
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:
PATH="$BASE/bin:$PATH" \
debootstrap \
--arch=arm64 \
--variant=minbase \
--keyring="$KEY" \
bookworm \
"$TARGET" \
https://deb.debian.org/debianIsto 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:
chroot "$TARGET" \
/usr/bin/apt-cache policy corosync-qnetdNo 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:
chroot "$TARGET" \
/usr/bin/apt-get --no-remove -y --fix-broken installDepois instalei:
chroot "$TARGET" \
/usr/bin/apt-get install -y \
--no-install-recommends \
corosync-qnetd \
libnss3-toolsEntre 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:
mount -o bind \
/proc \
/opt/debian-qnetd/procE:
mount -o bind \
/dev/pts \
/opt/debian-qnetd/dev/ptsIsto 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:
chroot /opt/debian-qnetd \
/usr/bin/corosync-qnetd-certutil \
-iVista a partir do OpenWrt, a base de dados NSS fica em:
/opt/debian-qnetd/etc/corosync/qnetd/nssdb
Podemos verificé-la com:
ls -lah \
/opt/debian-qnetd/etc/corosync/qnetd/nssdbDentro 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:
DB="/opt/debian-qnetd/etc/corosync/qnetd/nssdb"
ls -ln "$DB"No meu caso, tive de ajustar:
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:
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 reqOs 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:
chroot /opt/debian-qnetd \
/usr/bin/corosync-qnetd \
-h13. 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:
/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:
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
}
EOFDefinimos 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:
ubus call service list \
'{"name":"qnetd-debian"}'Um estado correto contém:
"running": true
No meu caso, também podíamos ver:
/usr/bin/corosync-qnetd
-f
-4
-l 192.168.1.1
-p 5403
-s req16. 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:
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:
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:
scp \
root@192.168.1.1:/opt/debian-qnetd/etc/corosync/qnetd/nssdb/qnetd-cacert.crt \
/root/qnetd-migration/qnetd-cacert.crtImportamos a CA:
certutil -A \
-d "sql:$DB" \
-n "QNet CA" \
-t "CT,c,c" \
-i "$DIR/qnetd-cacert.crt" \
-f "$PASS"Verificamos:
certutil -L \
-d "sql:$DB" \
-f "$PASS"Deveremos ver:
QNet CA CT,c,c
21. Criar o CSR do cluster
Geramos alguma entropia:
dd if=/dev/urandom \
of="$DIR/noise-new.txt" \
bs=1024 \
count=1 \
status=noneCriamos o CSR:
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:
scp \
"$CSR" \
root@192.168.1.1:/opt/debian-qnetd/tmp/hectormox.crqVoltamos a ligar-nos ao Flint:
ssh root@192.168.1.1
E assinamos:
chroot /opt/debian-qnetd \
/usr/bin/corosync-qnetd-certutil \
-s \
-c /tmp/hectormox.crq \
-n hectormoxO certificado assinado fica em:
/opt/debian-qnetd/etc/corosync/qnetd/nssdb/cluster-hectormox.crt
23. Recuperar o certificado assinado
A partir do miniproxmox:
scp \
root@192.168.1.1:/opt/debian-qnetd/etc/corosync/qnetd/nssdb/cluster-hectormox.crt \
/root/qnetd-migration/cluster-hectormox.crtPodemos convertê-lo para PEM:
cd /root/qnetd-migration
openssl x509 \
-inform DER \
-in cluster-hectormox.crt \
-out cluster-hectormox.pemE verificé-lo:
openssl verify \
-CAfile qnetd-cacert.crt \
cluster-hectormox.pemO resultado correto é:
OK
24. Importar o certificado do cluster
Adicionamos o certificado assinado é NSS:
certutil -A \
-d "sql:$DB" \
-n "Cluster Cert" \
-t "u,u,u" \
-i "$DIR/cluster-hectormox.crt" \
-f "$PASS"Verificamos:
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:
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é:
scp \
/root/qnetd-migration/qnetd-cacert.crt \
root@192.168.1.7:/root/qnetd-migration/E:
scp \
/root/qnetd-migration/qdevice-net-node.p12 \
root@192.168.1.7:/root/qnetd-migration/No zimaproxmox:
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:
certutil -A \
-d "sql:$DB" \
-n "QNet CA" \
-t "CT,c,c" \
-i "$CA" \
-f "$PASS"Importamos o PKCS#12:
pk12util \
-i "$P12" \
-d "sql:$DB" \
-k "$PASS" \
-W ""O resultado correto é:
PKCS12 IMPORT SUCCESSFUL
E verificamos:
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é:
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:
certutil -L \
-d "sql:$READY" \
-f "$READY/pwdfile.txt"E podemos confirmar a identidade:
certutil -L \
-d "sql:$READY" \
-n "Cluster Cert" \
-a |
openssl x509 \
-noout \
-subject \
-issuerNo 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:
ACTIVE="/etc/corosync/qdevice/net/nssdb"
BACKUP="${ACTIVE}.pre-glinet-$(date +%Y%m%d-%H%M%S)"
mv "$ACTIVE" "$BACKUP"Copiamos a nova:
cp -a \
/root/qnetd-migration/nssdb-ready \
"$ACTIVE"Ajustamos as permissóes:
chown -R root:root "$ACTIVE"
chmod 700 "$ACTIVE"
chmod 600 "$ACTIVE"/*Verificamos:
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:
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:
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:
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:
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-debianVoltamos a iniciar o serviéo:
"$SERVICE" start
Verificamos a integridade:
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:
scp -O `
root@192.168.1.1:/overlay/qnetd-backup-completo-XXXXXXXX.tar.gz `
"$env:USERPROFILE\Downloads\"Depois calculamos o hash:
Get-FileHash `
"$env:USERPROFILE\Downloads\qnetd-backup-completo-XXXXXXXX.tar.gz" `
-Algorithm SHA256O 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:
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:
netstat -lntp 2>/dev/null |
grep 5403Revimos 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:
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:
wc -l /etc/init.d/qnetd-debian
cat /etc/init.d/qnetd-debianDepois:
/etc/init.d/qnetd-debian enabled
Procuramos o processo:
pidof corosync-qnetd
Porta:
netstat -lntp 2>/dev/null |
grep 5403Estado no procd:
ubus call service list \
'{"name":"qnetd-debian"}'E, se quisermos testar o QNetd fora do procd:
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:
systemctl is-active corosync
systemctl is-active corosync-qdeviceDepois:
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:
chroot /opt/debian-qnetd \
id coroqnetdDiretó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:
chroot /opt/debian-qnetd \
/usr/bin/corosync-qnetd \
-hconfig_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:
OpenWrt
└── Debian 12 ARM64 em chroot
└── corosync-qnetdQNetd:
192.168.1.1:5403
TLS
procd
reinécio automético
arranque automético
E o cluster:
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:
- GL.iNet GL-BE9300 Flint 3 — Analisado no video: AliExpress España · AliExpress desde Europa · AliExpress Oficial GL.iNet · Amazon


