Ak sa chceme s OpenBaom posunúť do produkcie, mali by sme ho mať vysoko dostupné. Preto si dnes postavíme 3 nody, spojíme ich do clustra a využijeme funkcionalitu HAProxy a Keepalived.
Linux distribúciu, na ktorej bude bežať môj lab cluster, som si vybral Debian. Vy si samozrejme môžete zvoliť OS, ktorý preferujete vy. Ja nie som linuxák a keď som konfiguroval cluster na Debiane a na Rocky Linux, Debian mi prišiel jednoduchší.
Po-inštalačné úpravy OS
Tieto úpravy vykonáme na všetkých 3 budúcich nodeoch clustra.
Po základnej inštalácii Debianu,
- sa prihlásime účtom, ktorý sme vytvorili pri inštalačnom procese
- zmeníme uživateľa na root pomocou príkazu: su –
- pridáme účet, ktorý sme vytvorili pri inštalačnom procese, medzi sudoers príkazom: usermod -aG sudo <user>
- odhlásime sa a prihlásime sa znova účtom vytvoreným pri inštalačnom procese
- upravíme Debian source list tak, že zakomentujeme (# deb cdrom: …) cdrom ako source: sudo nano /etc/apt/source.list
- spustíme: sudo apt-get update
Inštalácia Openbao, Keepalived a HAProxy
Nainštalujeme si všetky potrebné balíky, pripravíme adresár a uživateľa pre openbao. V čase písanie tohto článku, bola posledná verzia openbaa 2.4.3. Vy si skontrolujte, ktorá verzia je aktuálna v čase vašej inštalácie a upravte curl a dpkg príkaz.
sudo apt-get install -y unzip curl gnupg2 keepalived haproxy sudo mkdir -p /etc/openbao sudo mkdir -p /opt/openbao/data sudo mkdir -p /var/log/openbao sudo useradd --system --home /etc/openbao --shell /bin/false openbao sudo chown -R openbao:openbao /opt/openbao /var/log/openbao /etc/openbao sudo curl -LO https://github.com/openbao/openbao/releases/download/v2.4.3/bao_2.4.3_linux_amd64.deb sudo dpkg -i bao_2.4.3_linux_amd64.deb
Funkčnosť openbaa overíme príkazom: bao version
Konfigurácia Openbao clustra
Kvôli prehľadu, si zapíšeme IP adresy, ktoré sme si zvolili pri inštalácii jednotlivých nodeov.
- bao01 – 10.100.1.41 – bao01.<domena>
- bao02 – 10.100.1.42 – bao02.<domena>
- bao03 – 10.100.1.43 – bao03.<domena>
- VIP – 10.100.1.44 – bao.<domena>
Na každom node budúceho clustra upravíme /etc/openbao/config.hcl nasledovne:
bao01
listener "tcp" {
address = "0.0.0.0:8200"
# cluster_address = "10.100.1.41:8201"
tls_disable = 1
}
storage "raft" {
path = "/opt/openbao/data"
node_id = "bao01"
}
api_addr = "http://10.100.1.41:8200"
cluster_addr = "http://10.100.1.41:8201"
ui = true
bao02
listener "tcp" {
address = "0.0.0.0:8200"
# cluster_address = "10.100.1.42:8201"
tls_disable = 1
}
storage "raft" {
path = "/opt/openbao/data"
node_id = "bao02"
}
api_addr = "http://10.100.1.42:8200"
cluster_addr = "http://10.100.1.42:8201"
ui = true
bao03
listener "tcp" {
address = "0.0.0.0:8200"
# cluster_address = "10.100.1.43:8201"
tls_disable = 1
}
storage "raft" {
path = "/opt/openbao/data"
node_id = "bao03"
}
api_addr = "http://10.100.1.43:8200"
cluster_addr = "http://10.100.1.43:8201"
ui = true
Rovnako na každom node upravíme konfiguráciu služby openbao príkazom /etc/systemd/system/openbao.service nasledovne:
[Unit] Description=Openbao Server After=network-online.target Wants=network-online.target [Service] User=openbao Group=openbao ExecStart=/usr/bin/bao server -config=/etc/openbao/config.hcl ExecReload=/bin/kill --signal HUP $MAINPID LimitNOFILE=65536 Restart=on-failure [Install] WantedBy=multi-user.target
Štart služby/servera openbao:
sudo systemctl daemon-reload sudo systemctl enable openbao sudo systemctl start openbao
Skontrolujeme, či je služba správne spustená: sudo systemctl status openbao
Premenná BAO_ADDR
Štandardne je hodnota premennej BAO_ADDR nastavena na https://127.0.0.1:8200. Keďže nemáme (zatiaľ) zapnuté TLS, musíme jej hodnotu zmeniť na http://127.0.0.1:8200.
export BAO_ADDR=http://127.0.0.1:8200
Ako chceme otestovať, či máme všetko správne, môžeme si vyvolať status servera openbao: bao status.
Výstup bude veľmi podobný tomuto:
cytroon@bao01:~$ export BAO_ADDR=http://127.0.0.1:8200 cytroon@bao01:~$ bao status Key Value --- ----- Seal Type shamir Initialized false Sealed true Total Shares 0 Threshold 0 Unseal Progress 0/0 Unseal Nonce n/a Version 2.4.3 Build Date 2025-10-22T20:21:42Z Storage Type raft HA Enabled true
Inicializácia Openbao clustra
Pre inicializáciu clustra, spustíme na node bao01 príkaz: bao operator init
Výstupu bude obsahovať kľúče pre unseal a root token. Všetky kľúče a token si starostlivo uschovajte.
cytroon@bao01:~$ bao operator init Unseal Key 1: OHe0C+........................6zYdkprFUHs8sd Unseal Key 2: iErxIguEe0b7Zji.......................dkprFf Unseal Key 3: tOMCGO682...................OXLMbem5/RsXPZts Unseal Key 4: WEKzNB8kEG25SG7G..................s-9M4DkOTK Unseal Key 5: HHnifkdj..............F7jnfGdFLYpExaQglZJxk2 Initial Root Token: s.Z9Tdf...........VyscoiYR Vault initialized with 5 key shares and a key threshold of 3. Please securely distribute the key shares printed above. When the Vault is re-sealed, restarted, or stopped, you must supply at least 3 of these keys to unseal it before it can start servicing requests. Vault does not store the generated root key. Without at least 3 keys to reconstruct the root key, Vault will remain permanently sealed! It is possible to generate new unseal keys, provided you have a quorum of existing unseal keys shares. See "bao operator rotate-keys" for more information.
Teraz vykonáme unseal nodu bao01 príkazom:
bao operator unseal
Openbao nás vyzve zadať ktorýkoľvek Unseal Key, ktorý nám bol vygenerovaný pri inicializácii. Túto akciu vykonáme 3x resp. toľko krát, kým nebudeme mať
Sealed false
To, ktorý Unseal Key v poradí zadávame, nám ukazuje hodnota Unseal Progress. Výstup z tohto postupu môže vyzerať takto:
cytroon@bao01:~$ bao status Key Value --- ----- Seal Type shamir Initialized true Sealed true Total Shares 5 Threshold 3 Unseal Progress 0/3 Unseal Nonce n/a Version 2.4.3 Build Date 2025-10-22T20:21:42Z Storage Type raft HA Enabled true cytroon@bao01:~$ bao operator unseal Unseal Key (will be hidden): Key Value --- ----- Seal Type shamir Initialized true Sealed true Total Shares 5 Threshold 3 Unseal Progress 1/3 Unseal Nonce e6b4abb9-a875-6a93-739c-c44fa9878b8c Version 2.4.3 Build Date 2025-10-22T20:21:42Z Storage Type raft HA Enabled true cytroon@bao01:~$ bao operator unseal Unseal Key (will be hidden): Key Value --- ----- Seal Type shamir Initialized true Sealed true Total Shares 5 Threshold 3 Unseal Progress 2/3 Unseal Nonce e6b4abb9-a875-6a93-739c-c44fa9878b8c Version 2.4.3 Build Date 2025-10-22T20:21:42Z Storage Type raft HA Enabled true cytroon@bao01:~$ bao operator unseal Unseal Key (will be hidden): Key Value --- ----- Seal Type shamir Initialized true Sealed false Total Shares 5 Threshold 3 Version 2.4.3 Build Date 2025-10-22T20:21:42Z Storage Type raft Cluster Name vault-cluster-10fca6aa Cluster ID 95ccea94-6468-07cc-77c1-cdff24814aed HA Enabled true HA Cluster n/a HA Mode standby Active Node Address <none> Raft Committed Index 27 Raft Applied Index 27 cytroon@bao01:~$
Keď sa nám úspešne podarilo urobiť unseal nodu bao01, môžeme pridať nody bao02 a bao03 k bao01 a tak vytvoriť cluster.
bao operator raft join http://10.100.1.41:8200"
Ak by bol na bao01 status Sealed stále TRUE, pridanie nodu skončí s chybou:
cytroon@bao02:~$ bao operator raft join http://10.100.1.41:8200 Error joining the node to the Raft cluster: Error making API request. URL: POST http://127.0.0.1:8200/v1/sys/storage/raft/join Code: 500. Errors: * failed to join raft cluster: failed to get raft challenge
Po úspešnom pridaní ďalšieho nodu budeme oboznámení potvrdzujúcim hlásením:
cytroon@bao02:~$ bao operator raft join http://10.100.1.41:8200 Key Value --- ----- Joined true cytroon@bao02:~$
Po pridaní všetkých zvyšných nodeov, ich treba postupne unseal. Či ich openbao vidí ako plnohodnotných členov clustra, skontrolujeme príkazom na node bao01:
cytroon@bao01:~$ export BAO_TOKEN='s.Z9Tdf...........VyscoiYR' cytroon@bao01:~$ bao operator raft list-peers Node Address State Voter ---- ------- ----- ----- bao01 10.100.1.41:8201 leader true bao02 10.100.1.42:8201 follower true bao03 10.100.1.43:8201 follower true
Poznámka: Pre tento úkon, už potrebujeme root token, ktorý bol vygenerovaný pri inicializácii clustra.
Týmto úkonom sme overili, že všetky nody sú členmi clustra. A čo je to teda ten Raft? :-)
Raft je distribuovaný konsenzuálny algoritmus, ktorý OpenBao používa na to, aby mali všetky nody v clustri rovnaký a konzistentný stav dát (storage backend). Nahrádza potrebu externých databáz ako Consul.
Raft zabezpečuje tri hlavné veci:
- Voľba lídra (leader election) – V clustri je vždy zvolený jeden leader, ktorý prijíma zápisy. Ostatné nody sú followers.
- Replikácia logu – Každý zápis (napr. vytvorenie secretu, zmena konfigurácie) ide najprv do leadera a ten ho replikuje na ostatné nody. Zápis je platný až keď väčšina (quorum) nodov potvrdí prijatie.
- Odolnosť voči výpadkom (fault tolerance) – Cluster môže fungovať aj pri výpadku menšiny nodov (napr. 3-node cluster vydrží výpadok 1 nodu). Pri výpadku leadera zvyšné nody automaticky zvolia nového.
Konfigurácia HAProxy
Čo robí v našom prostredí HAProxy:
- Smeruje klientov vždy na aktuálneho leadera – Sleduje /v1/sys/health na každom node a automaticky vyberá ten, ktorý je „leader = true“.
- Skryje internú topológiu clustra – Klienti sa pripájajú na jednu IP/URL, nie na konkrétny node.
- Zabezpečí vysokú dostupnosť pre API – Ak leader padne, HAProxy ho prestane používať a presmeruje traffic na nový leader bez potreby meniť konfiguráciu klientov.
- Chráni cluster pred chybnými požiadavkami – Vie robiť healthchecks a odstraňovať nefunkčné nody z rotácie.
Konfigurácia HAProxy je v našom prípade jednoduchá. Stačí na každom node editovať haproxy.cfg (sudo nano /etc/haproxy/haproxy.cfg) nasledovne:
global
maxconn 4096
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE->
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 10s
timeout client 5s
timeout server 10s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend openbao_front
bind *:9200
default_backend openbao_leader
backend openbao_leader
balance roundrobin
option httpclose
option httpchk GET /v1/sys/health
http-check expect status 200
default-server inter 2s fall 3 rise 3
server node1 10.100.1.41:8200 check
server node2 10.100.1.42:8200 check
server node3 10.100.1.43:8200 check
…a potom už len:
sudo systemctl restart haproxy sudo systemctl enable haproxy
Konfigurácia Keepalived
Keepalived poskytuje virtuálnu IP (VIP), ktorá sa automaticky presúva medzi HAProxy uzlami:
- Zjednotený entry-point pre klientov – VIP = jedna IP adresa, ktorú používame v BAO_ADDR, systemd jednotkách, CI/CD, PKI integráciách…
- Failover medzi HAProxy inštanciami – Ak vypadne HAProxy na node A, VIP sa automaticky presunie na node B. Klienti si nič nevšimnú.
- Eliminuje single point of failure na úrovni proxy – Aj keby OpenBao cluster bežal, bez Keepalived by výpadok jedného HAProxy znamenal výpadok API.
Pre konfiguráciu Keepalived máme tiež samostatný konfiguračný súbor (/etc/keepalived/keepalived.conf), no na rozdiel od haproxy, bude mat na každom node rôzne parametre.
bao01
vrrp_instance OPENBAO_VIP {
state MASTER
interface ens192
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
10.100.1.44/24
}
}
bao02
vrrp_instance OPENBAO_VIP {
state BACKUP
interface ens192
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
10.100.1.44/24
}
}
bao03
vrrp_instance OPENBAO_VIP {
state BACKUP
interface ens192
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
10.100.1.44/24
}
}
Po úprave konfiguračných súborov, stačí aj tu už len povoliť a naštartovať službu:
sudo systemctl enable keepalived sudo systemctl start keepalived
Pre overenie, kde sa aktuálne nachádza VIP, použijeme príkaz: ip a | grep 10.100.1.44
Testovanie HA
Zmena premennej BAO_ADDR na VIP a vylistovanie status openbao clustra:
cytroon@bao01:~$ export BAO_ADDR=http://10.100.1.44:8200 cytroon@bao01:~$ bao status Key Value --- ----- Seal Type shamir Initialized true Sealed false Total Shares 5 Threshold 3 Version 2.4.3 Build Date 2025-10-22T20:21:42Z Storage Type raft Cluster Name vault-cluster-10fca6aa Cluster ID 95ccea94-6468-07cc-77c1-cdff24814aed HA Enabled true HA Cluster https://10.100.1.41:8201 HA Mode active Active Since 2025-11-16T00:19:22.052223588Z Raft Committed Index 34 Raft Applied Index 34 cytroon@bao01:~$
Presun VIP na bao02 (na bao02 preto, lebo v konfigurácii má bao02 druhé najvyššie číslo prority):
Na bao01 zastavíme službu keepalived: sudo systemctl stop keepalived a na bao02 skontrolujeme prítomnosť VIP: ip a | grep 10.100.1.44
Úplný test HA:
- sudo shutdown now na bao01
- prihásime sa na bao02 a následne skontrolujeme kto je leadrom
cytroon@bao02:~$ export BAO_TOKEN='s.Z9Tdf...........VyscoiYR' cytroon@bao02:~$ bao operator raft list-peers Node Address State Voter ---- ------- ----- ----- bao01 10.100.1.41:8201 follower true bao02 10.100.1.42:8201 leader true bao03 10.100.1.43:8201 follower true
- na bao02 skontrolujeme, či sa presunula aj VIP
cytroon@bao02:~$ ip a | grep 10.100.1.44 inet 10.100.1.44/24 scope global secondary proto 0x12 ens192
Po obnovení komunikácie bao01 je nutné tento node zase unseal. (Existuje možnosť, ako nody po reštarte unsealnuť automaticky, ale to si vysvetlíme v niektorom z ďalších článkov.) Po obnovení sa na bao01 presunie VIP (kvôli nastavenej priorite) ale master node (bao02) na to nemá dôvod.
A tak: HAProxy na bao01, kde je aktuálna VIP, zistí, že leaderom je bao02, a tak komunikáciu presmeruje na bao02.
Záver
Na záver by som chcel dodať, že konfiguráciu operačného systému, haproxy a keepalived si pred presunutím do prevádzky nechajte skontrolovať skúsenými linuxovými a bezpečnostnými špecialistami. Bezpečnosť je v tomto prípade obzvlašť dôležitá.
Súvisiace články:
OpenBao – centrálna správa, uchovávanie a distribúcia citlivých dát













