概要
Linuxの機能で提供されているKeepAlivedを使用すれば、本格的なLBがなくても冗長の構成をとることができる。今回はそれを使用して冗長構成と監視体制を作るところまで行う。
環境
- OS:AlmaLinux 9.6
- unbound:1.16.2
- keepalived:v2.2.8
- 監視
- zabbix-server:7.0LTS
- zabbix-agent:7.0.21
作成方法。
今回、2台のサーバにはそれぞれDNSで名前解決するようのIPを保有しているものとする。OSのセットアップ方法自体の記載はここでは省略。
unboundのインストール
2台のサーバで以下のコマンドを実行
sudo dnf install unbound
sudo vi /etc/unbound/unbound.conf
unbound.confに、
- DNS用のインターフェースとして使用するIPを記載する。(VIPと実IP含める。)
- 面倒なら
interface: 0.0.0.0のコメントアウトだけでよい
- 面倒なら
- access-controlに名前解決を許可するIPをつける。
#interface: 0.0.0.0
以下を追記
interface: 127.0.0.1
access-control: 許可するセグメント allow
access-control: 127.0.0.0/8 allow
sudo systemctl restart unbound-keygen
その後、コンフィグを確認する、
sudo unbound-checkconf
unbound-checkconf: no errors in /etc/unbound/unbound.conf と表示されれば問題なし。
sudo systemctl enable --now unbound
その後、動作確認をする。
dig @localhost google.com
dig @localhost google.com
; <<>> DiG 9.16.23-RH <<>> @localhost google.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34268
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;google.com. IN A
;; ANSWER SECTION:
google.com. 294 IN A 142.250.207.14
;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Dec 02 16:36:23 JST 2025
;; MSG SIZE rcvd: 55
余談
ちなみに、'access-control:'の部分に、許可するクライアントのIPアドレスを設定していない場合は、以下のようにRefusedされる。(access-control: セグメント allowをつけ忘れていた)
dig @xxxxxxgoogle.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 47424
;; flags: qr rd ad; QUERY: 0, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; Query time: 2 msec
;; SERVER: xxxxxxx#53(xxxxxx)
;; WHEN: Tue Dec 02 16:38:15 JST 2025
;; MSG SIZE rcvd: 12
keepalivedの設定手順
両方のサーバで以下を実行
sudo dnf install -y keepalived
また、VRRPのfirewalldを許可しておく。
sudo firewall-cmd --add-protocol=vrrp --permanent
また、DNSとkeepalivedのfirewalldを許可する。ここはtrusted等、各々好きな方法で入れ込むこと。
sudo firewall-cmd --permanent --zone=public --add-service=dns
sudo nmcli con mod nic名 connection.zone public
sudo firewall-cmd --runtime-to-permanent
sudo firewall-cmd --permanent \
--zone=public \
--add-rich-rule='rule family="ipv4" source address="許可セグメント" port port="53" protocol="udp" accept'
sudo firewall-cmd --permanent \
--zone=public \
--add-rich-rule='rule family="ipv4" source address="許可セグメント" port port="53" protocol="tcp" accept'
VRRPのzoneによる許可は以下の通り
sudo firewall-cmd --permanent \
--zone=public-enp1s0f1 \
--add-rich-rule='rule family="ipv4" source address="許可セグメント" protocol value="vrrp" accept'
反映させる。
sudo firewall-cmd --reload
richルールの設定確認(zone=publicの場合)
sudo firewall-cmd --zone=public --list-rich-rules
設定ファイルの変更
まずは以下のコマンドでバックアップを取得する。
sudo cp -p /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bk
その後、設定ファイルに変更を行う。
sudo vi /etc/keepalived/keepalived.conf
MASTER側
- vrrp_strictを削除する。
- interface enp1s0f1
- auth_pass 1204
- デフォルトは1111だった。
- virtual_ipaddress
- (VIPに使用するIP)
- priority 100
- MASTER側はBACKUP側より大きくする必要がある。
- virtual_serverの部分は、今回使わないので消す。(見やすくするため)
- vrrp_scriptの設定を入れる
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_unbound {
script "/etc/keepalived/check-unbound-status.sh"
interval 5
timeout 1
fall 2
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface enp1s0f1
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1204
}
virtual_ipaddress {
VIPのIPアドレス
}
track_script {
chk_unbound
}
}
BACKUP側
- vrrp_strictを削除する。
- interface enp1s0f1
- auth_pass 1204
- デフォルトは1111だった。
- virtual_ipaddress
- (VIPに使用するIP)
- priority 80
- MASTER側はBACKUP側より大きくする必要がある
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_unbound {
script "/etc/keepalived/check-unbound-status.sh"
interval 5
timeout 1
fall 2
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface enp1s0f1
virtual_router_id 51
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1204
}
virtual_ipaddress {
2VIPになるIP
}
track_script {
chk_unbound
}
}
起動
MASTER側で先に起動させる。
sudo systemctl start keepalived
sudo systemctl enable keepalived.service
その後、IPがついているか否かを確認する。
ip -4 a
今回は、enp1s0f1に割り当てられる事を確認できる。
[jst-dito@office-keepalived-test ~]$ ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: enp1s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
inet 10.26.245.131/16 brd 10.26.255.255 scope global noprefixroute enp1s0f0
valid_lft forever preferred_lft forever
3: enp1s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
inet 192.168.161.0/24 brd 192.168.161.255 scope global noprefixroute enp1s0f1
valid_lft forever preferred_lft forever
inet VIPで使用するIP/32 scope global enp1s0f1
valid_lft forever preferred_lft forever
[jst-dito@office-keepalived-test ~]$
この時、pingを打ってみても、応答が帰ることを確認済み。
BACKUP側でも同じように起動させる。
sudo systemctl start keepalived
sudo systemctl enable keepalived.service
その後、IPがついているか否かを確認する。
ip -4 a
BACKUP側には存在しないことを確認できる。
FAILOVER
公式ドキュメントを確認する限り、意図してフェイルオーバーを切り替えるコマンドはないようだ。
sudo systemctl stop keepalived
シャットダウンさせるのであれば、そのままシャットダウンさせる。
これだけでip -4 a等で確認すると、IPが切り替わるのも確認できる。
priemptについて。
上記のままの設定の場合で、そのままoffice-keepalived-test(MASTER側)から
sudo systemctl start keepalived
を実行して立ち上げた場合、IPアドレスはMASTER側に移動する。
*つまり、priorityの高い方が原則的にIPアドレスを持つようだ。
余談。VirtualServerについて
KeepAlivedには、VRRPでVIPを作る機能と、LBとしてふるまう機能の2つがある。
下の方にvirtual_server IP {}と定義されている部分のことである。これは、VRRPでVIPだけ作りたい場合はなくても問題ない。
以下の設定の場合、
- 192.168.200.100 443 というVIPで待ち受け、
- 本物のサーバ 192.168.201.100 443に割り当てる
という挙動を取っている。SSL_GET{ }の部分がヘルスチェックになっている。
- lb_algoは誘導方式で、rrはラウンドロビン
- lb_kindは通信の転送方式。
- NATなら、NATして転送。
- DRなら、ダイレクトルーティングになる。
virtual_server 192.168.200.100 443 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
real_server 192.168.201.100 443 {
weight 1
SSL_GET {
url {
path /
digest ff20ad2481f97b1754ef3e12ecd3a9cc
}
url {
path /mrtg/
digest 9b3a0c85a887a256d6939da88aabd8cd
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
ヘルスチェックについて
unboundのヘルスチェック
しかしこの状態だと、VRRPの切り替わり判定が、
グローバルIPへの疎通性が取れなくなった時しか起こらないため、unboundがダウンしてしまった場合には自動でIPは切り替わってくれない
公式ドキュメントには、スクリプトの実行部分を定義してそれを組み込むようだ。
スクリプトの作成
以下のコマンドと内容で作成する。
sudo vi /etc/keepalived/check-unbound-status.sh
タイムアウトを1秒、再試行回数1回と定義し、自身を使用してlocalhostへの名前解決をする。コマンド実行結果「0,1」を判断する。単純なshell。
#!/bin/bash
if /usr/bin/dig @127.0.0.1 localhost. SOA +time=1 +tries=1 +short | grep -q .; then
exit 0
else
exit 1
fi
このshellに実行権を追加する。
sudo chmod +x /etc/keepalived/check-unbound-status.sh
もう既に上の部分でコンフィグに定義してしまっているが、一応パラメータを解説する。
| 項目 | 設定値 | 説明 |
|---|---|---|
| interval | 5 | スクリプトの実行間隔(秒)。 この設定では 5秒に1回 スクリプトを実行する。 |
| timeout | 1 | スクリプトのタイムアウト時間(秒)。 1秒以内に終了しない場合は異常と判定される。 |
| fall | 2 | 異常判定までの連続失敗回数。 2回連続で失敗すると異常と判断される。 |
| rise | 2 | 復旧判定までの連続成功回数。 2回連続で成功すると復旧と判断される。 |
vrrp_script chk_unbound {
script "/etc/keepalived/check-unbound-status.sh"
interval 5
timeout 1
fall 2
rise 2
}
unboundのステータスをダウンアップしたりすると、切り替わるることを確認できる。
sudo systemctl stop unbound
VIPの監視
VIPが意図せずに切り替わっていたり、戻し忘れをしてしまったときの監視を検知する方法をここでは考える。
検証方法は、Zabbix-agent2を用いるものとする。まずは以下の手順でzabbix-agent2をインストールする。
zabbix-agent2のインストール
epelで提供されるzabbix関連パッケージを無効にする
sudo vi /etc/yum.repos.d/epel.repo
[epel]
xxxx
excludepkgs=zabbix*
zabbixのリポジトリを追加してzabbix-agent2をインストール
sudo rpm -Uvh https://repo.zabbix.com/zabbix/7.0/alma/9/x86_64/zabbix-release-latest-7.0.el9.noarch.rpm
sudo dnf clean all
sudo dnf install zabbix-agent2
設定ファイルの変更
※下記、[proxy IP] は各拠点のIPアドレスを指定すること。ここでは10.26.7.62。また、ZabbixServer自体のIPも追加する。Server=10.26.7.62,10.26.7.47
sudo sed -i -e "s/^Server=.*/Server=[proxy IP]/" /etc/zabbix/zabbix_agent2.conf
sudo sed -i -e "s/^ServerActive=.*/ServerActive=[proxy IP]/" /etc/zabbix/zabbix_agent2.conf
sudo sed -i -e "s/^Hostname=.*/Hostname=`hostname --short`/g" /etc/zabbix/zabbix_agent2.conf
その後、今回Zabbix-agent2のrun機能を使用したいため、以下の内容を記載
sudo vi /etc/zabbix/zabbix_agent2.conf
AllowKey=system.run[*]
zabbix-agent2の起動・自動起動設定
sudo systemctl restart zabbix-agent2
sudo systemctl enable zabbix-agent2
なお、firewalldはzabbixプロキシ(zabbixサーバ)のIPを許可しているものとする。
sudo firewall-cmd --zone=trusted --add-source=[proxy IP]
sudo firewall-cmd --runtime-to-permanent
Zabbix側での設定
ホストの登録を行う。ここでは登録方法については省略する。その後、アイテムの作成を行う。
今回は、
- VIPのアドレスの有無
- Keepalived.confの中身
3.MASTERかSTANDBYか見る。
を取得する。
アイテムがMASTERかつ、VIPが存在する場合はOK、BACKUPの場合は特に何も表示しない。
というような内容のトリガーを設定する。
まず、コンフィグを取得するアイテムを用意する。

次に、保存前処理を用いてコンフィグからMASTERかBACKUPかを判定するアイテムを作成する。


これでテストして、MASTERかBACKUPか判定可能。
次に、アドレスの検索結果からVIPを確認するアイテムを作成する。VIPはマクロで指定するようにする。

アドレスが存在したらvip-existsを、失敗したらvip-not-existsを返すようにしている。

最後にトリガーを作成する。
- MASTERである。
- ipの有無チェックで正常に値が帰ってこない
最終テスト
テンプレートを対象ホストに適応させる。その後、
- $VIP_ADDRESS
を、ホストのマクロに指定してあげる。今回はVIPとなるIPアドレスを指定する。

keepaliveのサービスを落として、VIPの切り替わりを行ったところ、トリガーから発砲されたことを確認できた。

その後再度VIPのステータスを元に戻すと、無事に解決されたことを確認できた。
参考サイト
