0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KeepalivedのVRRPで、dnsキャッシュサーバを冗長させる

0
Posted at

概要

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等、各々好きな方法で入れ込むこと。

zone publicの場合のDNSサービス許可。
sudo firewall-cmd --permanent --zone=public --add-service=dns
sudo nmcli con mod nic名 connection.zone public
sudo firewall-cmd --runtime-to-permanent
richルールでDNSをIPセグメントで許可
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の設定を入れる
MASTER側keepalived.conf
! 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側より大きくする必要がある
BACKUP側keepalived.conf
! 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だけ作りたい場合はなくても問題ない。
以下の設定の場合、

  1. 192.168.200.100 443 というVIPで待ち受け、
  2. 本物のサーバ 192.168.201.100 443に割り当てる
    という挙動を取っている。SSL_GET{ }の部分がヘルスチェックになっている。
  • lb_algoは誘導方式で、rrはラウンドロビン
  • lb_kindは通信の転送方式。
    • NATなら、NATして転送。
    • DRなら、ダイレクトルーティングになる。
今回全て消した、virtualserverの部分
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。

check-unbound-status.sh
#!/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側での設定

ホストの登録を行う。ここでは登録方法については省略する。その後、アイテムの作成を行う。

今回は、

  1. VIPのアドレスの有無
  2. Keepalived.confの中身
    3.MASTERかSTANDBYか見る。
    を取得する。

アイテムがMASTERかつ、VIPが存在する場合はOK、BACKUPの場合は特に何も表示しない。

というような内容のトリガーを設定する。
まず、コンフィグを取得するアイテムを用意する。

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

これでテストして、MASTERかBACKUPか判定可能。

次に、アドレスの検索結果からVIPを確認するアイテムを作成する。VIPはマクロで指定するようにする。
image.png

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

最後にトリガーを作成する。

  • MASTERである。
  • ipの有無チェックで正常に値が帰ってこない

という場合にトリガーが発砲される。
image.png

最終テスト

テンプレートを対象ホストに適応させる。その後、

  • $VIP_ADDRESS

を、ホストのマクロに指定してあげる。今回はVIPとなるIPアドレスを指定する。
image.png

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

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

参考サイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?